From 37ee5fcea62b2145468aeed1d3b3ae111db622e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20Molakvo=C3=A6=20=28skjnldsv=29?= Date: Fri, 20 Mar 2020 12:22:07 +0100 Subject: [PATCH] Cleanup and change routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: John Molakvoæ (skjnldsv) --- appinfo/routes.php | 12 +- css/colors.scss | 33 --- css/forms.scss | 23 ++ css/icons.scss | 24 +++ css/sidebar.scss | 214 ------------------- img/app.png | Bin 196 -> 0 bytes img/app.svg | 9 +- img/clone.svg | 1 + img/favicon-mask.svg | 45 ---- img/favicon-touch.png | Bin 10238 -> 0 bytes img/favicon-touch.svg | 1 - img/favicon.ico | Bin 4286 -> 0 bytes img/favicon.png | Bin 313 -> 0 bytes img/favicon.svg | 1 - img/forms.svg | 8 + lib/Controller/PageController.php | 87 ++++---- package-lock.json | 21 ++ package.json | 2 + src/Forms.vue | 131 ++++++++++++ src/components/AppNavigationForm.vue | 79 +++++++ src/{App.vue => components/EmptyContent.vue} | 34 +-- src/main.js | 7 +- src/mixins/ViewsMixin.js | 29 +++ src/plugins/plugin.js | 1 - src/router.js | 78 ++++--- src/services/FormsService.js | 53 +++++ src/utils/FormsUtils.js | 44 ++++ src/views/Create.vue | 13 +- src/views/Fill.vue | 31 +++ src/views/List.vue | 65 +++--- src/views/Results.vue | 9 +- templates/main.php | 25 +++ 32 files changed, 650 insertions(+), 430 deletions(-) delete mode 100644 css/colors.scss create mode 100644 css/forms.scss create mode 100644 css/icons.scss delete mode 100644 css/sidebar.scss delete mode 100644 img/app.png create mode 100644 img/clone.svg delete mode 100644 img/favicon-mask.svg delete mode 100644 img/favicon-touch.png delete mode 100644 img/favicon-touch.svg delete mode 100644 img/favicon.ico delete mode 100644 img/favicon.png delete mode 100644 img/favicon.svg create mode 100644 img/forms.svg create mode 100644 src/Forms.vue create mode 100644 src/components/AppNavigationForm.vue rename src/{App.vue => components/EmptyContent.vue} (56%) create mode 100644 src/mixins/ViewsMixin.js create mode 100644 src/services/FormsService.js create mode 100644 src/utils/FormsUtils.js create mode 100644 src/views/Fill.vue create mode 100644 templates/main.php diff --git a/appinfo/routes.php b/appinfo/routes.php index 764a3b7..b973073 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -24,12 +24,14 @@ 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'], diff --git a/css/colors.scss b/css/colors.scss deleted file mode 100644 index 6495a93..0000000 --- a/css/colors.scss +++ /dev/null @@ -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); -} diff --git a/css/forms.scss b/css/forms.scss new file mode 100644 index 0000000..93649ee --- /dev/null +++ b/css/forms.scss @@ -0,0 +1,23 @@ +/** + * @copyright Copyright (c) 2020 John Molakvoæ + * + * @author John Molakvoæ + * + * @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 . + * + */ + +@import 'icons' diff --git a/css/icons.scss b/css/icons.scss new file mode 100644 index 0000000..a799705 --- /dev/null +++ b/css/icons.scss @@ -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); +} diff --git a/css/sidebar.scss b/css/sidebar.scss deleted file mode 100644 index eb8cf38..0000000 --- a/css/sidebar.scss +++ /dev/null @@ -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; - } - } - } -} diff --git a/img/app.png b/img/app.png deleted file mode 100644 index cf801c0f11295322d2779891dfaa0d4d2cc4f096..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv^#Gp`S0MeL2(Zr9%Mz%RrzFTP zn1QXmqx0~QqfeebdoIGfbR$sQ!PCVtL}Oxdf&z2L8WR`M4VJ|-8vpW$s4%czn`3$Q z0JE?KgUF2HXDq84&dzk^$uVeTSkUmn$HaLhqg$-k!p#i7RSJIYc$P60XcmK~tDnm{ Hr-UW|5PMb$ diff --git a/img/app.svg b/img/app.svg index d85219c..63cfdc3 100644 --- a/img/app.svg +++ b/img/app.svg @@ -1 +1,8 @@ - + + + + + + + + diff --git a/img/clone.svg b/img/clone.svg new file mode 100644 index 0000000..469fd1b --- /dev/null +++ b/img/clone.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/favicon-mask.svg b/img/favicon-mask.svg deleted file mode 100644 index 094e556..0000000 --- a/img/favicon-mask.svg +++ /dev/null @@ -1,45 +0,0 @@ - -image/svg+xml \ No newline at end of file diff --git a/img/favicon-touch.png b/img/favicon-touch.png deleted file mode 100644 index dec255f4470ded7fad3f557571a9626f1245c23b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10238 zcmcI~WmHtr+wUHRQa~{1RFDo4q+t+6KpK=TK|(qO1ZD;s5Ks`1Mrn`^=^2#+;#6-?_KM?>&}-mdp~;NSH|F-aw-fh8{)JJf^kBsgH3D6EhdRQnpsRUL*B)8$Y#&?$8bgv`(G0A3Mie#>suq;KuQ=pUi}1 z5Ch6S`nFdHf6Hp^)*~1Rrt%3@kwwS!T510indukGw=-6%XJhCC+O37RMxwt&4`r~Z z0kqa;<>xBRYWu#p`snPqi{XC8X1dk5^hv|^qi~2NhrhXj+2yTzAH9;N4#cHZ@tc07 zo!JMEslh(A9qrWnPVL^1hFqpgwjQ^PJwiJt)b0XMv%afs$t9^nmHyet%wR=es|{k5 zMs1S9A^`|h$&>wA^QP3^u<*oQ6es==;?>E&|D&DT zkp8&4)Nn4Y$%Z-5gB^fWzDp{LpV|&?6D}tXs?Po56b%I6DdygBj3!E7qPlp~Z;kw9 zlp0|7O8p|bT!pv}HHR8&O82K;Q?moKVZLRJ|Fp<_?7^QlNt^3_05ll9ew8CQ&osRn zaJ(zZssO+qf1ED%RLbI#EHgr02bO;!w+QBYWyzmS5Ov^0YHxQ;S{D^+37n0fFmW{ zg#L)*Le*2`NM}1=s_9$~ipl$bR7yJ303I_I8gJ1w_Us@Hhq~jCy?!c7NmIDAk z{cJ5^(QSbfGGq|~fGSg4>A07W6DS{$pGtW9GD_2#Ys-z{n+{~3PiZiz$!_D*vnLnA z5cdG6`&4F1@yKd+!;FpFvfKB5W{6&C%4ZjwkHf> z!;m&|X(`^;B|>3CklINMUknH05pC8IP%cL1=0ib6SK<#q4)Sa2bSDlUTwgos%B=of zYR%RT`pJ}cc6Mq^Shezby~?h-H}^O`tkULg3m@rAmI1BgidW4Smk6@+ zjHHVxYzH3Rm)}cjl3#xQmbHX2#J54!{^HBctTUIN(@Zr^y|TC-ZBB5F*u=^^T9}L% zmvUGRk8`r(LrZgO`CqLuz56~Zy2zT>_Vc#>l8{O|>N84{ka8k+*u8{FClsDYZewhx z*iLyf+x)sNd7P88dbqb<{m6enB%*y34v%7Eh^gc(?0xF)l_i)u?y1KnhM4XSIw`5o))ww!-6jHcVAnz#8^4<1JcPib(^w}OHj*zXC|>0&r2ly zf<{U8ib6~ULB4WyecA9*hL_d7Z~Q1njq%DXyk|==jS{)ELR$kN*{%G~9rjud&W@<; zj8)ZzMWLfQC!LfkUfJmlj^{K=+q8tthU4zDcq*jx^qJfU$tH>Hmc-4Ta2`7;VTi7} zw4_dpcK$H2v&@84S;^eXLJav$ety(Nb-KGyi%UcTPiU)gv0`vrlJ3}w;*Yp{k1H&F zb7l5m@y&VY9`;6<`%H$=Cma*{inX@$-`u$BxP7C=)Ii(mDF;NBAUU*Nk=vLVE*@)@ zMI!ILToww+>$zh(zL#&K&n%)uewi!9%>Uyaf#B}XBZPg>NRhewqud~X;b z4pCA}ve69}$$O|4$i^AfkJ4;5steu&XlHbD$d4|CKX3L3A(1a9Pw@NnunL6)Fb1*aiIXq$Yfzgtr)Q~f3LBuYWJmp>7sJl`B z44G}|qDjbQ;J39cTEB+eHePIdy>`4FJk((p-$2QK_u z4D^$1I7}4k+Ys$>myC*}l=|nUij*D0tUmYjhcrt#pE;sPCf>)VnGb&1+YYH+4>u3$ zr$bj9+=KzlXcFIu4nSTEYtoPBFn^EKm)A|E@%?C@!@c*#-3^RYbl^0RU|k=r(n)n3 z5zKddMiKQ^`0f{{9pcY&H{M!`0FC{X{^$oN%2W^ zvVYgm3~C8zA}a~?3s-|NbZq>(e~02MM>dL;;&)&GoJ9}q5hAcy(XTaeH%I{B1$LWI zJO?utnd+wf<)qP2mu_g)OkcV4j~6#oL5ai)Pw?h{Wq)X!CxVC!im+?(&wL}u zI|orMvctF!l>jt%^*2Bq^&avWhD_QM0y1a{*H!h#d=^T zrL3SeA3B*0>4@#>T$O_%0C)+AK`B=*MTDtfeW%i?ssGmz!Zj>ZC+)G#-Ya|nl6fue zYDg5;lH%OC|G15P$X#i&i2Adv)<0LtL5;*Df^%J^Y;|Fj;;+`7^SCe66h|9zCjs7_ z|G1>$Ru<{^rlkWZ+ zErWSP#aB$vgY}Ug@z+VPs|&Cj=n_ZkAeAa>{H~Lt2xonZ54gId*=;5wNG5~J^y(&(=jdXn7gQGql_d^S3T-Ss zngfV|RV6CWO_%NZ$bu~DEP8IJW9!g{;p+_9JvlGqHN^Ctlo~D`N!xaPAtEq1qcU(n z_9&N~L~-komV~kJ3o(6`%~lPn)R(@~gLRJW6_1hYddH=U7$1#Am-{;QA5YhpMpe_8%U|^&6T~ z3fzons6+b7Jqf(t@-TYhu92Ps=}dH1phhdtS%3eDmsQ^^InSZDV^>uS*1jLTl72f; zvgKgImH`+5pPS>BEIrbzBsK8y$RHU%AXPkUJsJOCZWOxSiRtn^fMY?<_YPS099_C` zqFfmRZgjTg1c(m-RsUYol*S(CaIGJ*f2h%OtYFct5clR)O2QkvTo(ualRwSEWFp{) zJV5$T{BdKK8vn^d78^JAQzn7_j^`wi6*xMnhi{T9h5Om0mYI#P14^`aQ~z#Y)+h~v zidST0T>d=D)2H?sEr3r}r*M2IiYw}qQOTMPm)w(5g;I2sEoI^qIY}z56HEs9;ve8RNdEnDTQ0OAOhQK@nRYu-7waD%jM? zUlnDAqznkBS7d1d~^lz@=4GMw4(0e zuaABs5u7ClAOG-DYAa{%VXk-}8n+P-E(wG<%M0iR z^Q$O#1g}T$mhA7Z26;e1^du++vdpZZf@Y$MFz>M*@~gy1Sf!vHvy9!GIM~6HZQ11P z&YuCK*cZzt)Aa!nO${k}ox+03^&OFy5wUwK3bE{o@KOojkmYuSn+OmbewA%qVZf3a zA~GsZLto@3o7zna1?-XCVFjKvoiJneIp*+g*+w6plq%Q@hK8*##agp4rG!?P3@mup zEykwIZ&nkbVeYf{S3PbmJEXK><^=wQ_!G^RAq7k5b}Ez?N!}Hs=y6E?VEmeTZP^EF zKnlXQO;8Q5Ff8Gw{>CQ{r+cYf&Y3}SQB@@Z!!NTw89TBjgkmry9bW_1fWz~P$IaRF zpN87wq{rRME)plwK#D+FKeZj-4%^uMB z>t(?4)aI3$G^zFZh)SO~^Rjm~8+&4Uevhi9NX^>ZRNyZ6e$#TA195JAP*Q9ZATM@5 zsl;qr?b3an*pFmap!?#j+1Tk-wUy2_Yt!^2d3wVQu^<5qp4F}Y@Is|x*yI%$X=Q)T%bsqO}!PhSu#DWqB5n-Ow9;(-c!$XiI$%jskro_ z5Xg4$mJ4p>bF_~tF^d?URTwxp@rNr$QKDDfCyZ_pYe_UAoro4Z19}jeE&kp=^%SnR=p*vk-QDE;J z6NrZt&!4tM$G^zTaZP~Qea9C%COeR1ET~ctol)IX3e!=;Ke?+rR-Wy51=CMuWBueZ z6a(R!KbS$xd;2Uy$Jy6DygMt9AIBHKytya#}e`!6P6Qrt^rtz$pys;P)hUV(hk@M%>{XMfTU^F_$Xt zMs14DXC_jRD&9D4$2rc2z4Gvb3KvyL-w2h0s0?=6yxnOOd~#~XrDvA(CT)I@U*6@^ zV?sOTI4xjy>1Cf*)M?EVDO|k<@)jZ3P^Ibq!WEA{OnkEGH2kx$;44)o*J3T%t4+}s zkW-o1g;%LPe1!Ky3NepUNV09lV)MB9CNg)YG+$AoP4=hrN2VJ)m6A-`!)A_p?yqW! zf?iAW0mfU|-M2HNGd31q?9bzT=WW7aIvu7YanlD`o27d=^XgeQeScf^o<5jB%1k0k zp;CO*#?GdpAwQp;v8~8l|8RiayEg4!W|Wy?K}z=#6&1lG3Qy{o#BT6eH0-THDMr$cKK6>-R?(LE3DnP) z);+Pg)llQ%?iOs8^*ty-C`O9{y_D@(9uINTbp0)@eYk@Kgf|nHWv4%8bEg|SGAD#W zovq_5#m`YnwB?x6{s>uw0SNQ{UojyT{P(Ex z{}bX&2>FK>tswFLPl(eD@^I0R!JF=}K6a?Th91jj`pxV=l#`HPh4ai$&8#Rv8=IC#y5_w|pn%21 zBUc-~E+C}ooiZDGouTS>^A?2WC(Y_=G8taI%(gD*zahiwR+Bkj9asn;AnSiWU=(_A zvfnH^_)myi{PL*mribF0dUZLxw^K>ngvX9<>KXnCYjF%rk+Z%(757I(W!k_Z7BN)i zeJc@85AkPrT?wuHnClR0@+xZzDjuHeMDA-$e{N%-;^k1eX&WIqx<&Kf=U00cfnxpfM~rVn)_o)0?gI%!7eK$)@0Jnl9=m3?FqxD-Lk z27_GaHs&$&DCNKjnahIP_5>hY3Ru(@Fhtu2{jl^`xSew8;FYE9Y1`@^?_(d4Y2ISx z^q+Ew$aq|)Wf&4LP-$eQtuPTAEE^T55at+_5jToOZvBw@@S z$L62O!}9`Fa&R7On{0Uc8dS>nsRJ&n?a4&KdJ@8fPQrG8+mfq%Kz?=8!Rc<^Q49eA zemb>$7vdY*T6;`{_1soEnV9^D(9^_Ep?-6YX+1p;YV`f3*GgQ8uuIMa)pb+^Rm1w& z+z6}t6a~Dr-1xj9u<}U%JU~Z;oo6|;ntv>~8!SvCGxN18%YOqg*RwWgaRhTm^=+K2 zQE-6mJ8xEr>dPwlERJ@9WX9gn&;y26y6uxIL>z0<%P}`Yh|irn<5@0-#@_~$U6yob z&{c-`-K?#tbCM-1fhwl0k%#`((Bt%GOwG81257t?86(!&-kkzzMgfX7K4)`1i*SvQ2f%U?DpJlKHe1UA{~Lxi2JLsSWF ze5-|b+#~@MpMX)T^L=t)ScZv9tk(J5Ka0kHH}*9yRGwl6?;X#>CLLW5JWYQ&^QuLwP20BAtg_bGO`d9EB(eu&Ylc)~lZm1c2@ttM25U{+$;4N@G%9=#OsziTDD z`k)s~%yB5WoBznZC#Af_9wXWm|HxZkf0m-_0W^RUqi2s4Fnq-u%cIsR^?w`7%yP~;F9-+yRdBajl4aKz4q%D^4T&K_e*sui02G1yMUJX7 zG>{2waNMR2b2_+=C1C70YI$=ac*$;zwSV{kHCX`JCv0eyq z%Tc+4A0N5-*9^%+sRYY~yR$n^+W*FpSXv{GDE(=u6?TvmU1M zW>?3UF$`FyEVe#(Up=}DpDf4-vZ@^&;+7XA_ssHo)Uj5CqApv_wU8gv0UWNTF*Qd` zt-997|tro;es5*HnIA zeIpMZ_|CM}c)q&*kE`%Sw*%5yfAb5_8KG;;a41zr^hWg}nPkYmZT1}>w3B3hIVVqd zafYi$;>_p1^4=e|YJ)kp6|CaOgsacrn%VDXFg{-98NNC%_KRBU(#BKsbUD=l{;GaE zrm4A=_rBj^F;{K7=VeP}IWBVzkfHX5qCR)4W1Pv}Wvv=q$aIR@35*jLV4j*QH_{7{R@y!g1WQK~6M{ z-u##2;|bCsTBi3r>tfdzt`JlfBR?rj{un8za{K;PSu$s^+-C=~^^(feV8ovPmB$rD za^n?Ej18ep!P`Q+_Q1~LB!*u^73TV>%_$RIegODeDS>E`Jh40QH(5u z)YoKTSJ&gL8vJjcbbpQk?|f&R%)cpgZoL$lv6(Qs zoeiCT2L_cMu@_mp=+;OGKl9aev2!`PGip|qKcd{p44sZo9am&^p3kgp%6%<1vFw`N znNt!gKxkTpz8X;EiRWqX=W~5g)dHK&%5urI`&M2qzxJc4?)0#nU5;n#_M-Z<(VKw9 zAN7s8j*K#8b8js6;eaDkwkC9EE(e=)LB8Zi)8(<5C=DZRIsD-MN}_q3l0=HDBkq$*jOYjvraORUo9!orVGHs zft6k<_V=#pO5*6T8JDc~Txespk4MiKy5LU(9y z?bVX~t3j*^w~AQgdhXmPe6gCDx?QS1UmDF0fJJe-piG$ooU7-8Sn|4oAzrIR_pvAO z;|tz4eznuB?i%VdH5LHq)o9Sk-nFzm8(nHLeKw$PzJ9eksAY(eB+%yPvE>@UJCb{p zVbh2c0K*RJ><#w(*S#0-K6+~4Xyh7+tPgY9p0_d;^|S6Wq}gVYzu~ML&_yP{vZQ&| z^CuawQu5R2=53cVT{@oLLpG$>ucxON980t|j6AwmHDXo!G5XuHgPgVp2!EcV68w$5 zfVJ+b7K$}o6=vDs%4fZ#lV0c}1|i0lUn8NtH%bJdH=@5^8El;LQ%W&@=04Dw0{FlgGO zOy$Kqa#{$*2aai_6d2vvj5QV^&f?UCHmHW3-Hm#BJ3jV2FQjM2Q#-w4KZJ-#d%1`s zq)=LP`MwhgpF`bdvhpIIGW4PjXe2+9$-uboDBoKdwHrk$Su>58|}0JNR1U z&OvQ`06IB6jEEPBsHAdi%5xFW%FA(08g?D*s>^k$4R;&~^mP<_?8q!qc7xEoBHbpk zYmV!zy)r&aXj-6q8OIGtiWpb-vJIhzIWb%TAh%T4ZnTrLx@G}~c0co71L}uF=CsEv z>|vu#6rX8MPw@=#Dk?|KLWmXqJCQcD}Ui=i;Sg z#4S;`H+1I_&R2sYE~PsqEte>`lSAIFp8I^>MnyGED1DFUlY`nbdx6(QLX8fo4j#`+ z1d>-nQlD?fdJR;^ajwZhsrYzJ+BeBGWWcd@%$TwMC0V8KcEZ}w*$LsPkJOPRPm diff --git a/img/favicon.ico b/img/favicon.ico deleted file mode 100644 index b5c8ac6b69b4667e6e20205a6b2f683bebbef5b4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4286 zcmeHL!A`rK3}rL(~ge6^UB zA36CxTfCStzxDh$@3O735A)gb*Js~rO!K@}=|Q};`f`R}nSZH?$x*$}4>+DWz#5t{ z_4RK34Rhv!wQ#ilD!FJ*{%lQ$|6JZ{(!U}PmA^mx`d8q4{j2!@@%mS+53hy)TMNDZ zUF`nv`2O3z{$-*o5w)eJ{of?+qgR)A&u0Wch@gzgzDTe0b49!5s zNrt8qU=qjxqElcJ!iJJ;t*6?LJnK06tn=uz!;d~4dGz_{mtpNfq z7Z1tmt^0jnO{lNb?7sh}m|ZGABag0Mb>*_=A%S_%4R@Yeu{$*{yKef5C3pRF4f5{u z1aM4Sy`Skee?!8)U6VI1+`Eg{Am{# diff --git a/img/forms.svg b/img/forms.svg new file mode 100644 index 0000000..63cfdc3 --- /dev/null +++ b/img/forms.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 1e2956b..982ffb0 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -7,6 +7,7 @@ * @author Inigo Jiron * @author Natalie Gilbert * @author Affan Hussain + * @author John Molakvoæ * * @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'); - } } diff --git a/package-lock.json b/package-lock.json index 44a68f3..00a8486 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", @@ -10977,6 +10993,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", diff --git a/package.json b/package.json index 039863e..e1e553e 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,9 @@ }, "dependencies": { "@nextcloud/axios": "^1.3.2", + "@nextcloud/dialogs": "^1.2.2", "@nextcloud/moment": "^1.1.0", + "@nextcloud/router": "^1.0.2", "@nextcloud/vue": "^1.4.1", "json2csv": "5.0.0", "vue": "^2.6.11", diff --git a/src/Forms.vue b/src/Forms.vue new file mode 100644 index 0000000..98007c5 --- /dev/null +++ b/src/Forms.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/src/components/AppNavigationForm.vue b/src/components/AppNavigationForm.vue new file mode 100644 index 0000000..8305cad --- /dev/null +++ b/src/components/AppNavigationForm.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/src/App.vue b/src/components/EmptyContent.vue similarity index 56% rename from src/App.vue rename to src/components/EmptyContent.vue index 7a042c7..7047d18 100644 --- a/src/App.vue +++ b/src/components/EmptyContent.vue @@ -1,7 +1,7 @@ diff --git a/src/main.js b/src/main.js index 8d09de4..e662a15 100644 --- a/src/main.js +++ b/src/main.js @@ -1,4 +1,3 @@ -/* jshint esversion: 6 */ /** * @copyright Copyright (c) 2018 René Gieling * @@ -23,7 +22,7 @@ import Vue from 'vue' import router from './router' -import App from './App' +import Forms from './Forms' import VueClipboard from 'vue-clipboard2' import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip' @@ -51,7 +50,7 @@ __webpack_public_path__ = OC.linkTo('forms', 'js/') /* eslint-disable-next-line no-new */ new Vue({ - el: '#app-forms', + el: '#content', router: router, - render: h => h(App), + render: h => h(Forms), }) diff --git a/src/mixins/ViewsMixin.js b/src/mixins/ViewsMixin.js new file mode 100644 index 0000000..d7e8307 --- /dev/null +++ b/src/mixins/ViewsMixin.js @@ -0,0 +1,29 @@ +/** + * @copyright Copyright (c) 2020 John Molakvoæ + * + * @author John Molakvoæ + * + * @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 . + */ + +export default { + props: { + hash: { + type: String, + default: null, + }, + }, +} diff --git a/src/plugins/plugin.js b/src/plugins/plugin.js index 04c76a7..ad83016 100644 --- a/src/plugins/plugin.js +++ b/src/plugins/plugin.js @@ -1,4 +1,3 @@ -/* jshint esversion: 6 */ // we need our modal component import ModalDialog from './ModalDialog' diff --git a/src/router.js b/src/router.js index db40d9d..9554db7 100644 --- a/src/router.js +++ b/src/router.js @@ -1,4 +1,3 @@ -/* jshint esversion: 6 */ /** * @copyright Copyright (c) 2018 Julius Härtl * @copyright Copyright (c) 2018 John Molakvoæ @@ -22,59 +21,56 @@ * along with this program. If not, see . * */ + import Vue from 'vue' import Router from 'vue-router' +import { generateUrl } from '@nextcloud/router' + +import Create from './views/Create' +import Results from './views/Results' -// 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', - components: { - default: Create, - }, - 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, + path: '/new', + component: Create, name: 'create', }, + { + path: '/:hash', + name: 'fill', + props: true, + }, + { + path: '/:hash/edit', + component: Create, + name: 'edit', + props: true, + }, + { + path: '/:hash/results', + component: Results, + name: 'results', + props: true, + }, + { + path: '/:hash/clone', + component: Create, + name: 'clone', + props: true, + }, ], }) diff --git a/src/services/FormsService.js b/src/services/FormsService.js new file mode 100644 index 0000000..95a8bd4 --- /dev/null +++ b/src/services/FormsService.js @@ -0,0 +1,53 @@ +/** + * @copyright Copyright (c) 2019 John Molakvoæ + * + * @author John Molakvoæ + * + * @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 . + */ + +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 } diff --git a/src/utils/FormsUtils.js b/src/utils/FormsUtils.js new file mode 100644 index 0000000..4d102b1 --- /dev/null +++ b/src/utils/FormsUtils.js @@ -0,0 +1,44 @@ +/** + * @copyright Copyright (c) 2020 John Molakvoæ + * + * @author John Molakvoæ + * + * @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 . + */ + +/** + * 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.formQuizQuestions, + }) + + // cleanup + delete newForm.options + delete newForm.event + + return newForm +} + +export { formatForm } diff --git a/src/views/Create.vue b/src/views/Create.vue index 8af5bc8..b807838 100644 --- a/src/views/Create.vue +++ b/src/views/Create.vue @@ -26,7 +26,7 @@ -->