Merge pull request #237 from nextcloud/enh/navigation
Cleanup and change routes
39
.gitignore
vendored
|
@ -1,23 +1,26 @@
|
|||
.DS_Store
|
||||
.sass-cache/
|
||||
.project/
|
||||
.idea/
|
||||
build/
|
||||
css/*.map
|
||||
js/*forms.*
|
||||
js/chunks/
|
||||
js/*.svg
|
||||
nbproject/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
Thumbs.db
|
||||
yarn-error.log
|
||||
*.cmd
|
||||
*.lock
|
||||
*.iml
|
||||
vendor/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
composer.lock
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.suo
|
||||
.svn
|
||||
vendor/
|
||||
|
||||
.marginalia
|
||||
|
||||
build/
|
||||
coverage/
|
||||
|
||||
cypress/screenshots
|
||||
cypress/snapshots
|
||||
|
||||
# Compiled files
|
||||
js/
|
||||
|
|
|
@ -24,14 +24,15 @@
|
|||
return [
|
||||
'routes' => [
|
||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'page#goto_form', 'url' => '/form/{hash}', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'page#create_form', 'url' => '/new', 'verb' => 'GET'],
|
||||
['name' => 'page#edit_form', 'url' => '/edit/{hash}', 'verb' => 'GET'],
|
||||
['name' => 'page#clone_form', 'url' => '/clone/{hash}', 'verb' => 'GET'],
|
||||
['name' => 'page#getResult', 'url' => '/results/{id}', 'verb' => 'GET'],
|
||||
// Before /{hash} to avoid conflict
|
||||
['name' => 'page#createForm', 'url' => '/new', 'verb' => 'GET'],
|
||||
['name' => 'page#editForm', 'url' => '/{hash}/edit/', 'verb' => 'GET'],
|
||||
['name' => 'page#cloneForm', 'url' => '/{hash}/clone/', 'verb' => 'GET'],
|
||||
['name' => 'page#getResult', 'url' => '/{hash}/results/', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'page#goto_form', 'url' => '/{hash}', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'page#delete_form', 'url' => '/delete', 'verb' => 'POST'],
|
||||
['name' => 'page#insert_vote', 'url' => '/insert/vote', 'verb' => 'POST'],
|
||||
['name' => 'page#search', 'url' => '/search', 'verb' => 'POST'],
|
||||
['name' => 'page#get_display_name', 'url' => '/get/displayname', 'verb' => 'POST'],
|
||||
|
@ -42,10 +43,10 @@ return [
|
|||
['name' => 'api#get_votes', 'url' => '/get/votes/{formId}', 'verb' => 'GET'],
|
||||
['name' => 'api#get_shares', 'url' => '/get/shares/{formId}', 'verb' => 'GET'],
|
||||
['name' => 'api#get_event', 'url' => '/get/event/{formId}', 'verb' => 'GET'],
|
||||
['name' => 'api#remove_form', 'url' => '/forms/{id}', 'verb' => 'DELETE'],
|
||||
['name' => 'api#get_forms', 'url' => '/get/forms', 'verb' => 'GET'],
|
||||
|
||||
['name' => 'api#newForm', 'url' => 'api/v1/form', 'verb' => 'POST'],
|
||||
['name' => 'api#deleteForm', 'url' => 'api/v1/form/{id}', 'verb' => 'DELETE'],
|
||||
|
||||
['name' => 'system#get_site_users_and_groups', 'url' => '/get/siteusers', 'verb' => 'POST'],
|
||||
]
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
$bg-no: #ffede9;
|
||||
$bg-maybe: #fcf7e1;
|
||||
$bg-unvoted: #fff4c8;
|
||||
$bg-yes: #ebf5d6;
|
||||
$bg-information: #b19c3e;
|
||||
|
||||
$fg-no: #f45573;
|
||||
$fg-maybe: #f0db98;
|
||||
$fg-unvoted: #f0db98;
|
||||
$fg-yes: #49bc49;
|
||||
|
||||
// Icon definitions
|
||||
@include icon-black-white('app', 'forms', 2);
|
||||
|
||||
.icon-yes {
|
||||
@include icon-color('checkmark', 'actions', $fg-yes, 1, true);
|
||||
}
|
||||
|
||||
.icon-comment-yes {
|
||||
@include icon-color('comment', 'actions', $fg-yes, 1, true);
|
||||
}
|
||||
|
||||
.icon-comment-no {
|
||||
@include icon-color('comment', 'actions', $fg-no, 1, true);
|
||||
}
|
||||
|
||||
.icon-no {
|
||||
@include icon-color('close', 'actions', $fg-no, 1, true);
|
||||
}
|
||||
|
||||
.icon-maybe {
|
||||
@include icon-color('maybe-vote-variant', 'forms', $fg-maybe);
|
||||
}
|
23
css/forms.scss
Normal file
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@import 'icons'
|
24
css/icons.scss
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
// Icon definitions
|
||||
@include icon-black-white('forms', 'forms', 3);
|
||||
@include icon-black-white('clone', 'forms', 1);
|
||||
|
||||
.icon-yes {
|
||||
@include icon-color('checkmark', 'actions', $color-success, 1, true);
|
||||
}
|
||||
|
||||
.icon-comment-yes {
|
||||
@include icon-color('comment', 'actions', $color-success, 1, true);
|
||||
}
|
||||
|
||||
.icon-comment-no {
|
||||
@include icon-color('comment', 'actions', $color-error, 1, true);
|
||||
}
|
||||
|
||||
.icon-no {
|
||||
@include icon-color('close', 'actions', $color-error, 1, true);
|
||||
}
|
||||
|
||||
.icon-maybe {
|
||||
@include icon-color('maybe-vote-variant', 'forms', $color-warning);
|
||||
}
|
214
css/sidebar.scss
|
@ -1,214 +0,0 @@
|
|||
@import 'colors.scss';
|
||||
|
||||
$border_current_user: 2px solid;
|
||||
$border_user: 1px solid var(--color-border-dark);
|
||||
$user-column-width: 265px;
|
||||
|
||||
#forms-sidebar {
|
||||
width: 520px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
min-width: 300px;
|
||||
border-left: 1px solid var(--color-border);
|
||||
transition: margin-right 300ms;
|
||||
z-index: 500;
|
||||
> div,
|
||||
> ul {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.authorRow {
|
||||
align-items: center;
|
||||
.author {
|
||||
margin-left: 8px;
|
||||
opacity: 0.5;
|
||||
flex-grow: 1;
|
||||
&.external {
|
||||
margin-right: 33px;
|
||||
opacity: 1;
|
||||
> input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detailsView {
|
||||
z-index: 1000 !important;
|
||||
.close.flex-row {
|
||||
justify-content: flex-end;
|
||||
margin: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.header.flex-row {
|
||||
flex-direction: row;
|
||||
flex-grow: 0;
|
||||
align-items: flex-start;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
padding: 0 17px;
|
||||
}
|
||||
|
||||
.formInformation {
|
||||
width: 220px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding-right: 15px;
|
||||
|
||||
.authorRow {
|
||||
.leftLabel {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.cloud {
|
||||
margin: 4px 0;
|
||||
|
||||
> span {
|
||||
color: var(--color-primary-text);
|
||||
margin: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: var(--border-radius);
|
||||
float: left;
|
||||
text-shadow: 1px 1px var(--color-box-shadow);
|
||||
background-color: var(--color-loading-light);
|
||||
}
|
||||
.open {
|
||||
background-color: $fg-yes;
|
||||
}
|
||||
.expired {
|
||||
background-color: $fg-no;
|
||||
}
|
||||
.information {
|
||||
background-color: $bg-information;
|
||||
}
|
||||
}
|
||||
}
|
||||
#expired_info {
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.formActions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 15px;
|
||||
|
||||
.close {
|
||||
margin: 15px;
|
||||
background-position: right top;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
> ul > li {
|
||||
&:focus,
|
||||
&:hover,
|
||||
&.active,
|
||||
a.selected {
|
||||
&,
|
||||
> a {
|
||||
opacity: 1;
|
||||
box-shadow: inset 4px 0 var(--color-primary);
|
||||
}
|
||||
}
|
||||
|
||||
> a[class*='icon-'],
|
||||
> ul > li > a[class*='icon-'],
|
||||
> a[style*='background-image'],
|
||||
> ul > li > a[style*='background-image'] {
|
||||
padding-left: 44px;
|
||||
}
|
||||
|
||||
> a,
|
||||
> ul > li > a {
|
||||
background-size: 16px 16px;
|
||||
background-position: 14px center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
justify-content: space-between;
|
||||
line-height: 44px;
|
||||
min-height: 44px;
|
||||
padding: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: var(--color-main-text);
|
||||
opacity: 0.57;
|
||||
flex: 1 1 0;
|
||||
z-index: 100;
|
||||
}
|
||||
a,
|
||||
.app-navigation-entry-deleted {
|
||||
padding-left: 44px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
#configurationsTabView {
|
||||
.configBox {
|
||||
padding: 8px 8px;
|
||||
|
||||
> .title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
> div {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
input.hasDatepicker {
|
||||
margin-left: 17px;
|
||||
}
|
||||
&.oneline {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
#commentsTabView {
|
||||
.newCommentForm div.message:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
color: grey;
|
||||
}
|
||||
#commentBox {
|
||||
border: 1px solid var(--color-border-dark);
|
||||
border-radius: var(--border-radius);
|
||||
padding: 7px 6px;
|
||||
margin: 3px 3px 3px 40px;
|
||||
cursor: text;
|
||||
}
|
||||
.comment {
|
||||
margin-bottom: 30px;
|
||||
|
||||
.date {
|
||||
right: 0;
|
||||
top: 5px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-left: 40px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
.new-comment {
|
||||
.submitComment {
|
||||
align-self: last baseline;
|
||||
width: 30px;
|
||||
margin: 0;
|
||||
padding: 7px 9px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.icon-loading-small {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
BIN
img/app.png
Before Width: | Height: | Size: 196 B |
|
@ -1 +1,8 @@
|
|||
<svg width="32" height="32" version="1.1" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg"><path d="m5 3a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3zm7 1c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h16c0.554 0 1-0.446 1-1v-2c0-0.554-0.446-1-1-1h-16zm-7 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3zm7 1c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h16c0.554 0 1-0.446 1-1v-2c0-0.554-0.446-1-1-1h-16zm-7 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3zm7 1c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h16c0.554 0 1-0.446 1-1v-2c0-0.554-0.446-1-1-1h-16z" fill="#fff" style="paint-order:markers fill stroke"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||
<circle cx="6" cy="6" r="3" fill="#fff"/>
|
||||
<circle cx="6" cy="16" r="3" fill="#fff"/>
|
||||
<circle cx="6" cy="26" r="3" fill="#fff"/>
|
||||
<rect width="18" height="4" x="11" y="4" rx="1" ry="1" fill="#fff"/>
|
||||
<rect width="18" height="4" x="11" y="14" rx="1" ry="1" fill="#fff"/>
|
||||
<rect width="18" height="4" x="11" y="24" rx="1" ry="1" fill="#fff"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 647 B After Width: | Height: | Size: 420 B |
1
img/clone.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M11.8 13.8H2.2V4.2h9.6m1.2 0c0-.67-.53-1.2-1.2-1.2H2.2C1.53 3 1 3.53 1 4.2v9.6c0 .67.53 1.2 1.2 1.2h9.6c.67 0 1.2-.53 1.2-1.2"/><path d="m4.2 1c-0.67 0-1.2 0.54-1.2 1.2h10.8v10.8c0.67 0 1.2-0.53 1.2-1.2v-9.6c0-0.67-0.53-1.2-1.2-1.2z"/></svg>
|
After Width: | Height: | Size: 327 B |
|
@ -1,45 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg10"
|
||||
viewBox="0 0 32 32"
|
||||
x="0px"
|
||||
y="0px"
|
||||
enable-background="new 0 0 595.275 311.111"
|
||||
width="32"
|
||||
height="32"
|
||||
xml:space="preserve"
|
||||
version="1.1"
|
||||
sodipodi:docname="favicon-mask.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1046"
|
||||
id="namedview15"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.6875"
|
||||
inkscape:cx="11.825118"
|
||||
inkscape:cy="3.2468217"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="34"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg10" /><metadata
|
||||
id="metadata16"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs14" /><path
|
||||
d="M 5 0 C 2.23 0 0 2.23 0 5 L 0 27 C 0 29.77 2.23 32 5 32 L 27 32 C 29.77 32 32 29.77 32 27 L 32 5 C 32 2.23 29.77 0 27 0 L 5 0 z M 5 3 A 3 3 0 0 1 8 6 A 3 3 0 0 1 5 9 A 3 3 0 0 1 2 6 A 3 3 0 0 1 5 3 z M 12 4 L 28 4 C 28.554 4 29 4.446 29 5 L 29 7 C 29 7.554 28.554 8 28 8 L 12 8 C 11.446 8 11 7.554 11 7 L 11 5 C 11 4.446 11.446 4 12 4 z M 5 13 A 3 3 0 0 1 8 16 A 3 3 0 0 1 5 19 A 3 3 0 0 1 2 16 A 3 3 0 0 1 5 13 z M 12 14 L 28 14 C 28.554 14 29 14.446 29 15 L 29 17 C 29 17.554 28.554 18 28 18 L 12 18 C 11.446 18 11 17.554 11 17 L 11 15 C 11 14.446 11.446 14 12 14 z M 5 23 A 3 3 0 0 1 8 26 A 3 3 0 0 1 5 29 A 3 3 0 0 1 2 26 A 3 3 0 0 1 5 23 z M 12 24 L 28 24 C 28.554 24 29 24.446 29 25 L 29 27 C 29 27.554 28.554 28 28 28 L 12 28 C 11.446 28 11 27.554 11 27 L 11 25 C 11 24.446 11.446 24 12 24 z "
|
||||
id="rect2" /></svg>
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 10 KiB |
|
@ -1 +0,0 @@
|
|||
<svg width="128" height="128" enable-background="new 0 0 595.275 311.111" version="1.1" viewBox="0 0 128 128" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="128" height="128" rx="20" ry="20" fill="#0082c9"/><path d="m20 12a12 12 0 0 0-12 12 12 12 0 0 0 12 12 12 12 0 0 0 12-12 12 12 0 0 0-12-12zm28 4c-2.216 0-4 1.784-4 4v8c0 2.216 1.784 4 4 4h64c2.216 0 4-1.784 4-4v-8c0-2.216-1.784-4-4-4zm-28 36a12 12 0 0 0-12 12 12 12 0 0 0 12 12 12 12 0 0 0 12-12 12 12 0 0 0-12-12zm28 4c-2.216 0-4 1.784-4 4v8c0 2.216 1.784 4 4 4h64c2.216 0 4-1.784 4-4v-8c0-2.216-1.784-4-4-4zm-28 36a12 12 0 0 0-12 12 12 12 0 0 0 12 12 12 12 0 0 0 12-12 12 12 0 0 0-12-12zm28 4c-2.216 0-4 1.784-4 4v8c0 2.216 1.784 4 4 4h64c2.216 0 4-1.784 4-4v-8c0-2.216-1.784-4-4-4z" fill="#fff" style="paint-order:markers fill stroke"/></svg>
|
Before Width: | Height: | Size: 824 B |
BIN
img/favicon.ico
Before Width: | Height: | Size: 4.2 KiB |
BIN
img/favicon.png
Before Width: | Height: | Size: 313 B |
|
@ -1 +0,0 @@
|
|||
<svg width="32" height="32" enable-background="new 0 0 595.275 311.111" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="32" height="32" rx="5" ry="5" fill="#0082c9"/><path d="m5 3a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3zm7 1c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h16c0.554 0 1-0.446 1-1v-2c0-0.554-0.446-1-1-1zm-7 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3zm7 1c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h16c0.554 0 1-0.446 1-1v-2c0-0.554-0.446-1-1-1zm-7 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3zm7 1c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h16c0.554 0 1-0.446 1-1v-2c0-0.554-0.446-1-1-1z" fill="#fff" style="paint-order:markers fill stroke"/></svg>
|
Before Width: | Height: | Size: 759 B |
8
img/forms.svg
Normal file
|
@ -0,0 +1,8 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32">
|
||||
<circle cx="6" cy="6" r="3" fill="#fff"/>
|
||||
<circle cx="6" cy="16" r="3" fill="#fff"/>
|
||||
<circle cx="6" cy="26" r="3" fill="#fff"/>
|
||||
<rect width="18" height="4" x="11" y="4" rx="1" ry="1" fill="#fff"/>
|
||||
<rect width="18" height="4" x="11" y="14" rx="1" ry="1" fill="#fff"/>
|
||||
<rect width="18" height="4" x="11" y="24" rx="1" ry="1" fill="#fff"/>
|
||||
</svg>
|
After Width: | Height: | Size: 420 B |
46
js/.jshintrc
|
@ -1,46 +0,0 @@
|
|||
{
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"indent": 4,
|
||||
"latedef": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"plusplus": false,
|
||||
"node": true,
|
||||
"undef": true,
|
||||
"unused": false,
|
||||
"strict": false,
|
||||
"maxparams": false,
|
||||
"maxdepth": 4,
|
||||
"esversion": 6,
|
||||
"browser": true,
|
||||
"devel": true,
|
||||
"jquery": true,
|
||||
"jasmine": true,
|
||||
"laxbreak": true,
|
||||
"globals": {
|
||||
"jQuery": true,
|
||||
"ICAL": true,
|
||||
"jstz": true,
|
||||
"moment": true,
|
||||
"angular": true,
|
||||
"app": true,
|
||||
"OC": true,
|
||||
"oc_current_user":true,
|
||||
"oc_requesttoken": true,
|
||||
"requestToken": true,
|
||||
"inject": true,
|
||||
"module": true,
|
||||
"t": true,
|
||||
"it": true,
|
||||
"exports": true,
|
||||
"escapeHTML": true,
|
||||
"possible": true,
|
||||
"dav": true,
|
||||
"hslToRgb": true,
|
||||
"autosize": true,
|
||||
"_": true
|
||||
}
|
||||
}
|
14
js/app.js
|
@ -1,14 +0,0 @@
|
|||
function deleteForm($formEl) {
|
||||
var str = t('forms', 'Do you really want to delete this new form?') + '\n\n' + $($formEl).attr('data-value');
|
||||
if (confirm(str)) {
|
||||
var form = document.form_delete_form;
|
||||
var hiddenId = document.createElement("input");
|
||||
hiddenId.setAttribute("name", "formId");
|
||||
hiddenId.setAttribute("type", "hidden");
|
||||
form.appendChild(hiddenId);
|
||||
form.elements.formId.value = $formEl.id.split('_')[2];
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -389,8 +389,9 @@ class ApiController extends Controller {
|
|||
* @NoAdminRequired
|
||||
* @param int $formId
|
||||
* @return DataResponse
|
||||
* TODO: use hash instead of id ?
|
||||
*/
|
||||
public function removeForm(int $id) {
|
||||
public function deleteForm(int $id) {
|
||||
try {
|
||||
$formToDelete = $this->eventMapper->find($id);
|
||||
} catch (DoesNotExistException $e) {
|
||||
|
@ -533,11 +534,6 @@ class ApiController extends Controller {
|
|||
|
||||
$this->eventMapper->insert($event);
|
||||
|
||||
|
||||
|
||||
return new Http\JSONResponse([
|
||||
'id' => $event->getId(),
|
||||
'hash' => $event->getHash(),
|
||||
]);
|
||||
return new Http\JSONResponse($this->getForm($event->getHash()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
* @author Inigo Jiron <ijiron@terpmail.umd.edu>
|
||||
* @author Natalie Gilbert
|
||||
* @author Affan Hussain
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
|
@ -86,40 +87,63 @@ class PageController extends Controller {
|
|||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function index(): TemplateResponse {
|
||||
return new TemplateResponse('forms', 'forms.tmpl',
|
||||
['urlGenerator' => $this->urlGenerator]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function createForm(): TemplateResponse {
|
||||
return new TemplateResponse('forms', 'forms.tmpl',
|
||||
['urlGenerator' => $this->urlGenerator]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
public function cloneForm(): TemplateResponse {
|
||||
return new TemplateResponse('forms', 'forms.tmpl',
|
||||
['urlGenerator' => $this->urlGenerator]);
|
||||
Util::addScript($this->appName, 'forms');
|
||||
Util::addStyle($this->appName, 'icons');
|
||||
return new TemplateResponse($this->appName, 'main');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param string $hash
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function editForm($hash): TemplateResponse {
|
||||
return new TemplateResponse('forms', 'forms.tmpl', [
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'hash' => $hash
|
||||
]);
|
||||
public function createForm(): TemplateResponse {
|
||||
Util::addScript($this->appName, 'forms');
|
||||
Util::addStyle($this->appName, 'icons');
|
||||
return new TemplateResponse($this->appName, 'main');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function cloneForm(): TemplateResponse {
|
||||
Util::addScript($this->appName, 'forms');
|
||||
Util::addStyle($this->appName, 'icons');
|
||||
return new TemplateResponse($this->appName, 'main');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function editForm(): TemplateResponse {
|
||||
Util::addScript($this->appName, 'forms');
|
||||
Util::addStyle($this->appName, 'icons');
|
||||
return new TemplateResponse($this->appName, 'main');
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getResult(): TemplateResponse {
|
||||
Util::addScript($this->appName, 'forms');
|
||||
Util::addStyle($this->appName, 'icons');
|
||||
return new TemplateResponse($this->appName, 'main');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -402,13 +426,4 @@ class PageController extends Controller {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param int $id
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function getResult(int $id): TemplateResponse {
|
||||
return new TemplateResponse('forms', 'forms.tmpl');
|
||||
}
|
||||
}
|
||||
|
|
326
package-lock.json
generated
|
@ -1668,6 +1668,22 @@
|
|||
"integrity": "sha512-f+sKpdLZXkODV+OY39K1M+Spmd4RgxmtEXmNn4Bviv4R7uBFHXuw+JX9ZdfDeOryfHjJ/TRQxQEp0GMpBwZFUw==",
|
||||
"dev": true
|
||||
},
|
||||
"@nextcloud/dialogs": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-1.2.2.tgz",
|
||||
"integrity": "sha512-N8A8J8UKSvz/hqNcm7gwpm70uAAsx0wurjhdYZ989jaMho+H/Hinjd2jkbV8UnsYYw0x/vWvEX5t6Lwbv08K0g==",
|
||||
"requires": {
|
||||
"core-js": "3.6.4",
|
||||
"toastify-js": "^1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "3.6.4",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
|
||||
"integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nextcloud/eslint-config": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/eslint-config/-/eslint-config-1.0.0.tgz",
|
||||
|
@ -1706,17 +1722,18 @@
|
|||
}
|
||||
},
|
||||
"@nextcloud/l10n": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-1.0.0.tgz",
|
||||
"integrity": "sha512-A6zUwFWgwvQ5q86GdcfgD2t3uZ+H/k45S0OUlS6iMf0p5br9IrovF7hdv5+jaJcdQpkpOX2AKuordC1KheNGGA==",
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-1.1.1.tgz",
|
||||
"integrity": "sha512-aVGvOhXgBzGtgMTOIVov1T7jt35FjX2vCqWCT0C/t6T6VgRn6l2Wb3/jzQycyUgGe71VPqS/4TpSH21yyH99YA==",
|
||||
"requires": {
|
||||
"core-js": "3.5.0"
|
||||
"core-js": "3.6.4",
|
||||
"node-gettext": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.5.0.tgz",
|
||||
"integrity": "sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw=="
|
||||
"version": "3.6.4",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz",
|
||||
"integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1729,6 +1746,23 @@
|
|||
"core-js": "3.6.1",
|
||||
"i18next": "19.0.2",
|
||||
"moment": "2.24.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextcloud/l10n": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/l10n/-/l10n-1.0.0.tgz",
|
||||
"integrity": "sha512-A6zUwFWgwvQ5q86GdcfgD2t3uZ+H/k45S0OUlS6iMf0p5br9IrovF7hdv5+jaJcdQpkpOX2AKuordC1KheNGGA==",
|
||||
"requires": {
|
||||
"core-js": "3.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.5.0.tgz",
|
||||
"integrity": "sha512-Ifh3kj78gzQ7NAoJXeTu+XwzDld0QRIwjBLRqAMhuLhP3d2Av5wmgE9ycfnvK6NAEjTkQ1sDPeoEZAWO3Hx1Uw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nextcloud/router": {
|
||||
|
@ -3759,6 +3793,11 @@
|
|||
"integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=",
|
||||
"dev": true
|
||||
},
|
||||
"debounce": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.0.tgz",
|
||||
"integrity": "sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
|
||||
|
@ -4421,15 +4460,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"eslint-plugin-nextcloud": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-nextcloud/-/eslint-plugin-nextcloud-0.3.0.tgz",
|
||||
"integrity": "sha512-LUD2qdirGL0BRt4uaMDGxen17mWVq9JwuGDt7P7Celz7bzdu0X48RrS8mhXn9e0w78+nYN5kPoULG2Bw04r4HA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"requireindex": "~1.2.0"
|
||||
}
|
||||
},
|
||||
"eslint-plugin-node": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz",
|
||||
|
@ -5279,22 +5309,26 @@
|
|||
"dependencies": {
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
|
||||
"optional": true
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"optional": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
|
||||
"optional": true
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.5",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
|
||||
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
|
@ -5303,12 +5337,14 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
|
@ -5317,32 +5353,38 @@
|
|||
},
|
||||
"chownr": {
|
||||
"version": "1.1.3",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz",
|
||||
"integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==",
|
||||
"optional": true
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"optional": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
|
@ -5350,22 +5392,26 @@
|
|||
},
|
||||
"deep-extend": {
|
||||
"version": "0.6.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
|
||||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"optional": true
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
|
||||
"optional": true
|
||||
},
|
||||
"detect-libc": {
|
||||
"version": "1.0.3",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
|
||||
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
|
||||
"optional": true
|
||||
},
|
||||
"fs-minipass": {
|
||||
"version": "1.2.7",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz",
|
||||
"integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minipass": "^2.6.0"
|
||||
|
@ -5373,12 +5419,14 @@
|
|||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"optional": true
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"aproba": "^1.0.3",
|
||||
|
@ -5393,7 +5441,8 @@
|
|||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
|
@ -5406,12 +5455,14 @@
|
|||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
|
||||
"optional": true
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
|
@ -5419,7 +5470,8 @@
|
|||
},
|
||||
"ignore-walk": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz",
|
||||
"integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
|
@ -5427,7 +5479,8 @@
|
|||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
|
@ -5436,17 +5489,20 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==",
|
||||
"optional": true
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
|
@ -5454,12 +5510,14 @@
|
|||
},
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||
"optional": true
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
|
@ -5467,12 +5525,14 @@
|
|||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
|
||||
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.9.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz",
|
||||
"integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
|
@ -5481,7 +5541,8 @@
|
|||
},
|
||||
"minizlib": {
|
||||
"version": "1.3.3",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
|
||||
"integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minipass": "^2.9.0"
|
||||
|
@ -5489,7 +5550,8 @@
|
|||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
|
||||
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
|
@ -5497,12 +5559,14 @@
|
|||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"optional": true
|
||||
},
|
||||
"needle": {
|
||||
"version": "2.4.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz",
|
||||
"integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"debug": "^3.2.6",
|
||||
|
@ -5512,7 +5576,8 @@
|
|||
},
|
||||
"node-pre-gyp": {
|
||||
"version": "0.14.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz",
|
||||
"integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"detect-libc": "^1.0.2",
|
||||
|
@ -5529,7 +5594,8 @@
|
|||
},
|
||||
"nopt": {
|
||||
"version": "4.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
|
||||
"integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"abbrev": "1",
|
||||
|
@ -5538,7 +5604,8 @@
|
|||
},
|
||||
"npm-bundled": {
|
||||
"version": "1.1.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz",
|
||||
"integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"npm-normalize-package-bin": "^1.0.1"
|
||||
|
@ -5546,12 +5613,14 @@
|
|||
},
|
||||
"npm-normalize-package-bin": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz",
|
||||
"integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==",
|
||||
"optional": true
|
||||
},
|
||||
"npm-packlist": {
|
||||
"version": "1.4.7",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.7.tgz",
|
||||
"integrity": "sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ignore-walk": "^3.0.1",
|
||||
|
@ -5560,7 +5629,8 @@
|
|||
},
|
||||
"npmlog": {
|
||||
"version": "4.1.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
|
@ -5571,17 +5641,20 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
|
||||
"optional": true
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
|
@ -5589,17 +5662,20 @@
|
|||
},
|
||||
"os-homedir": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
|
||||
"integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
|
||||
"optional": true
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
|
||||
"optional": true
|
||||
},
|
||||
"osenv": {
|
||||
"version": "0.1.5",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
|
||||
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
|
@ -5608,17 +5684,20 @@
|
|||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"optional": true
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"optional": true
|
||||
},
|
||||
"rc": {
|
||||
"version": "1.2.8",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
|
||||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"deep-extend": "^0.6.0",
|
||||
|
@ -5629,14 +5708,16 @@
|
|||
"dependencies": {
|
||||
"minimist": {
|
||||
"version": "1.2.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.3.6",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
|
||||
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
|
@ -5650,7 +5731,8 @@
|
|||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
|
@ -5658,37 +5740,44 @@
|
|||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"optional": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"optional": true
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"optional": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"optional": true
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
|
||||
"optional": true
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
|
||||
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
|
||||
"optional": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
|
@ -5698,7 +5787,8 @@
|
|||
},
|
||||
"string_decoder": {
|
||||
"version": "1.1.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
|
@ -5706,7 +5796,8 @@
|
|||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
|
@ -5714,12 +5805,14 @@
|
|||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||
"optional": true
|
||||
},
|
||||
"tar": {
|
||||
"version": "4.4.13",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz",
|
||||
"integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
|
@ -5733,12 +5826,14 @@
|
|||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"optional": true
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
|
@ -5746,12 +5841,14 @@
|
|||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"optional": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.1.1",
|
||||
"bundled": true,
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
|
@ -10977,6 +11074,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"toastify-js": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.7.0.tgz",
|
||||
"integrity": "sha512-GmPy4zJ/ulCfmCHlfCtgcB+K2xhx2AXW3T/ZZOSjyjaIGevhz+uvR8HSCTay/wBq4tt2mUnBqlObP1sSWGlsnQ=="
|
||||
},
|
||||
"tough-cookie": {
|
||||
"version": "2.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||
|
@ -11280,6 +11382,64 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"url-loader": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.0.0.tgz",
|
||||
"integrity": "sha512-sPsoBs8NkSJt9k/2zLUMDAf0rYaG00EtrFQpHRIphKrR6stGsO92LUJf/uUeQNKEoxqoJ4R4qDLqHl+AOEqolA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"loader-utils": "^2.0.0",
|
||||
"mime-types": "^2.1.26",
|
||||
"schema-utils": "^2.6.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ajv": {
|
||||
"version": "6.12.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
|
||||
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"emojis-list": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
||||
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
|
||||
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==",
|
||||
"dev": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.6.5",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.5.tgz",
|
||||
"integrity": "sha512-5KXuwKziQrTVHh8j/Uxz+QUbxkaLW9X/86NBlx/gnKgtsZA2GIVMUn17qWhRFwF8jdYb3Dig5hRO/W5mZqy6SQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^6.12.0",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"use": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
"main": "src/js/main.js",
|
||||
"scripts": {
|
||||
"build": "NODE_ENV=production webpack --progress --hide-modules --config webpack.prod.js",
|
||||
"dev": "NODE_ENV=development webpack --progress --watch --config webpack.dev.js",
|
||||
"dev": "NODE_ENV=development webpack --progress --config webpack.dev.js",
|
||||
"watch": "NODE_ENV=development webpack --progress --watch --config webpack.dev.js",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"lint:fix": "eslint --ext .js,.vue src --fix",
|
||||
|
@ -69,9 +69,14 @@
|
|||
"test:coverage": "jest --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^1.2.2",
|
||||
"@nextcloud/axios": "^1.3.2",
|
||||
"@nextcloud/dialogs": "^1.2.2",
|
||||
"@nextcloud/l10n": "^1.1.1",
|
||||
"@nextcloud/moment": "^1.1.0",
|
||||
"@nextcloud/router": "^1.0.2",
|
||||
"@nextcloud/vue": "^1.4.1",
|
||||
"debounce": "^1.2.0",
|
||||
"json2csv": "5.0.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
|
@ -98,7 +103,6 @@
|
|||
"eslint-import-resolver-webpack": "^0.12.1",
|
||||
"eslint-loader": "^3.0.3",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-nextcloud": "^0.3.0",
|
||||
"eslint-plugin-node": "^10.0.0",
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
|
@ -110,6 +114,7 @@
|
|||
"stylelint-config-recommended-scss": "^3.3.0",
|
||||
"stylelint-scss": "^3.16.0",
|
||||
"stylelint-webpack-plugin": "^0.10.5",
|
||||
"url-loader": "^4.0.0",
|
||||
"vue-loader": "^15.9.1",
|
||||
"vue-style-loader": "^4.1.1",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
|
|
162
src/Forms.vue
Normal file
|
@ -0,0 +1,162 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
|
||||
-
|
||||
- @author René Gieling <github@dartcafe.de>
|
||||
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<Content app-name="forms">
|
||||
<AppNavigation>
|
||||
<AppNavigationNew button-class="icon-add" :text="t('forms', 'New form')" @click="onNewForm" />
|
||||
<AppNavigationForm v-for="form in formattedForms"
|
||||
:key="form.id"
|
||||
:form="form"
|
||||
@delete="onDeleteForm" />
|
||||
</AppNavigation>
|
||||
|
||||
<!-- No forms & loading emptycontents -->
|
||||
<AppContent v-if="loading || noForms || (!hash && $route.name !== 'create')">
|
||||
<EmptyContent v-if="loading" icon="icon-loading">
|
||||
{{ t('forms', 'Loading forms …') }}
|
||||
</EmptyContent>
|
||||
<EmptyContent v-else-if="noForms">
|
||||
{{ t('forms', 'No forms in here') }}
|
||||
<template #desc>
|
||||
<button class="primary" @click="onNewForm">
|
||||
{{ t('forms', 'Create a new one') }}
|
||||
</button>
|
||||
</template>
|
||||
</EmptyContent>
|
||||
|
||||
<EmptyContent v-else>
|
||||
{{ t('forms', 'Please select a form') }}
|
||||
</EmptyContent>
|
||||
</AppContent>
|
||||
|
||||
<!-- No errors show router content -->
|
||||
<template v-else>
|
||||
<router-view :form="selectedForm" />
|
||||
<router-view :form="selectedForm" name="sidebar" />
|
||||
</template>
|
||||
</Content>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
|
||||
import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation'
|
||||
import AppNavigationNew from '@nextcloud/vue/dist/Components/AppNavigationNew'
|
||||
import Content from '@nextcloud/vue/dist/Components/Content'
|
||||
|
||||
import AppNavigationForm from './components/AppNavigationForm'
|
||||
import EmptyContent from './components/EmptyContent'
|
||||
|
||||
import { formatForm } from './utils/FormsUtils'
|
||||
|
||||
export default {
|
||||
name: 'Forms',
|
||||
|
||||
components: {
|
||||
AppNavigationForm,
|
||||
AppContent,
|
||||
AppNavigation,
|
||||
AppNavigationNew,
|
||||
Content,
|
||||
EmptyContent,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
forms: [],
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
noForms() {
|
||||
return this.forms && this.forms.length === 0
|
||||
},
|
||||
|
||||
formattedForms() {
|
||||
return this.forms.map(formatForm)
|
||||
},
|
||||
|
||||
hash() {
|
||||
return this.$route.params.hash
|
||||
},
|
||||
|
||||
selectedForm() {
|
||||
// TODO: replace with form.hash
|
||||
return this.forms.find(form => form.event.hash === this.hash)
|
||||
},
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.loadForms()
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Initial forms load
|
||||
*/
|
||||
async loadForms() {
|
||||
this.loading = true
|
||||
try {
|
||||
const response = await axios.get(generateUrl('apps/forms/get/forms'))
|
||||
this.forms = response.data
|
||||
} catch (error) {
|
||||
showError(t('forms', 'An error occured while loading the forms list'))
|
||||
console.error(error)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
async onNewForm() {
|
||||
try {
|
||||
// Request a new empty form
|
||||
const response = await axios.post(generateUrl('/apps/forms/api/v1/form'))
|
||||
const newForm = response.data
|
||||
this.forms.push(newForm)
|
||||
this.$router.push({ name: 'edit', params: { hash: newForm.event.hash } })
|
||||
} catch (error) {
|
||||
showError(t('forms', 'Unable to create a new form'))
|
||||
console.error(error)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove form from forms list after successful server deletion request
|
||||
*
|
||||
* @param {Number} id the form id
|
||||
*/
|
||||
async onDeleteForm(id) {
|
||||
const formIndex = this.forms.findIndex(form => form.id === id)
|
||||
this.forms.splice(formIndex, 1)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
179
src/components/AppNavigationForm.vue
Normal file
|
@ -0,0 +1,179 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<AppNavigationItem
|
||||
ref="navigationItem"
|
||||
:exact="true"
|
||||
:icon="loading ? 'icon-loading-small' : ''"
|
||||
:title="form.title"
|
||||
:to="{ name: 'edit', params: { hash: form.hash } }">
|
||||
<AppNavigationIconBullet slot="icon" :color="bulletColor" />
|
||||
<template v-if="!loading" #actions>
|
||||
<ActionLink
|
||||
:href="formLink"
|
||||
:icon="copied && copySuccess ? 'icon-checkmark-color' : 'icon-clippy'"
|
||||
target="_blank"
|
||||
@click.stop.prevent="copyLink">
|
||||
{{ clipboardTooltip }}
|
||||
</ActionLink>
|
||||
<ActionRouter :close-after-click="true"
|
||||
:exact="true"
|
||||
icon="icon-forms"
|
||||
:to="{ name: 'results', params: { hash: form.hash } }">
|
||||
{{ t('forms', 'Show results') }}
|
||||
</ActionRouter>
|
||||
<!-- <ActionRouter :close-after-click="true"
|
||||
:exact="true"
|
||||
icon="icon-clone"
|
||||
:to="{ name: 'clone', params: { hash: form.hash } }">
|
||||
{{ t('forms', 'Clone form') }}
|
||||
</ActionRouter> -->
|
||||
<ActionSeparator />
|
||||
<ActionButton :close-after-click="true" icon="icon-delete" @click="onDeleteForm">
|
||||
{{ t('forms', 'Delete form') }}
|
||||
</ActionButton>
|
||||
</template>
|
||||
</AppNavigationItem>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
|
||||
import ActionLink from '@nextcloud/vue/dist/Components/ActionLink'
|
||||
import ActionRouter from '@nextcloud/vue/dist/Components/ActionRouter'
|
||||
import ActionSeparator from '@nextcloud/vue/dist/Components/ActionSeparator'
|
||||
import AppNavigationIconBullet from '@nextcloud/vue/dist/Components/AppNavigationIconBullet'
|
||||
import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
|
||||
import axios from '@nextcloud/axios'
|
||||
import Vue from 'vue'
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
|
||||
Vue.use(VueClipboard)
|
||||
|
||||
export default {
|
||||
name: 'AppNavigationForm',
|
||||
|
||||
components: {
|
||||
AppNavigationItem,
|
||||
AppNavigationIconBullet,
|
||||
ActionButton,
|
||||
ActionLink,
|
||||
ActionRouter,
|
||||
ActionSeparator,
|
||||
},
|
||||
|
||||
props: {
|
||||
form: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
copySuccess: true,
|
||||
copied: false,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
/**
|
||||
* Map form state to bullet color
|
||||
*
|
||||
* @returns {string} hex color
|
||||
*/
|
||||
bulletColor() {
|
||||
const style = getComputedStyle(document.body)
|
||||
if (this.form.expired) {
|
||||
return style.getPropertyValue('--color-error').slice(-6)
|
||||
}
|
||||
return style.getPropertyValue('--color-success').slice(-6)
|
||||
},
|
||||
|
||||
/**
|
||||
* Return the form share link
|
||||
* @returns {string}
|
||||
*/
|
||||
formLink() {
|
||||
return window.location.protocol + '//' + window.location.host + generateUrl(`/apps/forms/${this.form.hash}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* Clipboard v-tooltip message
|
||||
* @returns {string}
|
||||
*/
|
||||
clipboardTooltip() {
|
||||
if (this.copied) {
|
||||
return this.copySuccess
|
||||
? t('forms', 'Form link copied')
|
||||
: t('forms', 'Cannot copy, please copy the link manually')
|
||||
}
|
||||
return t('forms', 'Copy to clipboard')
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
async onDeleteForm() {
|
||||
if (!confirm(t('forms', 'Are you sure you want to delete the form “{title}”', { title: this.form.title }))) {
|
||||
return
|
||||
}
|
||||
|
||||
// All good, let's delete
|
||||
this.loading = true
|
||||
try {
|
||||
await axios.delete(generateUrl('/apps/forms/api/v1/form/{id}', { id: this.form.id }))
|
||||
this.$emit('delete', this.form.id)
|
||||
showSuccess(t('forms', 'Deleted form “{title}”', { title: this.form.title }))
|
||||
} catch (error) {
|
||||
showError(t('forms', 'Error while deleting form “{title}”', { title: this.form.title }))
|
||||
console.error(error.response)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
async copyLink() {
|
||||
try {
|
||||
await this.$copyText(this.formLink)
|
||||
// make sure the menu stays open despite the click outside
|
||||
this.$refs.navigationItem.menuOpened = true
|
||||
this.copySuccess = true
|
||||
this.copied = true
|
||||
} catch (error) {
|
||||
this.copySuccess = false
|
||||
this.copied = true
|
||||
console.error(error)
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
this.copySuccess = false
|
||||
this.copied = false
|
||||
}, 4000)
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
|
@ -1,7 +1,7 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
|
||||
- @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @author René Gieling <github@dartcafe.de>
|
||||
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
|
@ -12,34 +12,40 @@
|
|||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div id="app-forms">
|
||||
<router-view />
|
||||
<div class="emptycontent" role="note">
|
||||
<div :class="icon" role="img" />
|
||||
<h2><slot /></h2>
|
||||
<p v-show="$slots.desc">
|
||||
<slot name="desc" />
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
name: 'EmptyContent',
|
||||
|
||||
props: {
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'icon-forms',
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#app-forms {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
.emptycontent {
|
||||
margin-top: 20vh;
|
||||
}
|
||||
|
||||
#app-content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
}
|
||||
</style>
|
|
@ -1,39 +0,0 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
|
||||
-
|
||||
- @author René Gieling <github@dartcafe.de>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="forms-sidebar">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.forms-sidebar {
|
||||
min-width: 300px;
|
||||
border-left: 1px solid var(--color-border);
|
||||
z-index: 500;
|
||||
> ul,
|
||||
> div {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -163,16 +163,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
formType() {
|
||||
if (this.form.event.type === 'textForm') {
|
||||
// TRANSLATORS This means that this is the type of the form. Another type is a 'date form'.
|
||||
return t('forms', 'Text form')
|
||||
} else {
|
||||
// TRANSLATORS This means that this is the type of the form. Another type is a 'text form'.
|
||||
return t('forms', 'Text form')
|
||||
}
|
||||
},
|
||||
|
||||
timeSpanCreated() {
|
||||
return moment(this.form.event.created, 'YYYY-MM-DD HH:mm')
|
||||
},
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
|
||||
<script>
|
||||
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
|
||||
// TODO: replace with same design as core sharing
|
||||
import UserDiv from './_base-UserDiv'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
|
|
36
src/main.js
|
@ -1,8 +1,8 @@
|
|||
/* jshint esversion: 6 */
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 René Gieling <github@dartcafe.de>
|
||||
*
|
||||
* @author René Gieling <github@dartcafe.de>
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
|
@ -21,37 +21,47 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
import router from './router'
|
||||
import App from './App'
|
||||
import { generateFilePath } from '@nextcloud/router'
|
||||
import { getRequestToken } from '@nextcloud/auth'
|
||||
import { translate, translatePlural } from '@nextcloud/l10n'
|
||||
import '@nextcloud/dialogs/styles/toast.scss'
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
|
||||
|
||||
import router from './router'
|
||||
import Forms from './Forms'
|
||||
import Modal from './plugins/plugin.js'
|
||||
|
||||
// TODO: not use global registration
|
||||
Vue.directive('tooltip', Tooltip)
|
||||
|
||||
Vue.use(VueClipboard)
|
||||
Vue.use(Modal)
|
||||
|
||||
Vue.prototype.t = t
|
||||
Vue.prototype.n = n
|
||||
Vue.prototype.t = translate
|
||||
Vue.prototype.n = translatePlural
|
||||
|
||||
// TODO: see if necessary
|
||||
Vue.prototype.OC = OC
|
||||
Vue.prototype.OCA = OCA
|
||||
|
||||
// CSP config for webpack dynamic chunk loading
|
||||
// eslint-disable-next-line
|
||||
__webpack_nonce__ = btoa(OC.requestToken)
|
||||
__webpack_nonce__ = btoa(getRequestToken())
|
||||
|
||||
// Correct the root of the app for chunk loading
|
||||
// OC.linkTo matches the apps folders
|
||||
// OC.generateUrl ensure the index.php (or not)
|
||||
// We do not want the index.php since we're loading files
|
||||
// eslint-disable-next-line
|
||||
__webpack_public_path__ = OC.linkTo('forms', 'js/')
|
||||
__webpack_public_path__ = generateFilePath('forms', '', 'js/')
|
||||
|
||||
/* eslint-disable-next-line no-new */
|
||||
new Vue({
|
||||
el: '#app-forms',
|
||||
router: router,
|
||||
render: h => h(App),
|
||||
el: '#content',
|
||||
// eslint-disable-next-line vue/match-component-file-name
|
||||
name: 'FormsRoot',
|
||||
router,
|
||||
render: h => h(Forms),
|
||||
})
|
||||
|
|
34
src/mixins/ViewsMixin.js
Normal file
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
props: {
|
||||
hash: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
form: {
|
||||
type: Object,
|
||||
// TODO: use default Form object ?
|
||||
default: {},
|
||||
},
|
||||
},
|
||||
}
|
53
src/models/Form.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
export default class {
|
||||
|
||||
#data
|
||||
|
||||
/**
|
||||
* Construct the form
|
||||
* @param {Object} data the form data
|
||||
*/
|
||||
constructor(data) {
|
||||
// Id check
|
||||
if (!('id' in data && typeof data.id === 'number')) {
|
||||
throw new Error('A new form must at least contain a valid id')
|
||||
}
|
||||
|
||||
// Hash check
|
||||
if (!('hash' in data && typeof data.id === 'string')) {
|
||||
throw new Error('A new form must at least contain a valid hash')
|
||||
}
|
||||
|
||||
this.#data = data
|
||||
}
|
||||
|
||||
get id() {
|
||||
return this.#data.id
|
||||
}
|
||||
|
||||
get hash() {
|
||||
return this.#data.hash
|
||||
}
|
||||
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
/* jshint esversion: 6 */
|
||||
// we need our modal component
|
||||
import ModalDialog from './ModalDialog'
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
/* jshint esversion: 6 */
|
||||
/**
|
||||
* @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
|
||||
* @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
|
@ -22,59 +21,66 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
|
||||
import Create from './views/Create'
|
||||
import Results from './views/Results'
|
||||
import Sidebar from './views/Sidebar'
|
||||
|
||||
// Dynamic loading
|
||||
const Create = () => import('./views/Create')
|
||||
const List = () => import('./views/List')
|
||||
const Results = () => import('./views/Results')
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
mode: 'history',
|
||||
base: OC.generateUrl(''),
|
||||
|
||||
// if index.php is in the url AND we got this far, then it's working:
|
||||
// let's keep using index.php in the url
|
||||
base: generateUrl('/apps/forms', ''),
|
||||
linkActiveClass: 'active',
|
||||
|
||||
routes: [
|
||||
{
|
||||
path: '/:index(index.php/)?apps/forms/',
|
||||
components: {
|
||||
default: List,
|
||||
},
|
||||
props: false,
|
||||
name: 'list',
|
||||
path: '/',
|
||||
name: 'root',
|
||||
},
|
||||
{
|
||||
path: '/:index(index.php/)?apps/forms/edit/:hash',
|
||||
path: '/new',
|
||||
components: {
|
||||
default: Create,
|
||||
sidebar: Sidebar,
|
||||
},
|
||||
props: true,
|
||||
name: 'edit',
|
||||
},
|
||||
{
|
||||
path: '/:index(index.php/)?apps/forms/results/:hash',
|
||||
components: {
|
||||
default: Results,
|
||||
},
|
||||
props: false,
|
||||
name: 'results',
|
||||
},
|
||||
{
|
||||
path: '/:index(index.php/)?apps/forms/clone/:hash',
|
||||
components: {
|
||||
default: Create,
|
||||
},
|
||||
props: true,
|
||||
name: 'clone',
|
||||
},
|
||||
{
|
||||
path: '/:index(index.php/)?apps/forms/new',
|
||||
components: {
|
||||
default: Create,
|
||||
},
|
||||
props: false,
|
||||
name: 'create',
|
||||
},
|
||||
{
|
||||
path: '/:hash',
|
||||
name: 'fill',
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/:hash/edit',
|
||||
components: {
|
||||
default: Create,
|
||||
sidebar: Sidebar,
|
||||
},
|
||||
name: 'edit',
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/:hash/results',
|
||||
component: Results,
|
||||
name: 'results',
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: '/:hash/clone',
|
||||
components: {
|
||||
default: Create,
|
||||
sidebar: Sidebar,
|
||||
},
|
||||
name: 'clone',
|
||||
props: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
53
src/services/FormsService.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
/**
|
||||
* Get the forms list
|
||||
*
|
||||
* @returns {Array}
|
||||
*/
|
||||
const getForms = async function() {
|
||||
try {
|
||||
const response = await axios.get(OC.generateUrl('apps/forms/get/forms'))
|
||||
return response.data
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw Error(t('forms', 'Unable to fetch the forms list'))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a form
|
||||
*
|
||||
* @param {int} id the form id to delete
|
||||
*/
|
||||
const deleteForm = async function(id) {
|
||||
try {
|
||||
axios.delete(OC.generateUrl('apps/forms/forms/{id}', { id }))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
throw Error(t('forms', 'Unable to delete the form'))
|
||||
}
|
||||
}
|
||||
|
||||
export { deleteForm, getForms }
|
44
src/utils/FormsUtils.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Format a form object prior to forms v2.0
|
||||
*
|
||||
* @param {Object} form the form raw object
|
||||
* @returns {Object} properly formatted form object
|
||||
*/
|
||||
const formatForm = function(form) {
|
||||
// clone form
|
||||
const newForm = Object.assign({}, form, form.event)
|
||||
|
||||
// migrate object architecture
|
||||
Object.assign(newForm, {
|
||||
questions: form.options && form.options.formQuizQuestions,
|
||||
})
|
||||
|
||||
// cleanup
|
||||
delete newForm.options
|
||||
delete newForm.event
|
||||
|
||||
return newForm
|
||||
}
|
||||
|
||||
export { formatForm }
|
|
@ -26,17 +26,7 @@
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div id="app-content">
|
||||
<Controls :intitle="title">
|
||||
<template slot="after">
|
||||
<button :disabled="writingForm" class="button btn primary" @click="writeForm(form.mode)">
|
||||
<span>{{ saveButtonTitle }}</span>
|
||||
<span v-if="writingForm" class="icon-loading-small" />
|
||||
</button>
|
||||
<button class="button symbol icon-settings" @click="switchSidebar" />
|
||||
</template>
|
||||
</Controls>
|
||||
|
||||
<AppContent>
|
||||
<div class="workbench">
|
||||
<div>
|
||||
<h2>{{ t('forms', 'Form description') }}</h2>
|
||||
|
@ -53,7 +43,7 @@
|
|||
|
||||
<div>
|
||||
<h2>{{ t('forms', 'Make a Form') }}</h2>
|
||||
<div v-show="form.event.type === 'quizForm'" id="quiz-form-selector-text">
|
||||
<div id="quiz-form-selector-text">
|
||||
<!--shows inputs for question types: drop down box to select the type, text box for question, and button to add-->
|
||||
<label for="ans-type">Answer Type: </label>
|
||||
<select v-model="selected">
|
||||
|
@ -64,7 +54,7 @@
|
|||
{{ option.text }}
|
||||
</option>
|
||||
</select>
|
||||
<input v-model="newQuizQuestion" :placeholder=" t('forms', 'Add Question') " @keyup.enter="addQuestion()">
|
||||
<input v-model="newQuizQuestion" :placeholder="t('forms', 'Add Question')" @keyup.enter="addQuestion()">
|
||||
<button id="questButton"
|
||||
@click="addQuestion()">
|
||||
{{ t('forms', 'Add Question') }}
|
||||
|
@ -72,7 +62,6 @@
|
|||
</div>
|
||||
<!--Transition group to list the already added questions (in the form of quizFormItems)-->
|
||||
<transitionGroup
|
||||
v-show="form.mode == 'create'"
|
||||
id="form-list"
|
||||
name="list"
|
||||
tag="ul"
|
||||
|
@ -89,195 +78,40 @@
|
|||
</transitionGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<SideBar v-if="sidebar">
|
||||
<div v-if="adminMode" class="warning">
|
||||
{{ t('forms', 'You are editing in admin mode') }}
|
||||
</div>
|
||||
<UserDiv :user-id="form.event.owner" :description="t('forms', 'Owner')" />
|
||||
|
||||
<ul class="tabHeaders">
|
||||
<li class="tabHeader selected" data-tabid="configurationsTabView" data-tabindex="0">
|
||||
<a href="#">
|
||||
{{ t('forms', 'Configuration') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div v-if="protect">
|
||||
<span>{{ t('forms', 'Configuration is locked. Changing options may result in unwanted behaviour, but you can unlock it anyway.') }}</span>
|
||||
<button @click="protect=false">
|
||||
{{ t('forms', 'Unlock configuration ') }}
|
||||
</button>
|
||||
</div>
|
||||
<div id="configurationsTabView" class="tab">
|
||||
<div class="configBox ">
|
||||
<label class="title icon-settings">
|
||||
{{ t('forms', 'Form configurations') }}
|
||||
</label>
|
||||
|
||||
<input id="anonymous"
|
||||
v-model="form.event.isAnonymous"
|
||||
:disabled="protect"
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<label for="anonymous" class="title">
|
||||
{{ t('forms', 'Anonymous form') }}
|
||||
</label>
|
||||
|
||||
<input id="unique"
|
||||
v-model="form.event.unique"
|
||||
:disabled="form.event.access !== 'registered' || form.event.isAnonymous"
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<label for="unique" class="title">
|
||||
<span>{{ t('forms', 'Only allow one submission per user') }}</span>
|
||||
</label>
|
||||
|
||||
<input v-show="form.event.isAnonymous"
|
||||
id="trueAnonymous"
|
||||
v-model="form.event.fullAnonymous"
|
||||
:disabled="protect"
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<input id="expiration"
|
||||
v-model="form.event.expiration"
|
||||
:disabled="protect"
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<label class="title" for="expiration">
|
||||
{{ t('forms', 'Expires') }}
|
||||
</label>
|
||||
|
||||
<DatetimePicker v-show="form.event.expiration"
|
||||
v-model="form.event.expirationDate"
|
||||
v-bind="expirationDatePicker"
|
||||
:disabled="protect"
|
||||
:time-picker-options="{ start: '00:00', step: '00:05', end: '23:55' }"
|
||||
style="width:170px" />
|
||||
</div>
|
||||
|
||||
<div class="configBox">
|
||||
<label class="title icon-user">
|
||||
{{ t('forms', 'Access') }}
|
||||
</label>
|
||||
<input id="private"
|
||||
v-model="form.event.access"
|
||||
:disabled="protect"
|
||||
type="radio"
|
||||
value="registered"
|
||||
class="radio">
|
||||
<label for="private" class="title">
|
||||
<div class="title icon-group" />
|
||||
<span>{{ t('forms', 'Registered users only') }}</span>
|
||||
</label>
|
||||
<input id="public"
|
||||
v-model="form.event.access"
|
||||
:disabled="protect"
|
||||
type="radio"
|
||||
value="public"
|
||||
class="radio">
|
||||
<label for="public" class="title">
|
||||
<div class="title icon-link" />
|
||||
<span>{{ t('forms', 'Public access') }}</span>
|
||||
</label>
|
||||
<input id="select"
|
||||
v-model="form.event.access"
|
||||
:disabled="protect"
|
||||
type="radio"
|
||||
value="select"
|
||||
class="radio">
|
||||
<label for="select" class="title">
|
||||
<div class="title icon-shared" />
|
||||
<span>{{ t('forms', 'Only shared') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ShareDiv v-show="form.event.access === 'select'"
|
||||
:active-shares="form.shares"
|
||||
:placeholder="t('forms', 'Name of user or group')"
|
||||
:hide-names="true"
|
||||
@update-shares="updateShares"
|
||||
@remove-share="removeShare" />
|
||||
</SideBar>
|
||||
<LoadingOverlay v-if="loadingForm" />
|
||||
</div>
|
||||
</AppContent>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from '@nextcloud/axios'
|
||||
import DatetimePicker from '@nextcloud/vue/dist/Components/DatetimePicker'
|
||||
import moment from '@nextcloud/moment'
|
||||
import debounce from 'debounce'
|
||||
|
||||
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
|
||||
import { showError, showSuccess } from '@nextcloud/dialogs'
|
||||
|
||||
import Controls from '../components/_base-Controls'
|
||||
import LoadingOverlay from '../components/_base-LoadingOverlay'
|
||||
import QuizFormItem from '../components/quizFormItem'
|
||||
import ShareDiv from '../components/shareDiv'
|
||||
import SideBar from '../components/_base-SideBar'
|
||||
import UserDiv from '../components/_base-UserDiv'
|
||||
|
||||
import ViewsMixin from '../mixins/ViewsMixin'
|
||||
|
||||
export default {
|
||||
name: 'Create',
|
||||
components: {
|
||||
Controls,
|
||||
DatetimePicker,
|
||||
LoadingOverlay,
|
||||
AppContent,
|
||||
QuizFormItem,
|
||||
ShareDiv,
|
||||
SideBar,
|
||||
UserDiv,
|
||||
},
|
||||
|
||||
mixins: [ViewsMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
move: {
|
||||
step: 1,
|
||||
unit: 'week',
|
||||
units: ['minute', 'hour', 'day', 'week', 'month', 'year'],
|
||||
},
|
||||
form: {
|
||||
mode: 'create',
|
||||
votes: [],
|
||||
shares: [],
|
||||
grantedAs: 'owner',
|
||||
id: 0,
|
||||
result: 'new',
|
||||
event: {
|
||||
id: 0,
|
||||
hash: '',
|
||||
type: 'quizForm',
|
||||
title: '',
|
||||
description: '',
|
||||
created: '',
|
||||
access: 'public',
|
||||
unique: false,
|
||||
expiration: false,
|
||||
expirationDate: '',
|
||||
expired: false,
|
||||
isAnonymous: false,
|
||||
fullAnonymous: false,
|
||||
owner: undefined,
|
||||
},
|
||||
options: {
|
||||
formQuizQuestions: [],
|
||||
},
|
||||
},
|
||||
lang: '',
|
||||
locale: '',
|
||||
placeholder: '',
|
||||
newQuizAnswer: '',
|
||||
newQuizQuestion: '',
|
||||
nextQuizAnswerId: 1,
|
||||
nextQuizQuestionId: 1,
|
||||
protect: false,
|
||||
writingForm: false,
|
||||
loadingForm: true,
|
||||
sidebar: false,
|
||||
titleEmpty: false,
|
||||
indexPage: '',
|
||||
longDateFormat: '',
|
||||
dateTimeFormat: '',
|
||||
selected: '',
|
||||
uniqueName: false,
|
||||
uniqueAns: false,
|
||||
|
@ -293,10 +127,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
adminMode() {
|
||||
return (this.form.event.owner !== OC.getCurrentUser().uid && OC.isUserAdmin())
|
||||
},
|
||||
|
||||
langShort() {
|
||||
return this.lang.split('-')[0]
|
||||
},
|
||||
|
@ -324,38 +154,6 @@ export default {
|
|||
return moment.localeData(moment.locale(this.locale))
|
||||
},
|
||||
|
||||
expirationDatePicker() {
|
||||
return {
|
||||
editable: true,
|
||||
minuteStep: 1,
|
||||
type: 'datetime',
|
||||
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
|
||||
lang: this.lang.split('-')[0],
|
||||
placeholder: t('forms', 'Expiration date'),
|
||||
timePickerOptions: {
|
||||
start: '00:00',
|
||||
step: '00:30',
|
||||
end: '23:30',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
optionDatePicker() {
|
||||
return {
|
||||
editable: false,
|
||||
minuteStep: 1,
|
||||
type: 'datetime',
|
||||
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
|
||||
lang: this.lang.split('-')[0],
|
||||
placeholder: t('forms', 'Click to add a date'),
|
||||
timePickerOptions: {
|
||||
start: '00:00',
|
||||
step: '00:30',
|
||||
end: '23:30',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
watch: {
|
||||
|
@ -363,37 +161,25 @@ export default {
|
|||
// only used when the title changes after page load
|
||||
document.title = t('forms', 'Forms') + ' - ' + this.title
|
||||
},
|
||||
|
||||
form: {
|
||||
deep: true,
|
||||
handler: function() {
|
||||
this.debounceWriteForm()
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.indexPage = OC.generateUrl('apps/forms/')
|
||||
this.lang = OC.getLanguage()
|
||||
try {
|
||||
this.locale = OC.getLocale()
|
||||
} catch (e) {
|
||||
if (e instanceof TypeError) {
|
||||
this.locale = this.lang
|
||||
} else {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
moment.locale(this.locale)
|
||||
this.longDateFormat = moment.localeData().longDateFormat('L')
|
||||
this.dateTimeFormat = moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT')
|
||||
|
||||
if (this.$route.name === 'create') {
|
||||
// TODO: manage this from Forms.vue, request a new form to the server
|
||||
this.form.event.owner = OC.getCurrentUser().uid
|
||||
this.loadingForm = false
|
||||
} else if (this.$route.name === 'edit') {
|
||||
this.loadForm(this.$route.params.hash)
|
||||
this.protect = true
|
||||
// TODO: fetch & update form?
|
||||
this.form.mode = 'edit'
|
||||
} else if (this.$route.name === 'clone') {
|
||||
this.loadForm(this.$route.params.hash)
|
||||
}
|
||||
if (window.innerWidth > 1024) {
|
||||
this.sidebar = true
|
||||
// TODO: CLONE
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -403,18 +189,6 @@ export default {
|
|||
this.sidebar = !this.sidebar
|
||||
},
|
||||
|
||||
addShare(item) {
|
||||
this.form.shares.push(item)
|
||||
},
|
||||
|
||||
updateShares(share) {
|
||||
this.form.shares = share.slice(0)
|
||||
},
|
||||
|
||||
removeShare(item) {
|
||||
this.form.shares.splice(this.form.shares.indexOf(item), 1)
|
||||
},
|
||||
|
||||
checkNames() {
|
||||
this.uniqueName = true
|
||||
this.form.options.formQuizQuestions.forEach(q => {
|
||||
|
@ -427,9 +201,9 @@ export default {
|
|||
addQuestion() {
|
||||
this.checkNames()
|
||||
if (this.selected === '') {
|
||||
OC.Notification.showTemporary(t('forms', 'Select a question type!'))
|
||||
showError(t('forms', 'Select a question type!'), { duration: 3000 })
|
||||
} else if (!this.uniqueName) {
|
||||
OC.Notification.showTemporary(t('forms', 'Cannot have the same question!'))
|
||||
showError(t('forms', 'Cannot have the same question!'))
|
||||
} else {
|
||||
if (this.newQuizQuestion !== null & this.newQuizQuestion !== '' & (/\S/.test(this.newQuizQuestion))) {
|
||||
this.form.options.formQuizQuestions.push({
|
||||
|
@ -460,7 +234,7 @@ export default {
|
|||
addAnswer(item, question) {
|
||||
this.checkAnsNames(item, question)
|
||||
if (!this.uniqueAnsName) {
|
||||
OC.Notification.showTemporary(t('forms', 'Two answers cannot be the same!'))
|
||||
showError(t('forms', 'Two answers cannot be the same!'), { duration: 3000 })
|
||||
} else {
|
||||
if (item.newQuizAnswer !== null & item.newQuizAnswer !== '' & (/\S/.test(item.newQuizAnswer))) {
|
||||
item.formQuizAnswers.push({
|
||||
|
@ -486,24 +260,22 @@ export default {
|
|||
})
|
||||
},
|
||||
|
||||
writeForm(mode) {
|
||||
debounceWriteForm: debounce(function() {
|
||||
this.writeForm()
|
||||
}, 200),
|
||||
|
||||
writeForm() {
|
||||
this.allHaveAns()
|
||||
if (mode !== '') {
|
||||
this.form.mode = mode
|
||||
}
|
||||
if (this.form.event.title.length === 0 | !(/\S/.test(this.form.event.title))) {
|
||||
this.titleEmpty = true
|
||||
OC.Notification.showTemporary(t('forms', 'Title must not be empty!'))
|
||||
} else if (this.form.options.formQuizQuestions.length === 0) {
|
||||
OC.Notification.showTemporary(t('forms', 'Must have at least one question!'))
|
||||
showError(t('forms', 'Title must not be empty!'), { duration: 3000 })
|
||||
} else if (!this.haveAns) {
|
||||
OC.Notification.showTemporary(t('forms', 'All questions need answers!'))
|
||||
showError(t('forms', 'All questions need answers!'), { duration: 3000 })
|
||||
} else if (this.form.event.expiration & this.form.event.expirationDate === '') {
|
||||
OC.Notification.showTemporary(t('forms', 'Need to pick an expiration date!'))
|
||||
showError(t('forms', 'Need to pick an expiration date!'), { duration: 3000 })
|
||||
} else {
|
||||
this.writingForm = true
|
||||
this.titleEmpty = false
|
||||
// this.form.event.expirationDate = moment(this.form.event.expirationDate).utc()
|
||||
|
||||
axios.post(OC.generateUrl('apps/forms/write/form'), this.form)
|
||||
.then((response) => {
|
||||
|
@ -511,201 +283,130 @@ export default {
|
|||
this.form.event.hash = response.data.hash
|
||||
this.form.event.id = response.data.id
|
||||
this.writingForm = false
|
||||
OC.Notification.showTemporary(t('forms', '%n successfully saved', 1, this.form.event.title))
|
||||
// window.location.href = OC.generateUrl('apps/forms/edit/' + this.form.event.hash)
|
||||
this.$router.push('/apps/forms/')
|
||||
showSuccess(t('forms', '%n successfully saved', 1, this.form.event.title), { duration: 3000 })
|
||||
}, (error) => {
|
||||
this.form.event.hash = ''
|
||||
this.writingForm = false
|
||||
OC.Notification.showTemporary(t('forms', 'Error on saving form, see console'))
|
||||
showError(t('forms', 'Error on saving form, see console'))
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(error.response)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
loadForm(hash) {
|
||||
this.loadingForm = true
|
||||
axios.get(OC.generateUrl('apps/forms/get/form/' + hash))
|
||||
.then((response) => {
|
||||
this.form = response.data
|
||||
if (this.form.event.expirationDate !== null) {
|
||||
this.form.event.expirationDate = new Date(moment.utc(this.form.event.expirationDate))
|
||||
} else {
|
||||
this.form.event.expirationDate = ''
|
||||
}
|
||||
|
||||
if (this.$route.name === 'clone') {
|
||||
this.form.event.owner = OC.getCurrentUser().uid
|
||||
this.form.event.title = t('forms', 'Clone of %n', 1, this.form.event.title)
|
||||
this.form.event.id = 0
|
||||
this.form.id = 0
|
||||
this.form.event.hash = ''
|
||||
this.form.grantedAs = 'owner'
|
||||
this.form.result = 'new'
|
||||
this.form.mode = 'create'
|
||||
this.form.votes = []
|
||||
}
|
||||
|
||||
this.loadingForm = false
|
||||
this.newQuizAnswer = ''
|
||||
this.newQuizQuestion = ''
|
||||
|
||||
}, (error) => {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(error.response)
|
||||
this.form.event.hash = ''
|
||||
this.loadingForm = false
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
#app-content {
|
||||
input.hasTimepicker {
|
||||
width: 75px;
|
||||
}
|
||||
input.hasTimepicker {
|
||||
width: 75px;
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: var(--color-error);
|
||||
font-weight: bold;
|
||||
color: var(--color-error);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.forms-content {
|
||||
display: flex;
|
||||
padding-top: 45px;
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
padding-top: 45px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
display: block;
|
||||
width: 100%;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.workbench {
|
||||
margin-top: 45px;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-wrap: wrap;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-wrap: wrap;
|
||||
overflow-x: hidden;
|
||||
|
||||
> div {
|
||||
min-width: 245px;
|
||||
max-width: 540px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.forms-sidebar {
|
||||
margin-top: 45px;
|
||||
width: 25%;
|
||||
|
||||
.configBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px;
|
||||
& > * {
|
||||
padding-left: 21px;
|
||||
}
|
||||
& > .title {
|
||||
display: flex;
|
||||
background-position: 0 2px;
|
||||
padding-left: 24px;
|
||||
opacity: 0.7;
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
& > span {
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
&.error {
|
||||
border: 2px solid var(--color-error);
|
||||
box-shadow: 1px 0 var(--border-radius) var(--color-box-shadow);
|
||||
}
|
||||
> div {
|
||||
min-width: 245px;
|
||||
max-width: 540px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Transitions for inserting and removing list items */
|
||||
.list-enter-active,
|
||||
.list-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.list-enter,
|
||||
.list-leave-to {
|
||||
opacity: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.list-move {
|
||||
transition: transform 0.5s;
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
/* */
|
||||
|
||||
#form-item-selector-text {
|
||||
> input {
|
||||
width: 100%;
|
||||
}
|
||||
> input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.form-table {
|
||||
> li {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
line-height: 24px;
|
||||
min-height: 24px;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
> li {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
line-height: 24px;
|
||||
min-height: 24px;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
&:active,
|
||||
&:hover {
|
||||
transition: var(--background-dark) 0.3s ease;
|
||||
background-color: var(--color-background-dark); //$hover-color;
|
||||
&:active,
|
||||
&:hover {
|
||||
transition: var(--background-dark) 0.3s ease;
|
||||
background-color: var(--color-background-dark); //$hover-color;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
font-size: 1.2em;
|
||||
opacity: 0.7;
|
||||
white-space: normal;
|
||||
padding-right: 4px;
|
||||
&.avatar {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
> div {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
font-size: 1.2em;
|
||||
opacity: 0.7;
|
||||
white-space: normal;
|
||||
padding-right: 4px;
|
||||
&.avatar {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-last-child(1) {
|
||||
justify-content: center;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
> div:nth-last-child(1) {
|
||||
justify-content: center;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
&.button-inline {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
&.button-inline {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.selectUnit {
|
||||
display: flex;
|
||||
|
|
31
src/views/Fill.vue
Normal file
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<span>TODO</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Fill',
|
||||
}
|
||||
</script>
|
|
@ -22,15 +22,7 @@
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div id="app-content">
|
||||
<Controls>
|
||||
<router-link :to="{ name: 'create'}" class="button">
|
||||
<span class="symbol icon-add" />
|
||||
<span class="hidden-visually">
|
||||
{{ t('forms', 'New') }}
|
||||
</span>
|
||||
</router-link>
|
||||
</Controls>
|
||||
<AppContent>
|
||||
<div v-if="noForms" class="">
|
||||
<div class="icon-forms" />
|
||||
<h2> {{ t('No existing forms.') }} </h2>
|
||||
|
@ -56,54 +48,69 @@
|
|||
</transition-group>
|
||||
<LoadingOverlay v-if="loading" />
|
||||
<modal-dialog />
|
||||
</div>
|
||||
</AppContent>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import axios from '@nextcloud/axios'
|
||||
|
||||
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
|
||||
|
||||
import FormListItem from '../components/formListItem'
|
||||
import Controls from '../components/_base-Controls'
|
||||
import axios from '@nextcloud/axios'
|
||||
import LoadingOverlay from '../components/_base-LoadingOverlay'
|
||||
import ViewsMixin from '../mixins/ViewsMixin'
|
||||
|
||||
export default {
|
||||
name: 'List',
|
||||
|
||||
components: {
|
||||
Controls,
|
||||
AppContent,
|
||||
FormListItem,
|
||||
LoadingOverlay,
|
||||
},
|
||||
|
||||
mixins: [ViewsMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
noForms: false,
|
||||
loading: true,
|
||||
forms: [],
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.indexPage = OC.generateUrl('apps/forms/')
|
||||
computed: {
|
||||
noForms() {
|
||||
return this.forms && this.forms.length > 0
|
||||
},
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
this.loadForms()
|
||||
},
|
||||
|
||||
methods: {
|
||||
loadForms() {
|
||||
/**
|
||||
* Initial forms load
|
||||
*/
|
||||
async loadForms() {
|
||||
this.loading = true
|
||||
axios.get(OC.generateUrl('apps/forms/get/forms'))
|
||||
.then((response) => {
|
||||
this.forms = response.data
|
||||
this.loading = false
|
||||
}, (error) => {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(error.response)
|
||||
this.loading = false
|
||||
})
|
||||
try {
|
||||
const response = await axios.get(OC.generateUrl('apps/forms/get/forms'))
|
||||
this.forms = response.data
|
||||
} catch (error) {
|
||||
showError(t('forms', 'An error occured while loading the forms list'))
|
||||
console.error(error)
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the help page
|
||||
*/
|
||||
helpPage() {
|
||||
window.open('https://github.com/affan98/forms/blob/master/Forms_Support.md')
|
||||
window.open('https://github.com/nextcloud/forms/blob/master/Forms_Support.md')
|
||||
},
|
||||
|
||||
viewFormResults(index, event, name) {
|
||||
this.$router.push({
|
||||
name: name,
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<AppContent>
|
||||
<div>
|
||||
<button class="button btn primary" @click="download">
|
||||
<span>{{ "Export to CSV" }}</span>
|
||||
|
@ -51,7 +51,7 @@
|
|||
<LoadingOverlay v-if="loading" />
|
||||
<modal-dialog />
|
||||
</div>
|
||||
</div>
|
||||
</AppContent>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -59,15 +59,20 @@ import ResultItem from '../components/resultItem'
|
|||
import json2csvParser from 'json2csv'
|
||||
import axios from '@nextcloud/axios'
|
||||
import LoadingOverlay from '../components/_base-LoadingOverlay'
|
||||
import ViewsMixin from '../mixins/ViewsMixin'
|
||||
|
||||
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
|
||||
export default {
|
||||
name: 'Results',
|
||||
|
||||
components: {
|
||||
AppContent,
|
||||
ResultItem,
|
||||
LoadingOverlay,
|
||||
},
|
||||
|
||||
mixins: [ViewsMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: true,
|
||||
|
|
237
src/views/Sidebar.vue
Normal file
|
@ -0,0 +1,237 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
-
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
- it under the terms of the GNU Affero General Public License as
|
||||
- published by the Free Software Foundation, either version 3 of the
|
||||
- License, or (at your option) any later version.
|
||||
-
|
||||
- This program is distributed in the hope that it will be useful,
|
||||
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
- GNU Affero General Public License for more details.
|
||||
-
|
||||
- You should have received a copy of the GNU Affero General Public License
|
||||
- along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-
|
||||
-->
|
||||
|
||||
<template>
|
||||
<AppSidebar :title="form.event.title">
|
||||
<div class="configBox ">
|
||||
<label class="title icon-settings">
|
||||
{{ t('forms', 'Form configurations') }}
|
||||
</label>
|
||||
|
||||
<input id="anonymous"
|
||||
v-model="form.event.isAnonymous"
|
||||
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<label for="anonymous" class="title">
|
||||
{{ t('forms', 'Anonymous form') }}
|
||||
</label>
|
||||
|
||||
<input id="unique"
|
||||
v-model="form.event.unique"
|
||||
:disabled="form.event.access !== 'registered' || form.event.isAnonymous"
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<label for="unique" class="title">
|
||||
<span>{{ t('forms', 'Only allow one submission per user') }}</span>
|
||||
</label>
|
||||
|
||||
<input v-show="form.event.isAnonymous"
|
||||
id="trueAnonymous"
|
||||
v-model="form.event.fullAnonymous"
|
||||
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<input id="expiration"
|
||||
v-model="form.event.expiration"
|
||||
|
||||
type="checkbox"
|
||||
class="checkbox">
|
||||
<label class="title" for="expiration">
|
||||
{{ t('forms', 'Expires') }}
|
||||
</label>
|
||||
|
||||
<DatetimePicker v-show="form.event.expiration"
|
||||
v-model="form.event.expirationDate"
|
||||
v-bind="expirationDatePicker"
|
||||
|
||||
:time-picker-options="{ start: '00:00', step: '00:05', end: '23:55' }"
|
||||
style="width:170px" />
|
||||
</div>
|
||||
|
||||
<div class="configBox">
|
||||
<label class="title icon-user">
|
||||
{{ t('forms', 'Access') }}
|
||||
</label>
|
||||
<input id="private"
|
||||
v-model="form.event.access"
|
||||
|
||||
type="radio"
|
||||
value="registered"
|
||||
class="radio">
|
||||
<label for="private" class="title">
|
||||
<div class="title icon-group" />
|
||||
<span>{{ t('forms', 'Registered users only') }}</span>
|
||||
</label>
|
||||
<input id="public"
|
||||
v-model="form.event.access"
|
||||
|
||||
type="radio"
|
||||
value="public"
|
||||
class="radio">
|
||||
<label for="public" class="title">
|
||||
<div class="title icon-link" />
|
||||
<span>{{ t('forms', 'Public access') }}</span>
|
||||
</label>
|
||||
<input id="select"
|
||||
v-model="form.event.access"
|
||||
|
||||
type="radio"
|
||||
value="select"
|
||||
class="radio">
|
||||
<label for="select" class="title">
|
||||
<div class="title icon-shared" />
|
||||
<span>{{ t('forms', 'Only shared') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<ShareDiv v-show="form.event.access === 'select'"
|
||||
:active-shares="form.shares"
|
||||
:placeholder="t('forms', 'Name of user or group')"
|
||||
:hide-names="true"
|
||||
@update-shares="updateShares"
|
||||
@remove-share="removeShare" />
|
||||
</AppSidebar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppSidebar from '@nextcloud/vue/dist/Components/AppSidebar'
|
||||
import DatetimePicker from '@nextcloud/vue/dist/Components/DatetimePicker'
|
||||
import moment from '@nextcloud/moment'
|
||||
|
||||
import ShareDiv from '../components/shareDiv'
|
||||
import ViewsMixin from '../mixins/ViewsMixin'
|
||||
|
||||
export default {
|
||||
name: 'Sidebar',
|
||||
|
||||
components: {
|
||||
AppSidebar,
|
||||
DatetimePicker,
|
||||
ShareDiv,
|
||||
},
|
||||
mixins: [ViewsMixin],
|
||||
|
||||
data() {
|
||||
return {
|
||||
lang: '',
|
||||
locale: '',
|
||||
longDateFormat: '',
|
||||
dateTimeFormat: '',
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
expirationDatePicker() {
|
||||
return {
|
||||
editable: true,
|
||||
minuteStep: 1,
|
||||
type: 'datetime',
|
||||
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
|
||||
lang: this.lang.split('-')[0],
|
||||
placeholder: t('forms', 'Expiration date'),
|
||||
timePickerOptions: {
|
||||
start: '00:00',
|
||||
step: '00:30',
|
||||
end: '23:30',
|
||||
},
|
||||
}
|
||||
},
|
||||
|
||||
optionDatePicker() {
|
||||
return {
|
||||
editable: false,
|
||||
minuteStep: 1,
|
||||
type: 'datetime',
|
||||
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
|
||||
lang: this.lang.split('-')[0],
|
||||
placeholder: t('forms', 'Click to add a date'),
|
||||
timePickerOptions: {
|
||||
start: '00:00',
|
||||
step: '00:30',
|
||||
end: '23:30',
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.lang = OC.getLanguage()
|
||||
try {
|
||||
this.locale = OC.getLocale()
|
||||
} catch (e) {
|
||||
if (e instanceof TypeError) {
|
||||
this.locale = this.lang
|
||||
} else {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
moment.locale(this.locale)
|
||||
this.longDateFormat = moment.localeData().longDateFormat('L')
|
||||
this.dateTimeFormat = moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT')
|
||||
},
|
||||
|
||||
methods: {
|
||||
addShare(item) {
|
||||
this.form.shares.push(item)
|
||||
},
|
||||
|
||||
updateShares(share) {
|
||||
this.form.shares = share.slice(0)
|
||||
},
|
||||
|
||||
removeShare(item) {
|
||||
this.form.shares.splice(this.form.shares.indexOf(item), 1)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.configBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px;
|
||||
& > * {
|
||||
padding-left: 21px;
|
||||
}
|
||||
& > .title {
|
||||
display: flex;
|
||||
background-position: 0 2px;
|
||||
padding-left: 24px;
|
||||
margin-bottom: 4px;
|
||||
& > span {
|
||||
padding-left: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input,
|
||||
textarea {
|
||||
&.error {
|
||||
border: 2px solid var(--color-error);
|
||||
box-shadow: 1px 0 var(--border-radius) var(--color-box-shadow);
|
||||
}
|
||||
}
|
||||
</style>
|
25
templates/main.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
?>
|
||||
|
||||
<div id="content"></div>
|
|
@ -8,48 +8,49 @@ module.exports = {
|
|||
path: path.resolve(__dirname, './js'),
|
||||
publicPath: '/js/',
|
||||
filename: 'forms.js',
|
||||
chunkFilename: 'chunks/[name].js'
|
||||
chunkFilename: 'chunks/[name].js',
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ['vue-style-loader', 'css-loader']
|
||||
use: ['vue-style-loader', 'css-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: ['vue-style-loader', 'css-loader', 'sass-loader']
|
||||
use: ['vue-style-loader', 'css-loader', 'sass-loader'],
|
||||
},
|
||||
{
|
||||
test: /\.(js|vue)$/,
|
||||
use: 'eslint-loader',
|
||||
exclude: /node_modules/,
|
||||
enforce: 'pre'
|
||||
enforce: 'pre',
|
||||
},
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
exclude: /node_modules/
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif|svg)$/,
|
||||
loader: 'file-loader',
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
name: '[name].[ext]?[hash]'
|
||||
}
|
||||
}
|
||||
]
|
||||
limit: 8192,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new VueLoaderPlugin(),
|
||||
new StyleLintPlugin()
|
||||
new StyleLintPlugin(),
|
||||
],
|
||||
resolve: {
|
||||
extensions: ['*', '.js', '.vue']
|
||||
}
|
||||
extensions: ['*', '.js', '.vue'],
|
||||
symlinks: false,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ module.exports = merge(common, {
|
|||
devServer: {
|
||||
historyApiFallback: true,
|
||||
noInfo: true,
|
||||
overlay: true
|
||||
overlay: true,
|
||||
},
|
||||
devtool: 'source-map'
|
||||
devtool: 'source-map',
|
||||
})
|
||||
|
|
|
@ -3,5 +3,5 @@ const merge = require('webpack-merge')
|
|||
const common = require('./webpack.common.js')
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production'
|
||||
mode: 'production',
|
||||
})
|
||||
|
|