Alan Colon il y a 7 ans
Parent
commit
75da8c2557
47 fichiers modifiés avec 12052 ajouts et 1291 suppressions
  1. 0 27
      app/api-service.js
  2. 0 18
      app/app-index.js
  3. 2 21
      app/app.js
  4. 0 1
      app/assets/app-index.js
  5. 0 0
      app/assets/app-style.scss
  6. 0 186
      app/assets/generic-logo.svg
  7. 0 16
      app/assets/index.js
  8. 0 37
      app/assets/style.scss
  9. 0 31
      app/async.js
  10. 0 1
      app/components/app-index.js
  11. 0 21
      app/components/crud-pages/README.md
  12. 0 70
      app/components/crud-pages/details.js
  13. 0 80
      app/components/crud-pages/index.js
  14. 0 77
      app/components/crud-pages/list.js
  15. 0 0
      app/components/crud-pages/options.js
  16. 0 69
      app/components/crud-pages/trash.js
  17. 0 13
      app/components/dashboard-page.js
  18. 0 20
      app/components/home-area.js
  19. 0 11
      app/components/home-page.js
  20. 0 8
      app/components/index.js
  21. 0 33
      app/components/login-page.js
  22. 0 15
      app/components/test-page.js
  23. 0 58
      app/components/user-area.js
  24. 0 31
      app/components/user-pages.js
  25. 1 4
      app/index.js
  26. 0 10
      app/routes.js
  27. 3 52
      bin/project.js
  28. 0 0
      lib/controllers/app-index.js
  29. 0 3
      lib/controllers/auth/index.js
  30. 0 30
      lib/controllers/auth/login.js
  31. 0 46
      lib/controllers/crud-controller.js
  32. 0 4
      lib/controllers/index.js
  33. 0 6
      lib/controllers/user.js
  34. 0 37
      lib/crud-route.js
  35. 0 1
      lib/database/app-index.js
  36. 0 12
      lib/database/index.js
  37. 0 3
      lib/database/sequelize.js
  38. 0 13
      lib/database/session.js
  39. 0 41
      lib/database/user.js
  40. 0 8
      lib/routes.js
  41. 2 31
      lib/server.js
  42. 12037 40
      package-lock.json
  43. 5 2
      package.json
  44. 0 16
      test/_common.js
  45. 0 72
      test/auth-test.js
  46. 0 14
      test/server-test.js
  47. 2 2
      webpack.config.js

+ 0 - 27
app/api-service.js

@@ -1,27 +0,0 @@
-const app = require('./app')
-
-app.service('api', function($http) {
-  let opts = {
-    headers: {},
-    withCredentials: true
-  }
-  const api = (req) => req.then(res => {
-    // Enter post-processing here
-    return res.data
-  })
-  this.login = data => api($http.post('/api/auth/login', data, opts))
-  this.setToken = token => {
-    this.token = token
-    opts.headers.authentication = `Bearer ${token}`
-  }
-
-  this.crud = (apiPrefix) => ({
-    list: () => api($http.get(`${apiPrefix}`, opts)),
-    create: data => api($http.post(`${apiPrefix}`, data, opts)),
-    read: id => api($http.get(`${apiPrefix}/${id}`, opts)),
-    update: (id, data) => api($http.patch(`${apiPrefix}/${id}`, data, opts)),
-    delete: (id) => api($http.delete(`${apiPrefix}/${id}`, opts)),
-    trash: () => api($http.get(`${apiPrefix}/trash`, opts)),
-    undelete: (id) => api($http.delete(`${apiPrefix}/trash/${id}`, opts))
-  })
-})

+ 0 - 18
app/app-index.js

@@ -1,18 +0,0 @@
-const app = require('./app')
-// TODO: Register app specific services
-app.config(($routeProvider, $mdThemingProvider) => {
-  // TODO: App Title
-  window.title = 'My App'
-
-  // TODO: Select a theme
-  const palettes = ['red', 'pink', 'purple', 'deep-purple', 'indigo', 'blue', 'light-blue', 'cyan', 'teal', 'green', 'light-green', 'lime', 'yellow', 'amber', 'orange', 'deep-orange', 'brown', 'grey', 'blue-grey']
-  const randomPalette = () => palettes[Math.floor(Math.random() * palettes.length)]
-  $mdThemingProvider.theme('default')
-    .primaryPalette(randomPalette())
-    .accentPalette(randomPalette())
-    .warnPalette(randomPalette())
-
-  // TODO: App Routes
-  //  $routeProvider.when('/test', {template: '<app-test-page />'})
-
-})

+ 2 - 21
app/app.js

@@ -1,24 +1,5 @@
 const angular = require('angular')
-const routes = require('./routes')
-require('angular-material/angular-material.css')
-require('angular-material-data-table/dist/md-data-table.min.css')
-require('angular-route')
-require('angular-material')
-require('angular-material-data-table')
-require('./async')
-window.jQuery = require('jquery')
+require('material-framework/app')
 
-const es6Html = require('es6-string-html-template')
-window.html = es6Html.html
-window.raw = es6Html.raw
-window.encode = es6Html.encode
+const app = angular.module('app', ['material-framework'])
 
-const app = angular.module('app', ['ngRoute', 'ngMaterial', 'async', 'md.data.table'])
-
-app.config(($routeProvider, $locationProvider, $mdThemingProvider) => {
-  routes($routeProvider)
-  $locationProvider.html5Mode(true)
-})
-
-
-module.exports = app;

+ 0 - 1
app/assets/app-index.js

@@ -1 +0,0 @@
-// TODO: App specific assets

+ 0 - 0
app/assets/app-style.scss


+ 0 - 186
app/assets/generic-logo.svg

@@ -1,186 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<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:xlink="http://www.w3.org/1999/xlink"
-   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
-   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
-   width="1425.8217"
-   height="353.73798"
-   id="svg4692"
-   version="1.1"
-   inkscape:version="0.47 r22583"
-   sodipodi:docname="New document 8">
-  <defs
-     id="defs4694">
-    <linearGradient
-       inkscape:collect="always"
-       id="linearGradient5225">
-      <stop
-         style="stop-color:#2294fe;stop-opacity:1"
-         offset="0"
-         id="stop5227" />
-      <stop
-         style="stop-color:#014f96;stop-opacity:1"
-         offset="1"
-         id="stop5229" />
-    </linearGradient>
-    <inkscape:perspective
-       sodipodi:type="inkscape:persp3d"
-       inkscape:vp_x="0 : 372.04724 : 1"
-       inkscape:vp_y="0 : 1000 : 0"
-       inkscape:vp_z="1052.3622 : 372.04724 : 1"
-       inkscape:persp3d-origin="526.18109 : 248.03149 : 1"
-       id="perspective4701" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5225"
-       id="linearGradient5284"
-       gradientUnits="userSpaceOnUse"
-       x1="-467.57132"
-       y1="-68.9729"
-       x2="-469.87463"
-       y2="488.42743" />
-    <linearGradient
-       inkscape:collect="always"
-       xlink:href="#linearGradient5225"
-       id="linearGradient5311"
-       gradientUnits="userSpaceOnUse"
-       x1="-467.57132"
-       y1="-68.9729"
-       x2="-469.87463"
-       y2="488.42743" />
-  </defs>
-  <sodipodi:namedview
-     inkscape:document-units="mm"
-     pagecolor="#ffffff"
-     bordercolor="#666666"
-     borderopacity="1.0"
-     inkscape:pageopacity="0.0"
-     inkscape:pageshadow="2"
-     inkscape:zoom="0.30699632"
-     inkscape:cx="642.17049"
-     inkscape:cy="175.65506"
-     inkscape:current-layer="layer1"
-     id="namedview4696"
-     showgrid="false"
-     inkscape:window-width="1099"
-     inkscape:window-height="851"
-     inkscape:window-x="605"
-     inkscape:window-y="226"
-     inkscape:window-maximized="0" />
-  <metadata
-     id="metadata4698">
-    <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></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <g
-     inkscape:label="Layer 1"
-     inkscape:groupmode="layer"
-     id="layer1"
-     transform="translate(364.42539,8.4822578)">
-    <g
-       id="g5286">
-      <g
-         transform="translate(-14.426456,-21.336377)"
-         id="text4703"
-         style="font-size:227.36433411px;font-style:normal;font-weight:normal;fill:#666666;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans">
-        <path
-           id="path5264"
-           d="m 145.494,192.3677 0,19.09505 c -5.77303,-3.1824 -11.58295,-5.55078 -17.42979,-7.10513 -5.77301,-1.62815 -11.61994,-2.44228 -17.5408,-2.44239 -13.248182,1.1e-4 -23.535816,4.21878 -30.862934,12.65602 -7.327209,8.36342 -10.990791,20.13129 -10.990757,35.30364 -3.4e-5,15.17247 3.663548,26.97735 10.990757,35.41466 7.327118,8.36335 17.614752,12.54502 30.862934,12.545 5.92086,2e-5 11.76779,-0.77711 17.5408,-2.33137 5.84684,-1.62824 11.65676,-4.03362 17.42979,-7.21615 l 0,18.87301 c -5.69902,2.66443 -11.61996,4.66275 -17.76284,5.99496 -6.06906,1.33221 -12.54509,1.99832 -19.42811,1.99832 -18.725045,0 -33.601407,-5.88394 -44.629129,-17.65182 -11.027781,-11.76785 -16.541656,-27.64337 -16.541644,-47.62661 -1.2e-5,-20.27916 5.550869,-36.22869 16.652662,-47.84865 11.175745,-11.61973 26.459172,-17.42965 45.850331,-17.42978 6.29092,1.3e-4 12.4339,0.66623 18.42894,1.99832 5.99486,1.25832 11.80478,3.18263 17.42979,5.77292" />
-        <path
-           id="path5266"
-           d="m 228.97934,201.91523 c -10.95381,1.1e-4 -19.61318,4.29279 -25.97815,12.87805 -6.36506,8.51145 -9.54756,20.20531 -9.54753,35.08161 -3e-5,14.87642 3.14547,26.60729 9.43651,35.19262 6.36497,8.51138 15.06135,12.76706 26.08917,12.76704 10.87966,2e-5 19.50203,-4.29266 25.86713,-12.87805 6.36492,-8.58534 9.54742,-20.2792 9.54753,-35.08161 -1.1e-4,-14.72828 -3.18261,-26.38513 -9.54753,-34.97059 -6.3651,-8.65928 -14.98747,-12.98896 -25.86713,-12.98907 m 0,-17.31877 c 17.76275,1.3e-4 31.71397,5.77304 41.85369,17.31877 10.1395,11.54594 15.2093,27.53248 15.20943,47.95966 -1.3e-4,20.35329 -5.06993,36.33983 -15.20943,47.95966 -10.13972,11.54585 -24.09094,17.31877 -41.85369,17.31877 -17.8369,0 -31.82512,-5.77292 -41.96471,-17.31877 -10.06562,-11.61983 -15.09842,-27.60637 -15.09841,-47.95966 -1e-5,-20.42718 5.03279,-36.41372 15.09841,-47.95966 10.13959,-11.54573 24.12781,-17.31864 41.96471,-17.31877" />
-        <path
-           id="path5268"
-           d="m 416.59933,211.46275 c 5.1067,-9.17736 11.21267,-15.94943 18.31793,-20.31625 7.10499,-4.36657 15.46832,-6.54991 25.09001,-6.55004 12.9519,1.3e-4 22.94348,4.55185 29.97479,13.65518 7.03093,9.02955 10.54649,21.90759 10.54669,38.63417 l 0,75.048 -20.53828,0 0,-74.38189 c -1.9e-4,-11.91582 -2.10952,-20.76022 -6.32802,-26.53324 -4.21884,-5.77282 -10.65786,-8.65927 -19.31708,-8.65938 -10.58384,1.1e-4 -18.94717,3.51566 -25.09001,10.54668 -6.14311,7.03122 -9.2146,16.61574 -9.21448,28.7536 l 0,70.27423 -20.53828,0 0,-74.38189 c -10e-5,-11.98983 -2.10943,-20.83423 -6.32801,-26.53324 -4.21876,-5.77282 -10.7318,-8.65927 -19.53912,-8.65938 -10.43573,1.1e-4 -18.72505,3.55267 -24.86798,10.6577 -6.14302,7.03122 -9.21451,16.57873 -9.21447,28.64258 l 0,70.27423 -20.53828,0 0,-124.33987 20.53828,0 0,19.31708 c 4.6627,-7.6231 10.25059,-13.24799 16.76368,-16.87469 6.51298,-3.62646 14.24721,-5.43974 23.20271,-5.43987 9.02935,1.3e-4 16.68957,2.29449 22.98067,6.8831 6.36491,4.58885 11.06465,11.24991 14.09925,19.98319" />
-        <path
-           id="path5270"
-           d="m 560.70036,293.28283 0,65.94454 -20.53828,0 0,-171.63343 20.53828,0 0,18.87301 c 4.29264,-7.40107 9.6955,-12.87794 16.20859,-16.43062 6.58699,-3.62646 14.43224,-5.43974 23.53576,-5.43987 15.09832,1.3e-4 27.34726,5.99508 36.74687,17.98487 9.47339,11.99002 14.21014,27.75452 14.21028,47.29356 -1.4e-4,19.53916 -4.73689,35.30367 -14.21028,47.29356 -9.39961,11.98992 -21.64855,17.98487 -36.74687,17.98487 -9.10352,0 -16.94877,-1.77628 -23.53576,-5.32885 -6.51309,-3.62657 -11.91595,-9.14045 -16.20859,-16.54164 m 69.49711,-43.40794 c -1.1e-4,-15.02432 -3.10861,-26.79219 -9.32549,-35.30364 -6.14308,-8.58527 -14.61743,-12.87795 -25.42307,-12.87806 -10.80579,1.1e-4 -19.31714,4.29279 -25.53408,12.87806 -6.14302,8.51145 -9.21451,20.27932 -9.21447,35.30364 -4e-5,15.02445 3.07145,26.82932 9.21447,35.41466 6.21694,8.51138 14.72829,12.76705 25.53408,12.76704 10.80564,10e-6 19.27999,-4.25566 25.42307,-12.76704 6.21688,-8.58534 9.32538,-20.39021 9.32549,-35.41466" />
-        <path
-           id="path5272"
-           d="m 741.77026,249.43082 c -16.5047,6e-5 -27.93951,1.88736 -34.30448,5.6619 -6.36505,3.77466 -9.54756,10.21368 -9.54753,19.31709 -3e-5,7.25319 2.36835,13.02611 7.10514,17.31877 4.81072,4.21869 11.32376,6.32802 19.53912,6.32801 11.32374,10e-6 20.39018,-3.99662 27.19935,-11.98992 6.883,-8.06725 10.32455,-18.76195 10.32465,-32.08412 l 0,-4.55173 -20.31625,0 m 40.74351,-8.43735 0,70.94034 -20.42726,0 0,-18.87302 c -4.66284,7.54922 -10.47276,13.13711 -17.42979,16.76368 -6.95718,3.55257 -15.46853,5.32885 -25.53408,5.32885 -12.73007,0 -22.86968,-3.55257 -30.41886,-10.6577 -7.47521,-7.17913 -11.2128,-16.76366 -11.21279,-28.7536 -10e-6,-13.98818 4.66273,-24.53486 13.98824,-31.64005 9.39946,-7.10506 23.38768,-10.65763 41.9647,-10.65771 l 28.64258,0 0,-1.99832 c -10e-5,-9.39941 -3.10859,-16.65256 -9.32549,-21.75947 -6.14307,-5.18072 -14.80244,-7.77113 -25.97815,-7.77124 -7.10519,1.1e-4 -14.02529,0.85124 -20.76032,2.5534 -6.73511,1.70238 -13.21114,4.25579 -19.42811,7.66023 l 0,-18.87302 c 7.47517,-2.88634 14.72832,-5.03268 21.75948,-6.43903 7.03107,-1.48011 13.87716,-2.22022 20.53828,-2.22035 17.9848,1.3e-4 31.41793,4.66287 40.29944,13.98823 8.88131,9.3256 13.32201,23.46184 13.32213,42.40878" />
-        <path
-           id="path5274"
-           d="m 928.50213,236.88581 0,75.048 -20.42726,0 0,-74.38189 c -1e-4,-11.76779 -2.29447,-20.57519 -6.8831,-26.42222 -4.58883,-5.84683 -11.47192,-8.77029 -20.6493,-8.7704 -11.02783,1.1e-4 -19.72421,3.51566 -26.08917,10.54668 -6.36506,7.03122 -9.54757,16.61574 -9.54752,28.7536 l 0,70.27423 -20.53829,0 0,-124.33987 20.53829,0 0,19.31708 c 4.88473,-7.47508 10.62064,-13.06297 17.20774,-16.76367 6.661,-3.70047 14.32122,-5.55076 22.98068,-5.55089 14.28418,1.3e-4 25.0899,4.44083 32.41718,13.32213 7.32705,8.80751 10.99063,21.79657 10.99075,38.96722" />
-        <path
-           id="path5276"
-           d="m 1021.2019,323.47965 c -5.7729,14.80234 -11.3978,24.46088 -16.8747,28.97563 -5.47688,4.51468 -12.80404,6.77204 -21.98147,6.77209 l -16.3196,0 0,-17.09674 11.98991,0 c 5.62487,-3e-5 9.99156,-1.33224 13.1001,-3.99664 3.10845,-2.66445 6.54999,-8.95544 10.32466,-18.87301 l 3.6636,-9.32549 -50.29107,-122.34155 21.64846,0 38.85621,97.25154 38.8562,-97.25154 21.6485,0 -54.6208,135.88571" />
-      </g>
-      <g
-         transform="translate(-416.34278,-21.336377)"
-         id="text4707"
-         style="font-size:102.52679443px;font-style:normal;font-weight:normal;fill:#666666;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans">
-        <path
-           id="path5241"
-           d="m 489.94918,115.05966 c -5e-5,-6.67489 -1.38509,-11.84795 -4.15514,-15.519195 -2.73676,-3.671159 -6.59152,-5.506761 -11.5643,-5.506811 -4.93947,5e-5 -8.79423,1.835652 -11.5643,5.506811 -2.73674,3.671245 -4.10509,8.844305 -4.10508,15.519195 -10e-6,6.64157 1.36834,11.79794 4.10508,15.46913 2.77007,3.67121 6.62483,5.50682 11.5643,5.50681 4.97278,1e-5 8.82754,-1.8356 11.5643,-5.50681 2.77005,-3.67119 4.15509,-8.82756 4.15514,-15.46913 m 9.21139,21.72687 c -5e-5,9.54513 -2.11934,16.63723 -6.35786,21.27631 -4.23862,4.67243 -10.72998,7.00865 -19.47409,7.00867 -3.23736,-2e-5 -6.29113,-0.25033 -9.16133,-0.75093 -2.87023,-0.46727 -5.65701,-1.20151 -8.36033,-2.20273 l 0,-8.96108 c 2.70332,1.46847 5.37329,2.55315 8.0099,3.25403 2.63657,0.70085 5.32323,1.05128 8.05997,1.0513 6.04077,-2e-5 10.56302,-1.58531 13.56678,-4.75589 3.00367,-3.13721 4.50552,-7.89309 4.50557,-14.26764 l 0,-4.55563 c -1.9024,3.30409 -4.33874,5.77381 -7.30904,7.40916 -2.97038,1.63536 -6.52477,2.45303 -10.66319,2.45303 -6.87519,0 -12.41537,-2.6199 -16.62055,-7.85972 -4.20521,-5.2398 -6.30781,-12.18171 -6.3078,-20.82575 -1e-5,-8.67736 2.10259,-15.635962 6.3078,-20.87582 4.20518,-5.239758 9.74536,-7.859662 16.62055,-7.85972 4.13842,5.8e-5 7.69281,0.817735 10.66319,2.453034 2.9703,1.635409 5.40664,4.105127 7.30904,7.409163 l 0,-8.510525 9.21139,0 0,49.110738" />
-        <path
-           id="path5243"
-           d="m 566.09334,113.40761 0,4.50558 -42.35237,0 c 0.40048,6.34119 2.30283,11.1805 5.70705,14.51795 3.43757,3.30409 8.21013,4.95614 14.31771,4.95613 3.53767,1e-5 6.95856,-0.43386 10.26269,-1.30161 3.33742,-0.86773 6.6415,-2.16934 9.91226,-3.90483 l 0,8.71077 c -3.30414,1.40174 -6.69166,2.46972 -10.16257,3.20397 -3.471,0.73424 -6.99201,1.10136 -10.56306,1.10136 -8.94442,0 -16.03652,-2.60322 -21.27631,-7.80966 -5.20645,-5.20643 -7.80967,-12.24846 -7.80966,-21.12613 -1e-5,-9.17798 2.46971,-16.453634 7.40916,-21.82699 4.9728,-5.406632 11.6644,-8.109972 20.07483,-8.11003 7.54262,5.8e-5 13.49998,2.436401 17.8721,7.309039 4.40539,4.839364 6.60812,11.430841 6.60817,19.774451 m -9.21139,-2.70334 c -0.0668,-5.03953 -1.48521,-9.06116 -4.25526,-12.06492 -2.73676,-3.003666 -6.37459,-4.505522 -10.9135,-4.505572 -5.13971,5e-5 -9.26147,1.451844 -12.36529,4.355387 -3.07048,2.903635 -4.83933,6.992015 -5.30656,12.265165 l 32.84061,-0.0501" />
-        <path
-           id="path5245"
-           d="m 627.61943,109.90328 0,33.84185 -9.21139,0 0,-33.54148 c -4e-5,-5.30652 -1.03466,-9.2781 -3.10384,-11.914733 -2.06926,-2.636546 -5.1731,-3.954842 -9.31151,-3.954891 -4.97285,4.9e-5 -8.89436,1.585342 -11.76455,4.755882 -2.87024,3.170632 -4.30534,7.492632 -4.30533,12.966032 l 0,31.68919 -9.26145,0 0,-56.069338 9.26145,0 0,8.710772 c 2.20271,-3.370784 4.78924,-5.890565 7.7596,-7.559348 3.00369,-1.668674 6.45796,-2.503038 10.36282,-2.503096 6.44125,5.8e-5 11.31394,2.002532 14.61808,6.007429 3.30403,3.971626 4.95607,9.828861 4.95612,17.571731" />
-        <path
-           id="path5247"
-           d="m 694.05159,113.40761 0,4.50558 -42.35238,0 c 0.40048,6.34119 2.30283,11.1805 5.70706,14.51795 3.43756,3.30409 8.21012,4.95614 14.31771,4.95613 3.53767,1e-5 6.95856,-0.43386 10.26269,-1.30161 3.33741,-0.86773 6.64149,-2.16934 9.91226,-3.90483 l 0,8.71077 c -3.30414,1.40174 -6.69166,2.46972 -10.16257,3.20397 -3.471,0.73424 -6.99202,1.10136 -10.56307,1.10136 -8.94442,0 -16.03651,-2.60322 -21.27631,-7.80966 -5.20644,-5.20643 -7.80966,-12.24846 -7.80966,-21.12613 0,-9.17798 2.46972,-16.453634 7.40917,-21.82699 4.9728,-5.406632 11.6644,-8.109972 20.07482,-8.11003 7.54262,5.8e-5 13.49999,2.436401 17.87211,7.309039 4.40539,4.839364 6.60811,11.430841 6.60817,19.774451 m -9.21139,-2.70334 c -0.0668,-5.03953 -1.48522,-9.06116 -4.25527,-12.06492 -2.73676,-3.003666 -6.37458,-4.505522 -10.91349,-4.505572 -5.13972,5e-5 -9.26148,1.451844 -12.36529,4.355387 -3.07049,2.903635 -4.83934,6.992015 -5.30657,12.265165 l 32.84062,-0.0501" />
-        <path
-           id="path5249"
-           d="m 741.46022,96.28644 c -1.03465,-0.600694 -2.16939,-1.034564 -3.40421,-1.301609 -1.20152,-0.300323 -2.53651,-0.450508 -4.00495,-0.450557 -5.20647,4.9e-5 -9.21142,1.702152 -12.01486,5.106315 -2.77011,3.370871 -4.15516,8.226881 -4.15514,14.568011 l 0,29.53653 -9.26145,0 0,-56.069338 9.26145,0 0,8.710772 c 1.93571,-3.404159 4.45549,-5.923939 7.55935,-7.559348 3.10381,-1.668674 6.87513,-2.503038 11.31399,-2.503096 0.63408,5.8e-5 1.33495,0.05012 2.1026,0.150186 0.76758,0.06681 1.61863,0.183617 2.55316,0.350433 l 0.0501,9.461701" />
-        <path
-           id="path5251"
-           d="m 751.22228,87.675792 9.21139,0 0,56.069338 -9.21139,0 0,-56.069338 m 0,-21.826994 9.21139,0 0,11.664426 -9.21139,0 0,-11.664426" />
-        <path
-           id="path5253"
-           d="m 820.00736,89.828454 0,8.610649 c -2.60326,-1.435062 -5.22317,-2.503048 -7.85972,-3.203963 -2.60326,-0.734192 -5.23985,-1.101312 -7.90978,-1.101362 -5.97408,5e-5 -10.61315,1.902401 -13.91721,5.707058 -3.3041,3.771374 -4.95614,9.077924 -4.95613,15.919684 -10e-6,6.84182 1.65203,12.16506 4.95613,15.96975 3.30406,3.77134 7.94313,5.65701 13.91721,5.657 2.66993,1e-5 5.30652,-0.35043 7.90978,-1.0513 2.63655,-0.73423 5.25646,-1.81891 7.85972,-3.25402 l 0,8.51052 c -2.56989,1.20149 -5.23985,2.1026 -8.0099,2.70334 -2.73676,0.60075 -5.65703,0.90112 -8.76084,0.90112 -8.4438,0 -15.15209,-2.65328 -20.12489,-7.95985 -4.97282,-5.30655 -7.45923,-12.46539 -7.45922,-21.47656 -10e-6,-9.1446 2.50309,-16.336822 7.50929,-21.57668 5.03954,-5.239758 11.93139,-7.859662 20.67557,-7.85972 2.8368,5.8e-5 5.60689,0.300429 8.31027,0.901115 2.7033,0.567424 5.32321,1.435163 7.85972,2.603219" />
-        <path
-           id="path5255"
-           d="m 868.56741,65.848798 9.21139,0 0,77.896332 -9.21139,0 0,-77.896332" />
-        <path
-           id="path5257"
-           d="m 918.72946,94.133778 c -4.93947,5e-5 -8.8443,1.935775 -11.71449,5.807182 -2.87023,3.83812 -4.30534,9.1113 -4.30533,15.81956 -1e-5,6.70832 1.41841,11.99819 4.25527,15.86963 2.87019,3.83809 6.7917,5.75713 11.76455,5.75712 4.90603,1e-5 8.79416,-1.93572 11.66442,-5.80718 2.87017,-3.87144 4.30528,-9.14462 4.30533,-15.81957 -5e-5,-6.64151 -1.43516,-11.898 -4.30533,-15.769498 -2.87026,-3.904781 -6.75839,-5.857194 -11.66442,-5.857244 m 0,-7.809658 c 8.00986,5.8e-5 14.30097,2.603274 18.87334,7.809658 4.57226,5.206483 6.85842,12.415392 6.85848,21.626742 -6e-5,9.17804 -2.28622,16.38695 -6.85848,21.62675 -4.57237,5.20644 -10.86348,7.80966 -18.87334,7.80966 -8.04331,0 -14.3511,-2.60322 -18.92341,-7.80966 -4.53895,-5.2398 -6.80842,-12.44871 -6.80842,-21.62675 0,-9.21135 2.26947,-16.420259 6.80842,-21.626742 4.57231,-5.206384 10.8801,-7.8096 18.92341,-7.809658" />
-        <path
-           id="path5259"
-           d="m 996.5757,115.05966 c -4e-5,-6.67489 -1.38509,-11.84795 -4.15513,-15.519195 -2.73676,-3.671159 -6.59152,-5.506761 -11.56431,-5.506811 -4.93946,5e-5 -8.79423,1.835652 -11.5643,5.506811 -2.73673,3.671245 -4.10509,8.844305 -4.10507,15.519195 -2e-5,6.64157 1.36834,11.79794 4.10507,15.46913 2.77007,3.67121 6.62484,5.50682 11.5643,5.50681 4.97279,1e-5 8.82755,-1.8356 11.56431,-5.50681 2.77004,-3.67119 4.15509,-8.82756 4.15513,-15.46913 m 9.2114,21.72687 c -10e-5,9.54513 -2.1193,16.63723 -6.35787,21.27631 -4.23862,4.67243 -10.72997,7.00865 -19.47408,7.00867 -3.23736,-2e-5 -6.29114,-0.25033 -9.16133,-0.75093 -2.87023,-0.46727 -5.65701,-1.20151 -8.36034,-2.20273 l 0,-8.96108 c 2.70333,1.46847 5.3733,2.55315 8.00991,3.25403 2.63657,0.70085 5.32322,1.05128 8.05996,1.0513 6.04077,-2e-5 10.56303,-1.58531 13.56678,-4.75589 3.00367,-3.13721 4.50553,-7.89309 4.50557,-14.26764 l 0,-4.55563 c -1.90239,3.30409 -4.33874,5.77381 -7.30903,7.40916 -2.97038,1.63536 -6.52477,2.45303 -10.66319,2.45303 -6.87519,0 -12.41537,-2.6199 -16.62056,-7.85972 -4.2052,-5.2398 -6.3078,-12.18171 -6.3078,-20.82575 0,-8.67736 2.1026,-15.635962 6.3078,-20.87582 4.20519,-5.239758 9.74537,-7.859662 16.62056,-7.85972 4.13842,5.8e-5 7.69281,0.817735 10.66319,2.453034 2.97029,1.635409 5.40664,4.105127 7.30903,7.409163 l 0,-8.510525 9.2114,0 0,49.110738" />
-        <path
-           id="path5261"
-           d="m 1046.4875,94.133778 c -4.9395,5e-5 -8.8443,1.935775 -11.7145,5.807182 -2.8703,3.83812 -4.3054,9.1113 -4.3054,15.81956 0,6.70832 1.4184,11.99819 4.2553,15.86963 2.8702,3.83809 6.7917,5.75713 11.7646,5.75712 4.906,1e-5 8.7941,-1.93572 11.6644,-5.80718 2.8701,-3.87144 4.3053,-9.14462 4.3053,-15.81957 0,-6.64151 -1.4352,-11.898 -4.3053,-15.769498 -2.8703,-3.904781 -6.7584,-5.857194 -11.6644,-5.857244 m 0,-7.809658 c 8.0098,5.8e-5 14.3009,2.603274 18.8733,7.809658 4.5723,5.206483 6.8584,12.415392 6.8585,21.626742 -10e-5,9.17804 -2.2862,16.38695 -6.8585,21.62675 -4.5724,5.20644 -10.8635,7.80966 -18.8733,7.80966 -8.0434,0 -14.3511,-2.60322 -18.9235,-7.80966 -4.5389,-5.2398 -6.8084,-12.44871 -6.8084,-21.62675 0,-9.21135 2.2695,-16.420259 6.8084,-21.626742 4.5724,-5.206384 10.8801,-7.8096 18.9235,-7.809658" />
-      </g>
-      <g
-         transform="matrix(0.43788811,-0.43788811,0.43788811,0.43788811,-547.02034,450.07345)"
-         id="g5278">
-        <path
-           sodipodi:type="arc"
-           style="fill:url(#linearGradient5311);fill-opacity:1;stroke:none"
-           id="path4711"
-           sodipodi:cx="-469.87463"
-           sodipodi:cy="202.81734"
-           sodipodi:rx="285.61008"
-           sodipodi:ry="285.61008"
-           d="m -184.26456,202.81734 c 0,157.73809 -127.87198,285.61007 -285.61007,285.61007 -157.73809,0 -285.61008,-127.87198 -285.61008,-285.61007 0,-157.738093 127.87199,-285.61008 285.61008,-285.61008 157.73809,0 285.61007,127.871987 285.61007,285.61008 z"
-           transform="translate(1201.9688,-114.00788)" />
-        <path
-           d="m -184.26456,202.81734 c 0,157.73809 -127.87198,285.61007 -285.61007,285.61007 -157.73809,0 -285.61008,-127.87198 -285.61008,-285.61007 0,-157.738093 127.87199,-285.61008 285.61008,-285.61008 157.73809,0 285.61007,127.871987 285.61007,285.61008 z"
-           sodipodi:ry="285.61008"
-           sodipodi:rx="285.61008"
-           sodipodi:cy="202.81734"
-           sodipodi:cx="-469.87463"
-           id="path4713"
-           style="fill:#eeeeee;fill-opacity:1;stroke:none"
-           sodipodi:type="arc"
-           transform="matrix(0.60887098,0,0,0.60887098,1018.1872,79.030259)" />
-      </g>
-    </g>
-  </g>
-</svg>

+ 0 - 16
app/assets/index.js

@@ -1,16 +0,0 @@
-const appIndex = require('./app-index')
-
-module.exports = Object.assign({
-  style: require('./style.scss'),
-  appStyle: require('./app-style.scss'),
-  logo: require('./generic-logo.svg'),
-  menuIcon: require('@alancnet/material-design-icons/navigation_ic_menu_48px.svg'),
-  userIcon: require('@alancnet/material-design-icons/social_ic_person_48px.svg'),
-  addUserIcon: require('@alancnet/material-design-icons/social_ic_person_add_48px.svg'),
-  dashboardIcon: require('@alancnet/material-design-icons/action_ic_dashboard_48px.svg'),
-  createIcon: require('@alancnet/material-design-icons/content_ic_add_48px.svg'),
-  editIcon: require('@alancnet/material-design-icons/content_ic_create_48px.svg'),
-  deleteIcon: require('@alancnet/material-design-icons/action_ic_delete_48px.svg'),
-  saveIcon: require('@alancnet/material-design-icons/content_ic_save_48px.svg'),
-  undoIcon: require('@alancnet/material-design-icons/content_ic_undo_48px.svg')
-}, appIndex)

+ 0 - 37
app/assets/style.scss

@@ -1,37 +0,0 @@
-body,
-ng-view,
-ng-view > *,
-app-user-area,
-app-home-area
-{
-  display: flex;
-  flex-direction: row;
-  flex-grow: 100
-}
-
-app-home-area {
-  .logo-container {
-    // padding-top: 10em;
-    padding-bottom: 5em;
-    text-align: center;
-  }
-  .logo {
-    max-width: 20em;
-  }
-  .home-content {
-    max-width: 400px;
-    margin-right: auto;
-    margin-left: auto;
-  }
-}
-
-md-sidenav {
-  .logo-container {
-    padding-top: 1em;
-    padding-bottom: 2em;
-    text-align: center;
-  }
-  .logo {
-    max-width: 80%;
-  }
-}

+ 0 - 31
app/async.js

@@ -1,31 +0,0 @@
-const angular = require('angular')
-const mod = angular.module('async', [])
-mod.run(($q, $window, $rootScope) => {
-  let timer = null
-  const then = $q.prototype.then
-  const setTimer = () => {
-    if (!timer) {
-      timer = setTimeout(() => {
-        timer = null
-        $rootScope.$digest()
-      })
-    }
-  }
-  $q.prototype.then = function(successCallback, errorCallback, notifyCallback) {
-    return then.call(
-      this,
-      successCallback && (val => {
-        setTimer()
-        return successCallback(val)
-      }),
-      errorCallback && (err => {
-        setTimer()
-        return errorCallback(err)
-      }),
-      notifyCallback && (msg => {
-        setTimer()
-        return errorCallback(err)
-      })
-    )
- }
-})

+ 0 - 1
app/components/app-index.js

@@ -1 +0,0 @@
-// TODO: App specific components

+ 0 - 21
app/components/crud-pages/README.md

@@ -1,21 +0,0 @@
-# CRUD Pages
-
-This utility will create standard pages for listing, creating, reading, updating, and deleting standard entities.
-
-```javascript
-crudPages({
-  typeName,         // string (required): MyEntity
-  typePlural,       // string (optional): MyEntities
-  camelName,        // string (optional): myEntity
-  camelPlural,      // string (optional): myEntities
-  paramName,        // string (optional): my-entity
-  paramPlural,      // string (optional): my-entities
-  apiPrefix,        // string (optional): /api/my-entities
-  columns: [
-    {
-      fieldName:    // string (required): Mailing Address
-      camelName:    // string (optional): mailingAddress
-    }
-  ]
-})
-```

+ 0 - 70
app/components/crud-pages/details.js

@@ -1,70 +0,0 @@
-const _ = require('lodash')
-const app = require('../../app')
-/**
- * @param {CrudPagesOptions} opts 
- */
-const details = (opts) => {
-  const defaultInput = column => html`
-    <md-input-container>
-      <label>${column.titleName}</label>
-      <input type="${column.type || 'text'}" ng-model="model.${raw(column.camelName)}" />
-    </md-input-container>
-  `
-
-  app.component(`app${opts.pascalName}DetailsPage`, {
-
-    template: html`
-      <app-user-area>
-        <h1>{{ctrl.isNew ? 'New ${opts.titleName}' : '${opts.titleName} Details'}}</h1>
-        <form name="form" ng-submit="ctrl.submit()">
-          ${opts.columns.map(c => c.input || defaultInput(c))}
-
-          <div>
-            <md-button type="submit" class="md-raised md-primary">Submit</md-button>
-          </div>
-
-        </form>
-      </app-user-area>
-    `,
-    controllerAs: 'ctrl',
-    controller: function(api, $scope, $routeParams, $mdToast, $location) {
-      this.isNew = $routeParams.id === 'new'
-      const crud = api.crud(opts.apiPrefix)
-      let original
-      if (this.isNew) {
-        original = {}
-        $scope.model = Object.create(original)
-      } else {
-        crud.read($routeParams.id).then(model => {
-          original = model
-          $scope.model = Object.create(original)
-        })
-      }
-
-      this.submit = async () => {
-        try {
-          if (this.isNew) {
-            await crud.create($scope.model)
-          } else {
-            const obj = {}
-            for (var key in $scope.model) {
-              if ($scope.model.hasOwnProperty(key)) {
-                obj[key] = $scope.model[key]
-              }
-            }
-            await crud.update(original.id, obj)
-          }
-          $mdToast.showSimple(`${opts.titleName} saved.`)
-          $location.url(opts.appPrefix)
-        } catch (err) {
-          console.error(err)
-          $mdToast.showSimple(`Could not save ${opts.titleName}: ${err.message || err}`)
-        }
-      }
-
-    }
-
-  })
-}
-
-module.exports = details

+ 0 - 80
app/components/crud-pages/index.js

@@ -1,80 +0,0 @@
-const app = require('../../app')
-const { pascal, camel, param, title } = require('change-case')
-const plural = require('plural')
-const list = require('./list')
-const details = require('./details')
-const trash = require('./trash')
-
-/** @define CrudPagesOptions
- * @property {string} titleName Type name in Title Case. This is used for labels like "New {Title Name}"
- * @property {string} titlePlural Plural type name in Title Case. This is used for labels like "View All {Title Plurals}"
- * @property {string} pascalName Type name in PascalCase. This is used for Class definitions like "app{PascalName}Page"
- * @property {string} pascalPlural Plural type name in PascalCase. This is used for Class definitions like "app{PascalPlural}List"
- * @property {string} camelName Type name in camelCase. This is used for referencing models, like "model.{camelName}"
- * @property {string} camelPlural Plural type name in camelCase.
- * @property {string} paramName Type name in param-case.
- * @property {string} paramPlural Plural type name in param-case. This is used for urls, like "/api/{param-plural}"
- * @property {string} apiPrefix API url path prefix. Default: /api/{param-plural}
- * @property {string} appPrefix APP url path prefix. Default: /{param-plural}
- * @property {CrudColumnOptions[]} columns
- */
-
-/** @define CrudColumnOptions
- * @property {string} titleName Field name in Title Case. This is used for field labels.
- * @property {string} camelName Field name in camelCase. This is used to reference data in the model.
- * @property {string} header HTML template for the list table header.
- * @property {string} cell HTML template for the list table cell
- * @property {string} type Field type. Can be applied to <input type="{type}" /> or used to determine a renderer.
- * @property {boolean} inList Default: true. Includes column in list page.
- */
-
-/**
- * @param {CrudPagesOptions} opts 
- */
-const crudPages = (opts) => {
-  if (!opts.pascalName) opts.pascalName = pascal(opts.titleName || opts.camelName || opts.paramName || '')
-  if (!opts.pascalName) throw new Error('pascalName is required')
-  if (opts.pascalName !== pascal(opts.pascalName)) throw new Error('pascalName should be PascalCased')
-  if (!opts.pascalPlural) opts.pascalPlural = plural(opts.pascalName)
-  if (opts.pascalPlural !== pascal(opts.pascalPlural)) throw new Error('pascalPlural should be PascalCased')
-  if (!opts.titleName) opts.titleName = title(opts.pascalName)
-  if (!opts.titlePlural) opts.titlePlural = plural(opts.titleName)
-  if (!opts.camelName) opts.camelName = camel(opts.pascalName)
-  if (opts.camelName !== camel(opts.camelName)) throw new Error('camelName should be camelCased')
-  if (!opts.camelPlural) opts.camelPlural = plural(opts.camelName)
-  if (opts.camelPlural !== camel(opts.camelPlural)) throw new Error('camelPlural should be camelCased')
-  if (!opts.paramName) opts.paramName = param(opts.pascalName)
-  if (opts.paramName !== param(opts.paramName)) throw new Error('paramName should be param-cased')
-  if (!opts.paramPlural) opts.paramPlural = plural(opts.paramName)
-  if (opts.paramPlural !== param(opts.paramPlural)) throw new Error('paramPlural should be param-cased')
-  if (!opts.apiPrefix) opts.apiPrefix = `/api/${opts.paramPlural}`
-  if (!opts.appPrefix) opts.appPrefix = `/${opts.paramPlural}`
-  if (!opts.listComponentName) opts.listComponentName = `app${opts.pascalPlural}List`
-  if (opts.listComponentName !== camel(opts.listComponentName)) throw new Error('listComponentName should be camelCased')
-  if (!opts.listComponentTag) opts.listComponentTag = `app-${opts.paramName}-list`
-  if (opts.listComponentTag !== param(opts.listComponentTag)) throw new Error('listComponentTag should be param-cased')
-  if (!opts.listPageComponentName) opts.listPageComponentName = `app${opts.pascalPlural}Page`
-  if (opts.listPageComponentName !== camel(opts.listPageComponentName)) throw new Error('listPageComponentName should be camelCased')
-  if (!opts.listPageComponentTag) opts.listPageComponentTag = `app-${opts.paramPlural}-page`
-  if (opts.listPageComponentTag !== param(opts.listPageComponentTag)) throw new Error('listPageComponentTag should be param-cased')
-  
-  if (!opts.columns) throw new Error('Columns are required')
-  opts.columns.forEach(col => {
-    if (!col.camelName) col.camelName = camel(opts.titleName)
-    if (!col.camelName) throw new Error('camelName is required')
-    if (col.camelName !== camel(col.camelName)) throw new Error('column.camelName should be camelCased')
-    if (!col.titleName) col.titleName = title(col.camelName)
-    if (col.type === undefined) col.type = 'text'
-    if (col.inList === undefined) col.inList = true
-  })
-
-  list(opts)
-  details(opts)
-  trash(opts)
-}
-
-
-  // TODO: Create Read Update Delete pages...
-
-
-module.exports = crudPages

+ 0 - 77
app/components/crud-pages/list.js

@@ -1,77 +0,0 @@
-const app = require('../../app')
-const {editIcon, createIcon, deleteIcon} = require('../../assets')
-
-/**
- * @param {CrudPagesOptions} opts 
- */
-const list = (opts) => {
-  const defaultHeader = column => html`<th md-column>${column.titleName}</th>`
-  const defaultCell = column => html`<td md-cell>{{${raw(opts.camelName)}.${raw(column.camelName)}}}</td>`
-
-  app.component(`app${opts.pascalPlural}Page`, {
-    template: html`
-      <app-user-area>
-        <h1>${opts.titlePlural}</h1>
-        <md-table-container>
-          <table md-table md-row-select md-auto-select  ng-model="ctrl.selected" md-progress="ctrl.promise">
-              <thead md-head md-order="query.order" md-on-reorder="ctrl.getRecords">
-                <tr md-row>
-                  ${opts.columns.filter(c => c.inList).map(c => c.header || defaultHeader(c))}
-                  <th md-column>Actions</th>
-                </tr>
-              </thead>
-              <tbody md-body>
-                <tr md-row md-select="${opts.camelName}" md-select-id="name" md-auto-select ng-repeat="${raw(opts.camelName)} in ctrl.data track by ${raw(opts.camelName)}.id">
-                  ${opts.columns.filter(c => c.inList).map(c => c.cell || defaultCell(c))}
-                  <td md-cell>
-                    <md-button ng-href="${opts.appPrefix}/{{${raw(opts.camelName)}.id}}">
-                      <md-icon md-svg-icon="${editIcon}"></md-icon>
-                      Edit
-                    </md-button>
-                    <md-button ng-click="ctrl.delete(${raw(opts.camelName)})">
-                      <md-icon md-svg-src="${deleteIcon}"></md-icon>
-                      Delete
-                    </md-button>
-
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-        </md-table-container>
-        <div layout="row" layout-align="end">
-          <md-button class="md-fab" aria-label="Add ${opts.titleName}" ng-href="${opts.appPrefix}/new">
-            <md-icon md-svg-src="${createIcon}"></md-icon>
-          </md-button>
-        </div>
-      </app-user-area>
-    `,
-    controllerAs: 'ctrl',
-    controller: function(api, $mdToast) {
-      const crud = api.crud(opts.apiPrefix)
-
-      this.selected = []
-      this.data = []
-
-      this.getRecords = () => {
-        this.promise = crud.list().then(data => {
-          this.data = data
-        })
-      }
-
-      this.delete = async (record) => {
-        try {
-          await crud.delete(record.id)
-          $mdToast.showSimple(`${opts.titleName} deleted.`)
-        } catch (err) {
-          console.error(err)
-          $mdToast.showSimple(`Could not delete ${opts.titleName}: ${err.message || err}`)
-        }
-      }
-
-      this.getRecords()      
-    }
-
-  })
-}
-
-module.exports = list

+ 0 - 0
app/components/crud-pages/options.js


+ 0 - 69
app/components/crud-pages/trash.js

@@ -1,69 +0,0 @@
-const app = require('../../app')
-const { undoIcon} = require('../../assets')
-
-/**
- * @param {CrudPagesOptions} opts 
- */
-const list = (opts) => {
-  const defaultHeader = column => html`<th md-column>${column.titleName}</th>`
-  const defaultCell = column => html`<td md-cell>{{${raw(opts.camelName)}.${raw(column.camelName)}}}</td>`
-
-  app.component(`app${opts.pascalPlural}TrashPage`, {
-    template: html`
-      <app-user-area>
-        <h1>${opts.titlePlural} Trash</h1>
-        <md-table-container>
-          <table md-table md-row-select md-auto-select md-multiple ng-model="ctrl.selected" md-progress="ctrl.promise">
-              <thead md-head md-order="query.order" md-on-reorder="ctrl.getRecords">
-                <tr md-row>
-                  ${opts.columns.filter(c => c.inList).map(c => c.header || defaultHeader(c))}
-                  <th md-column>Actions</th>
-                </tr>
-              </thead>
-              <tbody md-body>
-                <tr md-row md-select="${opts.camelName}" md-select-id="name" md-auto-select ng-repeat="${raw(opts.camelName)} in ctrl.data track by ${raw(opts.camelName)}.id">
-                  ${opts.columns.filter(c => c.inList).map(c => c.cell || defaultCell(c))}
-                  <td md-cell>
-                    <md-button ng-click="ctrl.undelete(${raw(opts.camelName)})">
-                      <md-icon md-svg-icon="${undoIcon}"></md-icon>
-                      Undelete
-                    </md-button>
-                  </td>
-                </tr>
-              </tbody>
-            </table>
-        </md-table-container>
-      </app-user-area>
-    `,
-    controllerAs: 'ctrl',
-    controller: function(api, $mdToast, $location) {
-      const crud = api.crud(`${opts.apiPrefix}`)
-
-      this.selected = []
-      this.data = []
-
-      this.getRecords = () => {
-        this.promise = crud.trash().then(data => {
-          this.data = data
-        })
-      }
-
-      this.undelete = async rec => {
-        try {
-          await crud.undelete(rec.id)
-          $mdToast.showSimple(`${opts.titleName} undeleted.`)
-          $location.url(`${opts.appPrefix}`)
-        } catch (err) {
-          console.error(err)
-          $mdToast.showSimple(`Could not undelete ${opts.titleName}: ${err.message || err}`)
-        }
-
-      }
-
-      this.getRecords()      
-    }
-
-  })
-}
-
-module.exports = list

+ 0 - 13
app/components/dashboard-page.js

@@ -1,13 +0,0 @@
-const app = require('../app')
-
-app.component('appDashboardPage', {
-  template: html`
-    <app-user-area>
-      Dashboard goes here
-    </app-user-area>
-  `,
-  controllerAs: 'dashboard',
-  controller: function() {
-
-  }
-})

+ 0 - 20
app/components/home-area.js

@@ -1,20 +0,0 @@
-const app = require('../app')
-const { logo } = require('../assets')
-
-app.component('appHomeArea', {
-  transclude: true,
-  template: html`
-    <div style="display: flex; align-items: center; justify-content: center; height: 100%; flex-grow: 100;">
-      <div style="flex-basis: auto">
-        <div class="logo-container">
-          <img class="logo" src="${logo}" />
-        </div>
-        <div class="home-content" ng-transclude>
-          <!-- content -->
-        </div>
-      </div>
-    </div>
-  `,
-  controller: function() {
-  }
-})

+ 0 - 11
app/components/home-page.js

@@ -1,11 +0,0 @@
-const app = require('../app')
-
-app.component('appHomePage', {
-  template: html`
-    <app-home-area>
-      <div layout="row">
-        <md-button flex ng-href="login" class="md-raised md-primary">Login</md-button>
-      </div>
-    </app-home-area>
-  `
-})

+ 0 - 8
app/components/index.js

@@ -1,8 +0,0 @@
-require('./home-area')
-require('./login-page')
-require('./test-page')
-require('./user-area')
-require('./home-page')
-require('./dashboard-page')
-require('./user-pages')
-require('./app-index')

+ 0 - 33
app/components/login-page.js

@@ -1,33 +0,0 @@
-const app = require('../app')
-
-app.component('appLoginPage', {
-  template: html`
-    <app-home-area>
-      <form name="form" ng-submit="login.submit(form)" class="md-inline-form" layout-align="center" layout="column" novalidate>
-        <md-input-container>
-          <label>Email</label>
-          <input type="email" required md-no-asterisk="true"  ng-model="login.model.email" />
-        </md-input-container>
-        <md-input-container>
-          <label>Password</label>
-          <input type="password" required md-no-asterisk="true"  ng-model="login.model.password" />
-        </md-input-container>
-        <md-button type="submit" class="md-raised md-primary">Login</md-button>
-        <md-button class="" href="/forgot-password">Forgot password</md-button>
-      </form>
-    </app-home-area>
-  `,
-  controllerAs: 'login',
-  controller: function(api, $mdToast, $location) {
-    this.submit = async form => {
-      try {
-        const res = await api.login(this.model)
-        api.setToken(res.token)
-        $location.url('/dashboard')
-      } catch (err) {
-        console.log($mdToast)
-        $mdToast.showSimple(`Login failed`)
-      }
-    }
-  }
-})

+ 0 - 15
app/components/test-page.js

@@ -1,15 +0,0 @@
-const app = require('../app')
-
-app.component('appTestPage', {
-  template: html`
-  <h2>Material Buttons</h2>
-  <p>
-    <md-button class="md-primary">Hello World</md-button>
-    <md-button class="md-accent">Hello World</md-button>
-    <md-button class="md-warn">Hello World</md-button>
-    <md-button class="">Hello World</md-button>
-  </p>
-  `,
-  controller: function() {
-  }
-})

+ 0 - 58
app/components/user-area.js

@@ -1,58 +0,0 @@
-const app = require('../app')
-const { logo, menuIcon, userIcon, dashboardIcon } = require('../assets')
-
-
-app.component('appUserArea', {
-  transclude: true,
-  template: html`
-    <div layout="row" flex>
-      <md-sidenav flex
-        md-component-id="left"
-        class="md-sidenav-left"
-        md-is-locked-open="$mdMedia('gt-md')"
-        md-whiteframe="4"
-        layout="column">
-
-        <header>
-          <div class="logo-container">
-            <img class="logo" src="${logo}" />
-          </div>          
-        </header>
-
-        <app-user-area-nav></app-user-area-nav>
-
-        <h3>
-          Administration
-        </h3>
-
-        <md-menu-item>
-          <md-button ng-href="/users">
-            <md-icon md-svg-icon="${userIcon}"></md-icon>
-            Users
-          </md-button>
-        </md-menu-item>
-      </md-sidenav>
-      <md-content flex>
-        <md-toolbar>
-          <div class="md-toolbar-tools">
-            <md-button class="md-icon-button" aria-label="Settings" ng-hide="$mdMedia('gt-md')" ng-click="ctrl.toggleNav()">
-              <md-icon md-svg-icon="${menuIcon}"></md-icon>
-            </md-button>
-          </div>
-        </md-toolbar>
-        <div layout-padding>
-          <div ng-transclude></div>
-        </div>
-      </md-content>
-    </div>
-  `,
-  controllerAs: 'ctrl',
-  controller: function($mdSidenav, $mdMedia, $scope) {
-    $scope.$mdMedia = $mdMedia
-    this.showNav = false
-    this.toggleNav = () => {
-      console.log('toggle')
-      $mdSidenav('left').toggle()
-    }
-  }
-})

+ 0 - 31
app/components/user-pages.js

@@ -1,31 +0,0 @@
-const crudPages = require('./crud-pages')
-
-crudPages({
-  titleName: 'User',
-  titlePlural: 'Users',
-  pascalName: 'User',
-  pascalPlural: 'Users',
-  camelName: 'user',
-  camelPlural: 'users',
-  snakeName: 'user',
-  snakePlural: 'users',
-  apiPrefix: '/api/users',
-  columns: [
-    {
-      titleName: 'Name',
-      camelName: 'name',
-      header: html`<th md-column md-order-by="nameToLower"><span>Name</span></th>`,
-      cell: html`<td md-cell>{{user.name}}</td>`
-    },
-    {
-      titleName: 'Email',
-      camelName: 'email'
-    },
-    {
-      titleName: 'Password',
-      camelName: 'password',
-      type: 'password',
-      inList: false
-    }
-  ]
-})

+ 1 - 4
app/index.js

@@ -1,4 +1 @@
-require('./app')
-require('./components')
-require('./api-service')
-require('./app-index')
+require('./app')

+ 0 - 10
app/routes.js

@@ -1,10 +0,0 @@
-module.exports = function($routeProvider) {
-  $routeProvider.when('/test', {template: '<app-test-page />'})
-  $routeProvider.when('/login', {template: '<app-login-page />'})
-  $routeProvider.when('/dashboard', {template: '<app-dashboard-page />'})
-  $routeProvider.when('/', {template: '<app-home-page />'})
-  $routeProvider.when('/users', {template: '<app-users-page />'})
-  $routeProvider.when('/users/trash', {template: '<app-users-trash-page />'})
-  $routeProvider.when('/users/:id', {template: '<app-user-details-page />'})
-  $routeProvider.otherwise({template: '<h1>404</h1>'})
-}

+ 3 - 52
bin/project.js

@@ -1,53 +1,4 @@
-const Vorpal = require('vorpal')
-const prompt = require('password-prompt')
-const database = require('../lib/database')
-const { User } = database
-const controllers = require('../lib/controllers')
-const chalk = require('chalk')
-const asTable = require('as-table')
 const config = require('../config')
-const server = require('../lib/server')
-
-const vorpal = new Vorpal()
-const main = async () => {
-  await database.init();
-
-  vorpal.command('create user <email> [password]', 'Creates a user')
-  .action(async model => {
-    if (!model.password) {
-      model.password = await prompt('Password: ')
-    }
-    const user = await User.create(model)
-    console.log('Created user')
-  })
-
-  vorpal.command('list users', 'Lists all users')
-  .action(async () => {
-    console.log(asTable((await User.all()).map(x => x.dataValues)))
-  })
-
-  vorpal.command('server', 'Runs the web server')
-  .action(() => server.start())
-
-  vorpal.delimiter('project>')
-  if (process.argv.length > 2) {
-    await vorpal.parse(process.argv)
-  } else {
-    await vorpal.show()
-  }
-}
-
-main().catch(err => {
-  console.error(chalk.red('Runtime Error!'))
-  console.error(err)
-})
-
-process.on('uncaughtException', (err) => {
-  console.error(chalk.red(`Uncaught Exception!`))
-  console.error(err)  
-})
-process.on('unhandledRejection', (err) => {
-  console.error(chalk.red(`Unhandled Promise Failure!`))
-  console.error(err)
-  process.exit(1)
-})
+const frameworkConfig = require('material-framework/config')
+frameworkConfig.inject(config)
+require('material-framework/bin/project')

+ 0 - 0
lib/controllers/app-index.js


+ 0 - 3
lib/controllers/auth/index.js

@@ -1,3 +0,0 @@
-module.exports = {
-  login: require('./login')
-}

+ 0 - 30
lib/controllers/auth/login.js

@@ -1,30 +0,0 @@
-const _ = require('lodash')
-const config = require('../../../config')
-const bcrypt = require('bcrypt')
-const JWT = require('jsonwebtoken')
-const aguid = require('aguid')
-const { User, Session } = require('../../database')
-
-module.exports = {
-  post: async (req, res) => {
-    const user = await User.find({where: {email: req.body.email}})
-    if (user) {
-      const success = await bcrypt.compare(req.body.password, user.password)
-      if (success) {
-        const sid = aguid()
-        const exp = Math.floor(Date.now()/1000) + config.auth.jwtExpires
-        await Session.create({
-          id: sid,
-          startAt: Date.now(),
-          endAt : exp
-        })
-        const token = JWT.sign({sid, exp}, config.auth.jwtSecret);
-        res.status(200).send({
-          user: user.sanitize(),
-          token
-        })
-      }
-    }
-    return res.send(401)
-  }
-}

+ 0 - 46
lib/controllers/crud-controller.js

@@ -1,46 +0,0 @@
-const { Op } = require('sequelize')
-
-const crudController = ({
-  Type
-}) => ({
-  list: async (req, res) => {
-    const data = (await Type.findAll()).map(d => d.sanitize ? d.sanitize() : d)
-    res.status(200).send(data && data.sanitize ? data.sanitize() : data)
-  },
-  create: async (req, res) => {
-    const data = (await Type.create(req.body))
-    res.status(200).send(data && data.sanitize ? data.sanitize() : data)
-  },
-  read: async (req, res) => {
-    const data = (await Type.findOne({where: {id: req.params.id}}))
-    res.status(200).send(data && data.sanitize ? data.sanitize() : data)
-  },
-  update: async (req, res) => {
-    const data = (await Type.update(req.body, { where: { id: req.params.id } }))
-    res.status(200).send(data && data.sanitize ? data.sanitize() : data)
-  },
-  delete: async (req, res) => {
-    const data = (await Type.destroy({ where: { id: req.params.id } }))
-    res.status(204).end()
-  },
-  trash: async (req, res) => {
-    const data = (await Type.findAll({
-      model: Type,
-      paranoid: false,
-      where: {
-        deletedAt: { [Op.ne]: null }
-      }
-    }))
-    res.status(200).send(data && data.sanitize ? data.sanitize() : data)
-  },
-  undelete: async (req, res) => {
-    const data = (await Type.update({ deletedAt: null }, {
-      paranoid: false,
-      where: { id: req.params.id }
-    }))
-    res.status(200).send(data && data.sanitize ? data.sanitize() : data)
-  }
-  // TODO: Create, Read, Update, Delete
-})
-
-module.exports = crudController

+ 0 - 4
lib/controllers/index.js

@@ -1,4 +0,0 @@
-module.exports = {
-  auth: require('./auth'),
-  user: require('./user')
-}

+ 0 - 6
lib/controllers/user.js

@@ -1,6 +0,0 @@
-const crudController = require('./crud-controller')
-const { User } = require('../database')
-
-module.exports = crudController({
-  Type: User
-})

+ 0 - 37
lib/crud-route.js

@@ -1,37 +0,0 @@
-const { pascal, camel, param } = require('change-case')
-const plural = require('plural')
-const asyncHandler = require('express-async-handler')
-
-module.exports = ({
-  app,
-  controller,
-  typeName,
-  typePlural,
-  camelName,
-  camelPlural,
-  paramName,
-  paramPlural,
-  apiPrefix  
-}) => {
-  if (!typeName) throw new Error('typeName is required')
-  if (typeName !== pascal(typeName)) throw new Error('typeName should be PascalCased')
-  if (!typePlural) typePlural = plural(typeName)
-  if (typePlural !== pascal(typePlural)) throw new Error('typePlural should be PascalCased')
-  if (!camelName) camelName = camel(typeName)
-  if (camelName !== camel(camelName)) throw new Error('camelName should be camelCased')
-  if (!camelPlural) camelPlural = plural(camelName)
-  if (camelPlural !== camel(camelPlural)) throw new Error('camelPlural should be camelCased')
-  if (!paramName) paramName = param(typeName)
-  if (paramName !== camel(paramName)) throw new Error('paramName should be param-cased')
-  if (!paramPlural) paramPlural = plural(paramName)
-  if (paramPlural !== camel(paramPlural)) throw new Error('paramPlural should be param-cased')
-  if (apiPrefix) apiPrefix = `/${paramPlural}`
-
-  if (controller.list) app.get(`/api/${paramPlural}`, asyncHandler(controller.list))
-  if (controller.create) app.post(`/api/${paramPlural}`, asyncHandler(controller.create))
-  if (controller.trash) app.get(`/api/${paramPlural}/trash`, asyncHandler(controller.trash))
-  if (controller.read) app.get(`/api/${paramPlural}/:id`, asyncHandler(controller.read))
-  if (controller.update) app.patch(`/api/${paramPlural}/:id`, asyncHandler(controller.update))
-  if (controller.delete) app.delete(`/api/${paramPlural}/:id`, asyncHandler(controller.delete))
-  if (controller.undelete) app.delete(`/api/${paramPlural}/trash/:id`, asyncHandler(controller.undelete))
-}

+ 0 - 1
lib/database/app-index.js

@@ -1 +0,0 @@
-// TODO: App Specific Models

+ 0 - 12
lib/database/index.js

@@ -1,12 +0,0 @@
-const config = require('../../config')
-const bcrypt = require('bcrypt')
-const sequelize = require('./sequelize')
-const User = require('./user')
-const Session = require('./session')
-const appIndex = require('./app-index')
-
-module.exports = Object.assign({
-  init: () => sequelize.sync(),
-  User,
-  Session
-}, appIndex)

+ 0 - 3
lib/database/sequelize.js

@@ -1,3 +0,0 @@
-const config = require('../../config')
-const Sequelize = require('sequelize')
-module.exports = new Sequelize(config.sequelize)

+ 0 - 13
lib/database/session.js

@@ -1,13 +0,0 @@
-const Sequelize = require('sequelize')
-const sequelize = require('./sequelize')
-
-const Session = sequelize.define('session', {
-  id: {
-    type: Sequelize.UUID,
-    primaryKey: true
-  },
-  startAt: Sequelize.DATE,
-  endAt: Sequelize.DATE
-})
-
-module.exports = Session

+ 0 - 41
lib/database/user.js

@@ -1,41 +0,0 @@
-const _ = require('lodash')
-const Sequelize = require('sequelize')
-const sequelize = require('./sequelize')
-const config = require('../../config')
-const bcrypt = require('bcrypt')
-
-const User = sequelize.define('user', {
-  id: {
-    type: Sequelize.UUID,
-    defaultValue: Sequelize.UUIDV1,
-    primaryKey: true
-  },
-  email: {
-    type: Sequelize.STRING,
-    unique: true,
-    validate: {
-      isEmail: true
-    }
-  },
-  name: Sequelize.STRING,
-  password: Sequelize.STRING,
-  resetToken: Sequelize.STRING
-}, {
-  paranoid: true,
-  indexes: [
-    {
-      unique: true,
-      fields: ['email']
-    }
-  ],
-  setterMethods: {
-    password(value) {
-      this.setDataValue('password', bcrypt.hashSync(value, config.auth.saltRounds))
-    }
-  }
-})
-User.prototype.sanitize = function() {
-  return _.omit(this.dataValues, 'password', 'resetToken')
-}
-
-module.exports = User

+ 0 - 8
lib/routes.js

@@ -1,8 +0,0 @@
-const crudRoute = require('./crud-route')
-const asyncHandler = require('express-async-handler')
-const C = require('./controllers')
-
-module.exports = app => {
-  app.post('/api/auth/login', asyncHandler(C.auth.login.post))
-  crudRoute({ app, controller: C.user, typeName: 'User' })
-}

+ 2 - 31
lib/server.js

@@ -1,31 +1,2 @@
-const express = require('express')
-const C = require('./controllers')
-const config = require('../config')
-const path = require('path')
-const chalk = require('chalk')
-const asyncHandler = require('express-async-handler')
-const bodyParser = require('body-parser')
-const routes = require('./routes')
-
-const app = express()
-app.use(bodyParser.json())
-
-routes(app)
-app.use(express.static('./public'))
-app.all('/api/*', (req, res) => {
-  res.send(404)
-})
-app.get('*', (req, res) => {
-  res.sendFile(path.join(process.cwd(), 'public/index.html'));
-})
-app.start = () => new Promise((resolve, reject) => {
-  try {
-    const listener = app.listen(config.server.port, function() {
-      app.address = listener.address()
-      console.log(`Server running at ${chalk.underline(chalk.blue(`http://localhost:${app.address.port}`))}`)
-    })
-  } catch (e) {
-    reject(e)
-  }
-})
-module.exports = app
+const app = require('material-framework/server')
+app.start()

Fichier diff supprimé car celui-ci est trop grand
+ 12037 - 40
package-lock.json


+ 5 - 2
package.json

@@ -18,6 +18,7 @@
     "angular": "^1.6.10",
     "angular-animate": "^1.7.0",
     "angular-aria": "^1.7.0",
+    "angular-chart.js": "^1.1.1",
     "angular-material": "^1.1.9",
     "angular-material-data-table": "^0.10.10",
     "angular-messages": "^1.7.0",
@@ -38,11 +39,13 @@
     "jsonwebtoken": "^8.2.2",
     "lodash": "^4.17.10",
     "material-design-icons": "^3.0.1",
+    "material-framework": "file:../material-framework",
     "node-sass": "^4.9.0",
     "password-prompt": "^1.0.4",
     "plural": "^1.1.0",
     "sequelize": "^4.37.6",
-    "vorpal": "^1.12.0"
+    "vorpal": "^1.12.0",
+    "xlsx": "^0.13.0"
   },
   "devDependencies": {
     "babel-loader": "^7.1.4",
@@ -60,7 +63,7 @@
     "sass-loader": "^7.0.1",
     "sqlite3": "^4.0.0",
     "style-loader": "^0.21.0",
-    "webpack": "^4.6.0",
+    "webpack": "^4.11.0",
     "webpack-cli": "^2.1.3",
     "webpack-livereload-plugin": "^2.1.1"
   }

+ 0 - 16
test/_common.js

@@ -1,16 +0,0 @@
-const config = require('../config');
-config.sequelize = {
-  // See http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor
-  dialect: 'sqlite',
-  database: 'project',
-  username: null,
-  password: null,
-  host: null,
-  port: null,
-  storage: ':memory:',
-  operatorsAliases: false,
-  logging: false
-}
-config.server.port = 51391
-const database = require('../lib/database')
-database.init()

+ 0 - 72
test/auth-test.js

@@ -1,72 +0,0 @@
-require('./_common')
-const { User } = require('../lib/database')
-const { expect } = require('chai')
-const controllers = require('../lib/controllers')
-const JWT = require('jsonwebtoken')
-const config = require('../config')
-const server = require('../lib/server')
-
-describe('Authentication', () => {
-  let user
-  before(async () => {
-    user = await User.create({
-      email: 'test@example.com',
-      password: 'hello world'
-    })
-  })
-  describe('user record', () => {
-    let userRecord
-    before(async () => {
-      userRecord = await User.find({where:{email: 'test@example.com'}})
-    })
-    it('should represent the user', async () => {
-      expect(userRecord).to.not.be.null
-      expect(userRecord.email).to.equal('test@example.com')
-    })
-    it('should have an encrypted password', () => {
-      expect(userRecord.password).to.not.equal('hello world')
-    })
-  })
-  it('should be able to log in', async () => {
-    const result = (await server.inject({
-      method: 'POST',
-      url: '/auth/login',
-      payload: {
-        email: 'test@example.com',
-        password: 'hello world'
-      }
-    })).result
-    expect(result).to.exist
-    expect(result.user).to.exist
-    expect(result.token).to.exist
-    expect(result.user.email).to.equal('test@example.com')
-
-    const decoded = await JWT.verify(result.token, config.auth.jwtSecret)
-
-    expect(decoded).to.exist
-    expect(decoded.iat).to.be.finite
-    expect(decoded.exp - decoded.iat).to.equal(config.auth.jwtExpires)
-  })
-  it('should reject invalid passwords', async () => {
-    const result = await server.inject({
-      method: 'POST',
-      url: '/auth/login',
-      payload: {
-        email: 'test@example.com',
-        password: 'goodbye world'
-      }
-    })
-    expect(result.statusCode).to.equal(401)
-  })
-  it('should reject invalid logins', async () => {
-    const result = await server.inject({
-      method: 'POST',
-      url: '/auth/login',
-      payload: {
-        email: 'idontexist@example.com',
-        password: 'hello world'
-      }
-    })
-    expect(result.statusCode).to.equal(401)
-  })
-})

+ 0 - 14
test/server-test.js

@@ -1,14 +0,0 @@
-require('./_common')
-const { expect } = require('chai')
-const server = require('../lib/server')
-const config = require('../config')
-
-describe('Server', () => {
-  it('should listen on the specified port', async () => {
-    await server.init()
-    expect(server)
-    expect(server.info.port).to.equal(config.server.port)
-    expect(server.info.address).to.equal('0.0.0.0')
-    await server.stop()
-  })
-})

+ 2 - 2
webpack.config.js

@@ -38,13 +38,13 @@ module.exports = {
         use:['style-loader','css-loader', 'sass-loader']
       },
       {
-        test:/\.(?:svg|eot|woff2|woff|ttf)$/,
+        test:/\.(?:svg|png|eot|woff2|woff|ttf)$/,
         use:['file-loader']
       },
       {
         test:/\.html$/,
         use:['html-loader']
-      },
+      }
     ]
   }
 };

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff