Browse Source

adding users delete, change table for users

master
HerrHase 3 years ago
parent
commit
c413e8be65
17 changed files with 813 additions and 289 deletions
  1. +1
    -0
      mix-manifest.json
  2. +8
    -28
      package-lock.json
  3. +1
    -1
      package.json
  4. +93
    -0
      public/css/OFL.txt
  5. +385
    -76
      public/css/index.css
  6. +33
    -16
      public/js/bucket-single.js
  7. +26
    -9
      public/js/create-bucket.js
  8. +14
    -14
      public/js/dashboard.js
  9. +103
    -49
      public/js/users.js
  10. +21
    -4
      resources/js/components/field-error.riot
  11. +20
    -0
      resources/js/components/sidebar-button.riot
  12. +57
    -10
      resources/js/components/users.riot
  13. +20
    -6
      resources/js/components/users/form.riot
  14. +0
    -4
      resources/scss/_container.scss
  15. +0
    -68
      resources/scss/components/_sidebar.scss
  16. +1
    -3
      resources/scss/index.scss
  17. +30
    -1
      src/http/api/users.ts

+ 1
- 0
mix-manifest.json View File

@ -15,5 +15,6 @@
"/public/css/IBMPlexMono.ttf": "/public/css/IBMPlexMono.ttf", "/public/css/IBMPlexMono.ttf": "/public/css/IBMPlexMono.ttf",
"/public/css/IBMPlexMono.woff": "/public/css/IBMPlexMono.woff", "/public/css/IBMPlexMono.woff": "/public/css/IBMPlexMono.woff",
"/public/css/IBMPlexMono.woff2": "/public/css/IBMPlexMono.woff2", "/public/css/IBMPlexMono.woff2": "/public/css/IBMPlexMono.woff2",
"/public/css/OFL.txt": "/public/css/OFL.txt",
"/public/css/stylesheet.css": "/public/css/stylesheet.css" "/public/css/stylesheet.css": "/public/css/stylesheet.css"
} }

+ 8
- 28
package-lock.json View File

@ -6,7 +6,7 @@
"": { "": {
"license": "GPL", "license": "GPL",
"dependencies": { "dependencies": {
"@tentakelfabrik/plain-ui": "^0.1.0",
"@tentakelfabrik/plain-ui": "^0.2.0",
"@tentakelfabrik/tiny-validator": "^2.0.0", "@tentakelfabrik/tiny-validator": "^2.0.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"lodash.remove": "^4.7.0", "lodash.remove": "^4.7.0",
@ -1883,9 +1883,9 @@
} }
}, },
"node_modules/@tentakelfabrik/plain-ui": { "node_modules/@tentakelfabrik/plain-ui": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@tentakelfabrik/plain-ui/-/plain-ui-0.1.0.tgz",
"integrity": "sha512-43DPKQw+rr42RRdfURr6beJPUemG2PrK+/fcwVR0X4pnlTbE4VMXeYx80LgcBH2ebYYabl3Lc0cbt2MLkSDbOQ==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@tentakelfabrik/plain-ui/-/plain-ui-0.2.0.tgz",
"integrity": "sha512-h45qve6Jn8/QcoQrQpr5zUaeoh8owL6X94QiR41S78BcKQtfGkycwfJCYVLmGtN1PhKUXwXM3l6FS4r/zRqNdw==",
"dependencies": { "dependencies": {
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"reflex-grid": "^2.0.7" "reflex-grid": "^2.0.7"
@ -4929,20 +4929,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true "dev": true
}, },
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": { "node_modules/function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -8070,6 +8056,7 @@
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
"deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=0.4.x" "node": ">=0.4.x"
@ -11862,9 +11849,9 @@
} }
}, },
"@tentakelfabrik/plain-ui": { "@tentakelfabrik/plain-ui": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@tentakelfabrik/plain-ui/-/plain-ui-0.1.0.tgz",
"integrity": "sha512-43DPKQw+rr42RRdfURr6beJPUemG2PrK+/fcwVR0X4pnlTbE4VMXeYx80LgcBH2ebYYabl3Lc0cbt2MLkSDbOQ==",
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@tentakelfabrik/plain-ui/-/plain-ui-0.2.0.tgz",
"integrity": "sha512-h45qve6Jn8/QcoQrQpr5zUaeoh8owL6X94QiR41S78BcKQtfGkycwfJCYVLmGtN1PhKUXwXM3l6FS4r/zRqNdw==",
"requires": { "requires": {
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"reflex-grid": "^2.0.7" "reflex-grid": "^2.0.7"
@ -14355,13 +14342,6 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true "dev": true
}, },
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": { "function-bind": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",


+ 1
- 1
package.json View File

@ -6,7 +6,7 @@
"author": "me@herr-hase.wtf", "author": "me@herr-hase.wtf",
"license": "GPL", "license": "GPL",
"dependencies": { "dependencies": {
"@tentakelfabrik/plain-ui": "^0.1.0",
"@tentakelfabrik/plain-ui": "^0.2.0",
"@tentakelfabrik/tiny-validator": "^2.0.0", "@tentakelfabrik/tiny-validator": "^2.0.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"lodash.remove": "^4.7.0", "lodash.remove": "^4.7.0",


+ 93
- 0
public/css/OFL.txt View File

@ -0,0 +1,93 @@
Copyright © 2017 IBM Corp. with Reserved Font Name "Plex"
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

+ 385
- 76
public/css/index.css View File

@ -1596,6 +1596,13 @@
* @param {Boolean} $important [false] * @param {Boolean} $important [false]
* *
*/ */
/**
* adding overlay with z-index and color
*
* @param {z-index}
* @param {color}
*
*/
/** /**
* variables * variables
* *
@ -1631,6 +1638,20 @@
* border * border
* *
*/ */
/**
* Container
*
*
* @author Björn Hase, Tentakelfabrik
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://github.com/tentakelfabrik/crispy-css
*
*/
.container--app {
max-width: 100%;
padding: 15px 30px;
}
/** /**
* normalize * normalize
* *
@ -1661,6 +1682,7 @@
--warning-contrast: #f8d9ac; --warning-contrast: #f8d9ac;
--background: #3e3e3e; --background: #3e3e3e;
--background-contrast: #ffffff; --background-contrast: #ffffff;
--background-alpha: rgba(0, 0, 0, 0.7);
--border: #3e3e3e; --border: #3e3e3e;
--border-contrast: #ffffff; --border-contrast: #ffffff;
--font-family: IBM Plex Mono, sans-serif; --font-family: IBM Plex Mono, sans-serif;
@ -2612,7 +2634,7 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
*/ */
.table { .table {
width: 100%; width: 100%;
border: 1px solid #cacaca;
border: 1px solid var(--border);
background: var(--white); background: var(--white);
} }
.table--striped tr:nth-child(even) { .table--striped tr:nth-child(even) {
@ -2621,23 +2643,27 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
.table--scroll { .table--scroll {
overflow-x: auto; overflow-x: auto;
} }
.table td {
.table__td {
color: var(--text); color: var(--text);
} }
.table td,
.table th {
.table__td, .table__th {
text-align: left; text-align: left;
border-bottom: 1px solid #cacaca;
padding: 0.5em 1.25em;
border-bottom: 1px solid var(--border);
padding: 0.25em 0.75em;
}
@media only screen and (min-width: 992px) {
.table__td, .table__th {
padding: 0.5em 1.25em;
}
} }
.table th {
.table__th {
color: white; color: white;
background-color: #3e3e3e;
background-color: var(--background);
} }
.table tr:hover {
.table--hover .table__tr:hover {
background-color: #585858; background-color: #585858;
} }
.table tr:hover td {
.table--hover .table__tr:hover .table__td {
color: white; color: white;
} }
@ -2676,6 +2702,7 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
.bar__start, .bar__main, .bar__end { .bar__start, .bar__main, .bar__end {
display: flex; display: flex;
align-self: center; align-self: center;
align-items: center;
margin-left: 0.75em; margin-left: 0.75em;
} }
.bar__start:last-child, .bar__main:last-child, .bar__end:last-child { .bar__start:last-child, .bar__main:last-child, .bar__end:last-child {
@ -2705,6 +2732,18 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.modal:before {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
transition: background-color 0.5s;
z-index: 19;
content: "";
transition: background-color 0.5s;
}
.modal__inner { .modal__inner {
position: relative; position: relative;
z-index: 21; z-index: 21;
@ -2730,24 +2769,13 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
.modal .button { .modal .button {
color: var(--text-contrast); color: var(--text-contrast);
} }
.modal:before {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
transition: background-color 0.5s;
z-index: 19;
content: "";
}
.modal--open { .modal--open {
display: flex; display: flex;
visibility: visible; visibility: visible;
transition: visibility 0s linear 0s; transition: visibility 0s linear 0s;
} }
.modal--open:before { .modal--open:before {
background: rgba(0, 0, 0, 0.87);
background-color: var(--background-alpha);
} }
.modal--open .modal__inner { .modal--open .modal__inner {
transform: scale(1); transform: scale(1);
@ -2823,6 +2851,77 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
height: 60px; height: 60px;
} }
} }
/**
* <div class="sidebar">
* <div class="sidebar__inner">
* <div class="sidebar__body">
* </div>
* <div class="sidebar__footer">
* </div>
* </div>
* </div>
*
* @author Björn Hase, Tentakelfabrik
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://gitea.com/tentakelfabrik/plain-ui
*
*/
.sidebar {
position: fixed;
z-index: 9;
top: 0;
left: 0;
width: 100%;
height: 100%;
max-width: 95%;
visibility: hidden;
transition: visibility 0s linear 0.5s;
}
.sidebar:before {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
transition: background-color 0.5s;
z-index: 9;
content: "";
transition: background-color 0.5s;
}
.sidebar__inner {
position: relative;
height: 100%;
z-index: 10;
transition: transform 0.2s;
transform: translateX(-100%);
}
.sidebar__footer {
position: fixed;
left: 0;
bottom: 0;
display: flex;
justify-content: space-between;
background: var(--background);
width: 100%;
padding: 1rem;
}
.sidebar--open {
visibility: visible;
transition: visibility 0s linear 0s;
}
.sidebar--open .sidebar__inner {
transform: translateX(0);
}
.sidebar--open:before {
background: var(--background-alpha);
}
@media only screen and (min-width: 992px) {
.sidebar {
max-width: 33%;
}
}
/** /**
* masonry * masonry
* *
@ -14355,6 +14454,10 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
color: var(--background-contrast); color: var(--background-contrast);
} }
.color-background-alpha {
color: var(--background-alpha);
}
.color-border { .color-border {
color: var(--border); color: var(--border);
} }
@ -14439,6 +14542,10 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
fill: var(--background-contrast); fill: var(--background-contrast);
} }
.fill-background-alpha {
fill: var(--background-alpha);
}
.fill-border { .fill-border {
fill: var(--border); fill: var(--border);
} }
@ -14523,6 +14630,10 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
fill: var(--background-contrast); fill: var(--background-contrast);
} }
.hover-fill-background-alpha:hover svg {
fill: var(--background-alpha);
}
.hover-fill-border:hover svg { .hover-fill-border:hover svg {
fill: var(--border); fill: var(--border);
} }
@ -14607,6 +14718,10 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
border-color: var(--background-contrast); border-color: var(--background-contrast);
} }
.border-color-background-alpha {
border-color: var(--background-alpha);
}
.border-color-border { .border-color-border {
border-color: var(--border); border-color: var(--border);
} }
@ -14691,6 +14806,10 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
background-color: var(--background-contrast); background-color: var(--background-contrast);
} }
.background-color-background-alpha {
background-color: var(--background-alpha);
}
.background-color-border { .background-color-border {
background-color: var(--border); background-color: var(--border);
} }
@ -14760,6 +14879,11 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
font-weight: bolder; font-weight: bolder;
} }
/**
* font-sizes
*
*
*/
.size-default { .size-default {
font-size: 0.9rem; font-size: 0.9rem;
} }
@ -14905,6 +15029,245 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
font-size: 2.7rem; font-size: 2.7rem;
} }
} }
/**
* white-space
*
*
*/
.white-space-normal {
white-space: normal;
}
.white-space-nowrap {
white-space: nowrap;
}
.white-space-pre {
white-space: pre;
}
.white-space-preline {
white-space: preline;
}
.white-space-preline {
white-space: pre-line;
}
.white-space-prewrap {
white-space: pre-wrap;
}
/**
* visibility
*
*
* @author Björn Hase, Tentakelfabrik
* @license http://opensource.org/licenses/MIT The MIT License
* @link https://github.com/tentakelfabrik/plain-ui-css
*
*/
/**
* display
*
*
*/
.display-block {
display: block;
}
@media only screen and (min-width: 576px) {
.display-block-xs {
display: block;
}
}
@media only screen and (min-width: 768px) {
.display-block-sm {
display: block;
}
}
@media only screen and (min-width: 992px) {
.display-block-md {
display: block;
}
}
@media only screen and (min-width: 1200px) {
.display-block-lg {
display: block;
}
}
@media only screen and (min-width: 1600px) {
.display-block-xlg {
display: block;
}
}
.display-inline {
display: inline;
}
@media only screen and (min-width: 576px) {
.display-inline-xs {
display: inline;
}
}
@media only screen and (min-width: 768px) {
.display-inline-sm {
display: inline;
}
}
@media only screen and (min-width: 992px) {
.display-inline-md {
display: inline;
}
}
@media only screen and (min-width: 1200px) {
.display-inline-lg {
display: inline;
}
}
@media only screen and (min-width: 1600px) {
.display-inline-xlg {
display: inline;
}
}
.display-inline-block {
display: inline-block;
}
@media only screen and (min-width: 576px) {
.display-inline-block-xs {
display: inline-block;
}
}
@media only screen and (min-width: 768px) {
.display-inline-block-sm {
display: inline-block;
}
}
@media only screen and (min-width: 992px) {
.display-inline-block-md {
display: inline-block;
}
}
@media only screen and (min-width: 1200px) {
.display-inline-block-lg {
display: inline-block;
}
}
@media only screen and (min-width: 1600px) {
.display-inline-block-xlg {
display: inline-block;
}
}
.display-flex {
display: flex;
}
@media only screen and (min-width: 576px) {
.display-flex-xs {
display: flex;
}
}
@media only screen and (min-width: 768px) {
.display-flex-sm {
display: flex;
}
}
@media only screen and (min-width: 992px) {
.display-flex-md {
display: flex;
}
}
@media only screen and (min-width: 1200px) {
.display-flex-lg {
display: flex;
}
}
@media only screen and (min-width: 1600px) {
.display-flex-xlg {
display: flex;
}
}
.display-inline-flex {
display: inline-flex;
}
@media only screen and (min-width: 576px) {
.display-inline-flex-xs {
display: inline-flex;
}
}
@media only screen and (min-width: 768px) {
.display-inline-flex-sm {
display: inline-flex;
}
}
@media only screen and (min-width: 992px) {
.display-inline-flex-md {
display: inline-flex;
}
}
@media only screen and (min-width: 1200px) {
.display-inline-flex-lg {
display: inline-flex;
}
}
@media only screen and (min-width: 1600px) {
.display-inline-flex-xlg {
display: inline-flex;
}
}
.display-table {
display: table;
}
@media only screen and (min-width: 576px) {
.display-table-xs {
display: table;
}
}
@media only screen and (min-width: 768px) {
.display-table-sm {
display: table;
}
}
@media only screen and (min-width: 992px) {
.display-table-md {
display: table;
}
}
@media only screen and (min-width: 1200px) {
.display-table-lg {
display: table;
}
}
@media only screen and (min-width: 1600px) {
.display-table-xlg {
display: table;
}
}
/**
* for hidden-xs etc, show https://reflexgrid.com/#visibility-helpers
*
* @TODO full integration of reflexgrid will change this part
*
*/
/**
* Visibility
*
*/
.visibility-hidden {
visibility: hidden;
}
.visibility-visible {
visibility: visible;
}
.visibility-collapse {
visibility: collapse;
}
/** /**
* *
* *
@ -14955,60 +15318,6 @@ input[type=checkbox].field-choice:checked ~ .field-switch:after {
padding: 0; padding: 0;
} }
.sidebar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
max-width: 33%;
z-index: 1;
visibility: hidden;
transition: visibility 0s linear 0.5s;
}
.sidebar__inner {
position: relative;
height: 100%;
transition: transform 0.2s;
transform: translateX(-100%);
}
.sidebar__footer {
position: fixed;
left: 0;
bottom: 0;
display: flex;
justify-content: space-between;
background: var(--background);
width: 100%;
padding: 1rem;
}
.sidebar:before {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
transition: background-color 0.5s;
z-index: 0;
content: "";
}
.sidebar--open {
visibility: visible;
transition: visibility 0s linear 0s;
}
.sidebar--open .sidebar__inner {
transform: translateX(0);
}
.sidebar--open:before {
background: rgba(0, 0, 0, 0.7);
}
.container--app {
max-width: 100%;
padding: 15px 30px;
}
.turbolinks-progress-bar { .turbolinks-progress-bar {
height: 5px; height: 5px;
background-color: var(--danger); background-color: var(--danger);


+ 33
- 16
public/js/bucket-single.js View File

@ -20,19 +20,36 @@ __webpack_require__.r(__webpack_exports__);
errors: [ errors: [
], ],
// css class for
closest: '.field-group',
},
/**
*
*
* @param {Object} props
* @param {Object} state
*
*/
onBeforeMounted(props, state)
{
if (props.closest) {
state.closest = props.closest
}
}, },
/** /**
* *
* *
* @param {Object} props [description]
* @param {Object} state [description]
* @param {Object} props
* @param {Object} state
* *
*/ */
onMounted(props, state) onMounted(props, state)
{ {
// getting parent element for entire field // getting parent element for entire field
const parent = this.root.closest('.field-group')
const parent = this.root.closest(state.closest)
// getting current element by name // getting current element by name
const element = document.querySelector('[name="' + props.name + '"]') const element = document.querySelector('[name="' + props.name + '"]')
@ -107,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div expr4="expr4" class="field-error"></div>',
'<div expr7="expr7" class="field-error"></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -118,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0; return _scope.state.errors.length > 0;
}, },
'redundantAttribute': 'expr4',
'selector': '[expr4]',
'redundantAttribute': 'expr7',
'selector': '[expr7]',
'template': template( 'template': template(
'<ul><li expr5="expr5"></li></ul>',
'<ul><li expr8="expr8"></li></ul>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -153,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr5',
'selector': '[expr5]',
'redundantAttribute': 'expr8',
'selector': '[expr8]',
'itemName': 'error', 'itemName': 'error',
'indexName': null, 'indexName': null,
@ -272,7 +289,7 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
getComponent getComponent
) { ) {
return template( return template(
'<div class="note-form"><div class="panel"><div class="panel__body"><form id="form" novalidate><input expr1="expr1" type="hidden" name="_id"/><div class="field-group"><label class="field-label">\n title\n <input type="text" class="field-text" name="title"/></label></div><div class="field-group"><label class="field-label">\n content\n <textarea name="content" class="field-text"></textarea></label></div><div class><div class="tabs"></div></div><div><button expr2="expr2" class="button"></button><button expr3="expr3" class="button" type="submit"></button></div></form></div></div></div>',
'<div class="note-form"><div class="panel"><div class="panel__body"><form id="form" novalidate><input expr9="expr9" type="hidden" name="_id"/><div class="field-group"><label class="field-label">\n title\n <input type="text" class="field-text" name="title"/></label></div><div class="field-group"><label class="field-label">\n content\n <textarea name="content" class="field-text"></textarea></label></div><div class><div class="tabs"></div></div><div><button expr10="expr10" class="button"></button><button expr11="expr11" class="button" type="submit"></button></div></form></div></div></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -283,8 +300,8 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
return _scope.state.note && _scope.state.note._id; return _scope.state.note && _scope.state.note._id;
}, },
'redundantAttribute': 'expr1',
'selector': '[expr1]',
'redundantAttribute': 'expr9',
'selector': '[expr9]',
'template': template( 'template': template(
null, null,
@ -315,8 +332,8 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
return !_scope.state.note || (_scope.state.note && !_scope.state.note._id); return !_scope.state.note || (_scope.state.note && !_scope.state.note._id);
}, },
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'redundantAttribute': 'expr10',
'selector': '[expr10]',
'template': template( 'template': template(
'\n Create\n ', '\n Create\n ',
@ -332,8 +349,8 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
return _scope.state.note && _scope.state.note._id; return _scope.state.note && _scope.state.note._id;
}, },
'redundantAttribute': 'expr3',
'selector': '[expr3]',
'redundantAttribute': 'expr11',
'selector': '[expr11]',
'template': template( 'template': template(
'\n Save\n ', '\n Save\n ',


+ 26
- 9
public/js/create-bucket.js View File

@ -20,19 +20,36 @@ __webpack_require__.r(__webpack_exports__);
errors: [ errors: [
], ],
// css class for
closest: '.field-group',
},
/**
*
*
* @param {Object} props
* @param {Object} state
*
*/
onBeforeMounted(props, state)
{
if (props.closest) {
state.closest = props.closest
}
}, },
/** /**
* *
* *
* @param {Object} props [description]
* @param {Object} state [description]
* @param {Object} props
* @param {Object} state
* *
*/ */
onMounted(props, state) onMounted(props, state)
{ {
// getting parent element for entire field // getting parent element for entire field
const parent = this.root.closest('.field-group')
const parent = this.root.closest(state.closest)
// getting current element by name // getting current element by name
const element = document.querySelector('[name="' + props.name + '"]') const element = document.querySelector('[name="' + props.name + '"]')
@ -107,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div expr4="expr4" class="field-error"></div>',
'<div expr7="expr7" class="field-error"></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -118,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0; return _scope.state.errors.length > 0;
}, },
'redundantAttribute': 'expr4',
'selector': '[expr4]',
'redundantAttribute': 'expr7',
'selector': '[expr7]',
'template': template( 'template': template(
'<ul><li expr5="expr5"></li></ul>',
'<ul><li expr8="expr8"></li></ul>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -153,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr5',
'selector': '[expr5]',
'redundantAttribute': 'expr8',
'selector': '[expr8]',
'itemName': 'error', 'itemName': 'error',
'indexName': null, 'indexName': null,


+ 14
- 14
public/js/dashboard.js View File

@ -74,7 +74,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div class="buckets"><div class="grid"><div expr12="expr12" class="col-12 col-md-4 col-xlg-3"></div></div><div class="grid"><div class="col-12"><div class="buckets__more"><button expr17="expr17" type="button" class="button">\n More\n <svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-arrow-down"/></svg></button></div></div></div></div>',
'<div class="buckets"><div class="grid"><div expr13="expr13" class="col-12 col-md-4 col-xlg-3"></div></div><div class="grid"><div class="col-12"><div class="buckets__more"><button expr18="expr18" type="button" class="button">\n More\n <svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-arrow-down"/></svg></button></div></div></div></div>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -82,11 +82,11 @@ __webpack_require__.r(__webpack_exports__);
'condition': null, 'condition': null,
'template': template( 'template': template(
'<article class="panel buckets__item"><div class="bar"><div class="bar__end w-100"><button expr13="expr13" class="button button--transparent"><svg class="icon fill-text-contrast" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-delete"/></svg></button></div></div><div class="panel__body"><a expr14="expr14"><h3 expr15="expr15" class="buckets__title"> </h3><div class="content"><p expr16="expr16"> </p></div></a></div></article>',
'<article class="panel buckets__item"><div class="bar"><div class="bar__end w-100"><button expr14="expr14" class="button button--transparent"><svg class="icon fill-text-contrast" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-delete"/></svg></button></div></div><div class="panel__body"><a expr15="expr15"><h3 expr16="expr16" class="buckets__title"> </h3><div class="content"><p expr17="expr17"> </p></div></a></div></article>',
[ [
{ {
'redundantAttribute': 'expr13',
'selector': '[expr13]',
'redundantAttribute': 'expr14',
'selector': '[expr14]',
'expressions': [ 'expressions': [
{ {
@ -102,8 +102,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr14',
'selector': '[expr14]',
'redundantAttribute': 'expr15',
'selector': '[expr15]',
'expressions': [ 'expressions': [
{ {
@ -124,8 +124,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr15',
'selector': '[expr15]',
'redundantAttribute': 'expr16',
'selector': '[expr16]',
'expressions': [ 'expressions': [
{ {
@ -145,8 +145,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr16',
'selector': '[expr16]',
'redundantAttribute': 'expr17',
'selector': '[expr17]',
'expressions': [ 'expressions': [
{ {
@ -168,8 +168,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr12',
'selector': '[expr12]',
'redundantAttribute': 'expr13',
'selector': '[expr13]',
'itemName': 'bucket', 'itemName': 'bucket',
'indexName': null, 'indexName': null,
@ -180,8 +180,8 @@ __webpack_require__.r(__webpack_exports__);
} }
}, },
{ {
'redundantAttribute': 'expr17',
'selector': '[expr17]',
'redundantAttribute': 'expr18',
'selector': '[expr18]',
'expressions': [ 'expressions': [
{ {


+ 103
- 49
public/js/users.js View File

@ -20,19 +20,36 @@ __webpack_require__.r(__webpack_exports__);
errors: [ errors: [
], ],
// css class for
closest: '.field-group',
}, },
/** /**
* *
* *
* @param {Object} props [description]
* @param {Object} state [description]
* @param {Object} props
* @param {Object} state
*
*/
onBeforeMounted(props, state)
{
if (props.closest) {
state.closest = props.closest
}
},
/**
*
*
* @param {Object} props
* @param {Object} state
* *
*/ */
onMounted(props, state) onMounted(props, state)
{ {
// getting parent element for entire field // getting parent element for entire field
const parent = this.root.closest('.field-group')
const parent = this.root.closest(state.closest)
// getting current element by name // getting current element by name
const element = document.querySelector('[name="' + props.name + '"]') const element = document.querySelector('[name="' + props.name + '"]')
@ -107,7 +124,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div expr4="expr4" class="field-error"></div>',
'<div expr7="expr7" class="field-error"></div>',
[ [
{ {
'type': bindingTypes.IF, 'type': bindingTypes.IF,
@ -118,11 +135,11 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.errors.length > 0; return _scope.state.errors.length > 0;
}, },
'redundantAttribute': 'expr4',
'selector': '[expr4]',
'redundantAttribute': 'expr7',
'selector': '[expr7]',
'template': template( 'template': template(
'<ul><li expr5="expr5"></li></ul>',
'<ul><li expr8="expr8"></li></ul>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -153,8 +170,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr5',
'selector': '[expr5]',
'redundantAttribute': 'expr8',
'selector': '[expr8]',
'itemName': 'error', 'itemName': 'error',
'indexName': null, 'indexName': null,
@ -205,6 +222,14 @@ __webpack_require__.r(__webpack_exports__);
// getting innerHtml before rendering component // getting innerHtml before rendering component
this.content = this.root.innerHTML; this.content = this.root.innerHTML;
this.root.innerHTML = ''; this.root.innerHTML = '';
if (!this.props.event) {
console.error('sidebar-button: attribute for name of custom event is missing')
}
if (!this.props.selector) {
console.error('sidebar-button: attribute for selector to send custom event is missing')
}
}, },
/** /**
@ -219,6 +244,7 @@ __webpack_require__.r(__webpack_exports__);
}, },
/** /**
* create custom event with props
* *
* @param {[type]} event * @param {[type]} event
* @return {[type]} * @return {[type]}
@ -238,11 +264,11 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<button expr0="expr0" class="button m-bottom-0" type="button"></button>',
'<button expr12="expr12" class="button m-bottom-0" type="button"></button>',
[ [
{ {
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'redundantAttribute': 'expr12',
'selector': '[expr12]',
'expressions': [ 'expressions': [
{ {
@ -301,15 +327,15 @@ __webpack_require__.r(__webpack_exports__);
}, },
handleDelete(event, bucket) {
handleDelete(event, user) {
event.preventDefault() event.preventDefault()
axios__WEBPACK_IMPORTED_MODULE_0___default().delete('/api/bucket/' + bucket._id)
axios__WEBPACK_IMPORTED_MODULE_0___default().delete('/api/users/' + user._id)
.then((response) => { .then((response) => {
// removing from buckets // removing from buckets
lodash_remove__WEBPACK_IMPORTED_MODULE_1___default()(this.state.buckets, function(b) {
return b._id === bucket._id
lodash_remove__WEBPACK_IMPORTED_MODULE_1___default()(this.state.users, function(u) {
return u._id === user._id
}) })
this.update() this.update()
@ -336,7 +362,7 @@ __webpack_require__.r(__webpack_exports__);
getComponent getComponent
) { ) {
return template( return template(
'<div class="buckets"><table class="table"><tbody><tr expr6="expr6"></tr></tbody></table><div expr10="expr10" class="grid"></div></div>',
'<div class="buckets"><table class="table"><thead><tr class="table__tr"><th class="table__th">\n Email\n </th><th class="table__th">\n Display Name\n </th><th class="table__th" colspan="2">\n Roles\n </th></tr></thead><tbody><tr expr0="expr0" class="table__tr"></tr></tbody></table><div expr5="expr5" class="grid"></div></div>',
[ [
{ {
'type': bindingTypes.EACH, 'type': bindingTypes.EACH,
@ -344,11 +370,11 @@ __webpack_require__.r(__webpack_exports__);
'condition': null, 'condition': null,
'template': template( 'template': template(
'<td expr7="expr7" class="table__td"> </td><td expr8="expr8" class="table__td"> </td><td expr9="expr9" class="table__td"> </td><td class="table__td"><button class="button button--small m-bottom-0 m-right-3"><svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-edit"/></svg></button><button class="button button--small m-bottom-0" type="button"><svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-delete"/></svg></button></td>',
'<td expr1="expr1" class="table__td"> </td><td expr2="expr2" class="table__td"> </td><td class="table__td"><div expr3="expr3"></div></td><td class="table__td right"><button class="button button--small m-bottom-0 m-right-3"><svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-edit"/></svg></button><button expr4="expr4" class="button button--small m-bottom-0" type="button"><svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-delete"/></svg></button></td>',
[ [
{ {
'redundantAttribute': 'expr7',
'selector': '[expr7]',
'redundantAttribute': 'expr1',
'selector': '[expr1]',
'expressions': [ 'expressions': [
{ {
@ -359,7 +385,7 @@ __webpack_require__.r(__webpack_exports__);
_scope _scope
) { ) {
return [ return [
_scope.user.display_name
_scope.user.email
].join( ].join(
'' ''
); );
@ -368,8 +394,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr8',
'selector': '[expr8]',
'redundantAttribute': 'expr2',
'selector': '[expr2]',
'expressions': [ 'expressions': [
{ {
@ -380,7 +406,7 @@ __webpack_require__.r(__webpack_exports__);
_scope _scope
) { ) {
return [ return [
_scope.user.email
_scope.user.display_name
].join( ].join(
'' ''
); );
@ -389,22 +415,35 @@ __webpack_require__.r(__webpack_exports__);
] ]
}, },
{ {
'redundantAttribute': 'expr9',
'selector': '[expr9]',
'type': bindingTypes.IF,
'evaluate': function(
_scope
) {
return _scope.user.roles && _scope.user.roles.indexOf('admin') >= 0;
},
'redundantAttribute': 'expr3',
'selector': '[expr3]',
'template': template(
'\n Admin\n <svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-check"/></svg>',
[]
)
},
{
'redundantAttribute': 'expr4',
'selector': '[expr4]',
'expressions': [ 'expressions': [
{ {
'type': expressionTypes.TEXT,
'childNodeIndex': 0,
'type': expressionTypes.EVENT,
'name': 'onclick',
'evaluate': function( 'evaluate': function(
_scope _scope
) { ) {
return [
_scope.user.is_admin
].join(
''
);
return (event) => { _scope.handleDelete(event, _scope.user) };
} }
} }
] ]
@ -412,8 +451,8 @@ __webpack_require__.r(__webpack_exports__);
] ]
), ),
'redundantAttribute': 'expr6',
'selector': '[expr6]',
'redundantAttribute': 'expr0',
'selector': '[expr0]',
'itemName': 'user', 'itemName': 'user',
'indexName': null, 'indexName': null,
@ -432,15 +471,15 @@ __webpack_require__.r(__webpack_exports__);
return _scope.state.maxLength > _scope.state.users.length; return _scope.state.maxLength > _scope.state.users.length;
}, },
'redundantAttribute': 'expr10',
'selector': '[expr10]',
'redundantAttribute': 'expr5',
'selector': '[expr5]',
'template': template( 'template': template(
'<div class="col-12"><div class="buckets__more"><button expr11="expr11" type="button" class="button">\n More\n <svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-arrow-down"/></svg></button></div></div>',
'<div class="col-12"><div class="buckets__more"><button expr6="expr6" type="button" class="button">\n More\n <svg class="icon" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-arrow-down"/></svg></button></div></div>',
[ [
{ {
'redundantAttribute': 'expr11',
'selector': '[expr11]',
'redundantAttribute': 'expr6',
'selector': '[expr6]',
'expressions': [ 'expressions': [
{ {
@ -567,11 +606,11 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
getComponent getComponent
) { ) {
return template( return template(
'<div class="sidebar"><div class="sidebar__inner"><div class="bar"><div class="bar__main">\n Create User\n </div><div class="bar__end"><button expr18="expr18" class="button button--transparent" type="button"><svg class="icon fill-text-contrast" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-close"/></svg></button></div></div><div class="sidebar__body"><form id="app-users-form" novalidate><div class="field-group"><label class="field-label">\n Display Name\n <input name="display_name" type="text" class="field-text"/></label><field-error expr19="expr19" name="display_name"></field-error></div><div class="field-group"><label class="field-label">\n E-Mail\n <input name="email" type="text" class="field-text"/></label><field-error expr20="expr20" name="email"></field-error></div><div class="field-group"><label class="field-label">\n Password\n <input name="password" type="password" class="field-text"/></label><field-error expr21="expr21" name="password"></field-error></div></form></div><div class="sidebar__footer"><button class="button m-bottom-0" type="submit" form="app-users-form">\n Save\n <svg class="icon fill-success p-left-3" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-check"/></svg></button><button class="button m-bottom-0" type="submit" form="app-users-form">\n Save and Close\n <svg class="icon fill-success p-left-3" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-arrow-right"/></svg></button></div></div></div>',
'<div class="sidebar"><div class="sidebar__inner"><div class="bar"><div class="bar__main">\n Create User\n </div><div class="bar__end"><button expr19="expr19" class="button button--transparent" type="button"><svg class="icon fill-text-contrast" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-close"/></svg></button></div></div><div class="sidebar__body"><form id="app-users-form" novalidate><div class="field-group"><label class="field-label">\n E-Mail\n <input name="email" type="text" class="field-text"/></label><field-error expr20="expr20" name="email"></field-error></div><div class="field-group"><label class="field-label">\n Display Name\n <input name="display_name" type="text" class="field-text"/></label><field-error expr21="expr21" name="display_name"></field-error></div><div class="field-group"><label class="field-label">\n Password\n <input name="password" type="password" class="field-text"/></label><field-error expr22="expr22" name="password"></field-error></div><div class="field-group"><label class="field-label"><input name="roles[]" type="checkbox" class="field-choice" value="admin"/><svg class="icon field-choice__unchecked" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-checkbox"/></svg><svg class="icon field-choice__checked" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-checkbox-checked"/></svg>\n Admin\n </label><field-error expr23="expr23" name="roles"></field-error></div></form></div><div class="sidebar__footer"><button class="button m-bottom-0" type="submit" form="app-users-form">\n Save\n <svg class="icon fill-success p-left-3" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-check"/></svg></button><button class="button m-bottom-0" type="submit" form="app-users-form">\n Save and Close\n <svg class="icon fill-success p-left-3" aria-hidden="true"><use xlink:href="/symbol-defs.svg#icon-arrow-right"/></svg></button></div></div></div>',
[ [
{ {
'redundantAttribute': 'expr18',
'selector': '[expr18]',
'redundantAttribute': 'expr19',
'selector': '[expr19]',
'expressions': [ 'expressions': [
{ {
@ -598,8 +637,8 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
'slots': [], 'slots': [],
'attributes': [], 'attributes': [],
'redundantAttribute': 'expr19',
'selector': '[expr19]'
'redundantAttribute': 'expr20',
'selector': '[expr20]'
}, },
{ {
'type': bindingTypes.TAG, 'type': bindingTypes.TAG,
@ -613,8 +652,8 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
'slots': [], 'slots': [],
'attributes': [], 'attributes': [],
'redundantAttribute': 'expr20',
'selector': '[expr20]'
'redundantAttribute': 'expr21',
'selector': '[expr21]'
}, },
{ {
'type': bindingTypes.TAG, 'type': bindingTypes.TAG,
@ -628,8 +667,23 @@ riot__WEBPACK_IMPORTED_MODULE_3__.mount('field-error')
'slots': [], 'slots': [],
'attributes': [], 'attributes': [],
'redundantAttribute': 'expr21',
'selector': '[expr21]'
'redundantAttribute': 'expr22',
'selector': '[expr22]'
},
{
'type': bindingTypes.TAG,
'getComponent': getComponent,
'evaluate': function(
_scope
) {
return 'field-error';
},
'slots': [],
'attributes': [],
'redundantAttribute': 'expr23',
'selector': '[expr23]'
} }
] ]
); );


+ 21
- 4
resources/js/components/field-error.riot View File

@ -12,7 +12,7 @@
* Shows errors of Validation and raise a element to * Shows errors of Validation and raise a element to
* trigger single validation of field * trigger single validation of field
* *
* <field-error name="name" nofieldupdate></field-error>
* <field-error name="name" closest="<optional>" nofieldupdate></field-error>
* *
* @author Björn Hase, Tentakelfabrik, me@tentakelfabrik.de * @author Björn Hase, Tentakelfabrik, me@tentakelfabrik.de
* *
@ -24,19 +24,36 @@
errors: [ errors: [
], ],
// css class for
closest: '.field-group',
},
/**
*
*
* @param {Object} props
* @param {Object} state
*
*/
onBeforeMounted(props, state)
{
if (props.closest) {
state.closest = props.closest
}
}, },
/** /**
* *
* *
* @param {Object} props [description]
* @param {Object} state [description]
* @param {Object} props
* @param {Object} state
* *
*/ */
onMounted(props, state) onMounted(props, state)
{ {
// getting parent element for entire field // getting parent element for entire field
const parent = this.root.closest('.field-group')
const parent = this.root.closest(state.closest)
// getting current element by name // getting current element by name
const element = document.querySelector('[name="' + props.name + '"]') const element = document.querySelector('[name="' + props.name + '"]')


+ 20
- 0
resources/js/components/sidebar-button.riot View File

@ -2,6 +2,17 @@
<button class="button m-bottom-0" type="button" onclick={ (event) => { handleClick(event) } }></button> <button class="button m-bottom-0" type="button" onclick={ (event) => { handleClick(event) } }></button>
<script> <script>
/**
* button to create customEvent and dispatch to element
*
* <app-sidebar-button event="" selector="" data={ }>
*
* </app-sidebar-button>
*
* @author Björn Hase
*
*/
export default { export default {
state: { state: {
@ -18,6 +29,14 @@
// getting innerHtml before rendering component // getting innerHtml before rendering component
this.content = this.root.innerHTML; this.content = this.root.innerHTML;
this.root.innerHTML = ''; this.root.innerHTML = '';
if (!this.props.event) {
console.error('sidebar-button: attribute for name of custom event is missing')
}
if (!this.props.selector) {
console.error('sidebar-button: attribute for selector to send custom event is missing')
}
}, },
/** /**
@ -32,6 +51,7 @@
}, },
/** /**
* create custom event with props
* *
* @param {[type]} event * @param {[type]} event
* @return {[type]} * @return {[type]}


+ 57
- 10
resources/js/components/users.riot View File

@ -1,24 +1,47 @@
<app-users> <app-users>
<div class="buckets"> <div class="buckets">
<table class="table"> <table class="table">
<thead>
<tr class="table__tr">
<th class="table__th">
Email
</th>
<th class="table__th">
Display Name
</th>
<th class="table__th" colspan="2">
Roles
</th>
</tr>
</thead>
<tbody> <tbody>
<tr each={ user in state.users }>
<td class="table__td">
{ user.display_name }
</td>
<tr class="table__tr" each={ user in state.users }>
<td class="table__td"> <td class="table__td">
{ user.email } { user.email }
</td> </td>
<td class="table__td"> <td class="table__td">
{ user.is_admin }
{ user.display_name }
</td> </td>
<td class="table__td"> <td class="table__td">
<div if={ user.roles && user.roles.indexOf('admin') >= 0 }>
Admin
<svg class="icon" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-check"></use>
</svg>
</div>
</td>
<!-- actions -->
<td class="table__td right">
<button class="button button--small m-bottom-0 m-right-3"> <button class="button button--small m-bottom-0 m-right-3">
<svg class="icon" aria-hidden="true"> <svg class="icon" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-edit"></use> <use xlink:href="/symbol-defs.svg#icon-edit"></use>
</svg> </svg>
</button> </button>
<button class="button button--small m-bottom-0" type="button">
<button class="button button--small m-bottom-0" type="button" onclick={ (event) => { handleDelete(event, user) } }>
<svg class="icon" aria-hidden="true"> <svg class="icon" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-delete"></use> <use xlink:href="/symbol-defs.svg#icon-delete"></use>
</svg> </svg>
@ -27,6 +50,29 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div class="modal">
<div class="modal__inner">
<div class="modal__title center">
<svg class="icon fill-text-contrast" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-close"></use>
</svg>
{ title }
</div>
<div class="modal__body">
{ content }
</div>
<div class="modal__footer">
<button class="button button--outline button--danger" onclick={ () => { handleConfirm(event, data) } }>
Confirm
</button>
<button class="button button--outline float-right" onclick={ (event) => { handleClose(event) } }>
Reject
</button>
</div>
</div>
</div>
<div class="grid" if={ state.maxLength > state.users.length }> <div class="grid" if={ state.maxLength > state.users.length }>
<div class="col-12"> <div class="col-12">
<div class="buckets__more"> <div class="buckets__more">
@ -39,6 +85,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<script> <script>
@ -68,15 +115,15 @@
}, },
handleDelete(event, bucket) {
handleDelete(event, user) {
event.preventDefault() event.preventDefault()
axios.delete('/api/bucket/' + bucket._id)
axios.delete('/api/users/' + user._id)
.then((response) => { .then((response) => {
// removing from buckets // removing from buckets
remove(this.state.buckets, function(b) {
return b._id === bucket._id
remove(this.state.users, function(u) {
return u._id === user._id
}) })
this.update() this.update()


+ 20
- 6
resources/js/components/users/form.riot View File

@ -19,17 +19,17 @@
<form id="app-users-form" novalidate> <form id="app-users-form" novalidate>
<div class="field-group"> <div class="field-group">
<label class="field-label"> <label class="field-label">
Display Name
<input name="display_name" type="text" class="field-text" />
E-Mail
<input name="email" type="text" class="field-text" />
</label> </label>
<field-error name="display_name"></field-error>
<field-error name="email"></field-error>
</div> </div>
<div class="field-group"> <div class="field-group">
<label class="field-label"> <label class="field-label">
E-Mail
<input name="email" type="text" class="field-text" />
Display Name
<input name="display_name" type="text" class="field-text" />
</label> </label>
<field-error name="email"></field-error>
<field-error name="display_name"></field-error>
</div> </div>
<div class="field-group"> <div class="field-group">
<label class="field-label"> <label class="field-label">
@ -38,8 +38,22 @@
</label> </label>
<field-error name="password"></field-error> <field-error name="password"></field-error>
</div> </div>
<div class="field-group">
<label class="field-label">
<input name="roles[]" type="checkbox" class="field-choice" value="admin" />
<svg class="icon field-choice__unchecked" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-checkbox"></use>
</svg>
<svg class="icon field-choice__checked" aria-hidden="true">
<use xlink:href="/symbol-defs.svg#icon-checkbox-checked"></use>
</svg>
Admin
</label>
<field-error name="roles"></field-error>
</div>
</form> </form>
</div> </div>
<div class="sidebar__footer"> <div class="sidebar__footer">
<button class="button m-bottom-0" type="submit" form="app-users-form"> <button class="button m-bottom-0" type="submit" form="app-users-form">
Save Save


+ 0
- 4
resources/scss/_container.scss View File

@ -1,4 +0,0 @@
.container--app {
max-width: 100%;
padding: 15px 30px;
}

+ 0
- 68
resources/scss/components/_sidebar.scss View File

@ -1,68 +0,0 @@
.sidebar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
max-width: 33%;
z-index: 1;
visibility: hidden;
transition: visibility 0s linear 0.5s;
&__body {
@extend .panel__body;
}
&__inner {
@extend .panel;
position: relative;
height: 100%;
transition: transform 0.2s;
transform: translateX(-100%);
}
&__footer {
position: fixed;
left: 0;
bottom: 0;
display: flex;
justify-content: space-between;
background: var(--background);
width: 100%;
padding: 1rem;
}
&:before {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: transparent;
transition: background-color 0.5s;
z-index: 0;
content: "";
}
&--open {
visibility: visible;
transition: visibility 0s linear 0s;
.sidebar__inner {
transform: translateX(0);
}
&:before {
background: rgba(0,0,0,.7);
}
}
}

+ 1
- 3
resources/scss/index.scss View File

@ -3,9 +3,7 @@
'components/buckets', 'components/buckets',
'components/note-form', 'components/note-form',
'components/field',
'components/sidebar',
'container';
'components/field';
.turbolinks-progress-bar { .turbolinks-progress-bar {
height: 5px; height: 5px;


+ 30
- 1
src/http/api/users.ts View File

@ -2,6 +2,7 @@ import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts'
import UserRepository from '../../repositories/user.ts' import UserRepository from '../../repositories/user.ts'
import { validate, required, maxLength, isEmail } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' import { validate, required, maxLength, isEmail } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts'
import { uuid } from '../../rules/uuid.ts'
const router = Router() const router = Router()
@ -48,7 +49,7 @@ router.post('/', async function(request, response)
user = await userRepository.create(body) user = await userRepository.create(body)
// remove password // remove password
// @TODO make sure repository can hide variables
// @TODO make sure repository can hide variables
delete user.password delete user.password
} }
@ -57,4 +58,32 @@ router.post('/', async function(request, response)
}) })
}) })
/**
*
*
* @param request
* @param response
* @return
*
*/
router.delete('/:id', async function(request, response)
{
const userRepository = new UserRepository()
let user = false
const [ valid, errors ] = await validate(request.params, {
'_id': [ required, uuid ]
})
if (valid) {
user = userRepository.db.deleteOne({
'_id': request.params._id
})
}
response.json({
data: user
})
})
export default router export default router

Loading…
Cancel
Save