Alan Colon před 7 roky
rodič
revize
add2aa9943

+ 1 - 1
app/app.js

@@ -28,4 +28,4 @@ app.run(($rootScope) => {
   $rootScope.identity = x => x
 })
 
-module.exports = app;
+module.exports = app

+ 11 - 2
app/components/user-area.js

@@ -1,6 +1,6 @@
 const app = require('../app')
 const { logo, menuIcon, userIcon, dashboardIcon, roleIcon } = require('../assets')
-
+const assets = require('../assets')
 
 app.component('appUserArea', {
   transclude: true,
@@ -21,6 +21,13 @@ app.component('appUserArea', {
 
         <app-user-area-nav></app-user-area-nav>
 
+        <md-menu-item ng-repeat="crud in ctrl.cruds">
+          <md-button ng-href="/{{crud.paramPlural}}">
+            <md-icon md-svg-icon="{{assets[crud.iconAsset]}}"></md-icon>
+            {{crud.titlePlural}}
+          </md-button>
+        </md-menu-item>
+
         <h3>
           Administration
         </h3>
@@ -53,7 +60,9 @@ app.component('appUserArea', {
     </div>
   `,
   controllerAs: 'ctrl',
-  controller: function($mdSidenav, $mdMedia, $scope) {
+  controller: function($mdSidenav, $mdMedia, $scope, cruds) {
+    this.cruds = cruds
+    $scope.assets = assets
     $scope.$mdMedia = $mdMedia
     this.showNav = false
     this.toggleNav = () => {

+ 1 - 0
app/crud/pages/details.js

@@ -77,6 +77,7 @@ const details = (opts) => {
         </form>
       </app-user-area>
     `
+  console.log(`crud: app${opts.pascalName}DetailsPage`)
   app.component(`app${opts.pascalName}DetailsPage`, {
 
     template,

+ 1 - 0
app/crud/pages/list.js

@@ -49,6 +49,7 @@ const list = (opts) => {
         </div>
       </app-user-area>
     `
+  console.log(`crud: app${opts.pascalPlural}Page`)
   app.component(`app${opts.pascalPlural}Page`, {
     template,
     controllerAs: 'ctrl',

+ 1 - 0
app/crud/pages/trash.js

@@ -8,6 +8,7 @@ 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>`
 
+  console.log(`crud: app${opts.pascalPlural}TrashPage`)
   app.component(`app${opts.pascalPlural}TrashPage`, {
     template: html`
       <app-user-area>

+ 1 - 0
app/crud/routes.js

@@ -1,6 +1,7 @@
 const defaults = require('./defaults')
 const crudRoutes = ($routeProvider) => (opts) => {
   opts = defaults(opts)
+  console.log(`crud: ${opts.appPrefix}`)
   $routeProvider.when(opts.appPrefix, {template: `<app-${opts.paramPlural}-page />`})
   $routeProvider.when(`${opts.appPrefix}/trash`, {template: `<app-${opts.paramPlural}-trash-page />`})
   $routeProvider.when(`${opts.appPrefix}/:${opts.camelName}Id`, {template: `<app-${opts.paramName}-details-page />`})

+ 20 - 0
auto-crud/app-factory.js

@@ -0,0 +1,20 @@
+const autoCrud = require('./index')
+const app = require('../app/app')
+const { pages, routes } = require('../app/crud')
+const defaults = require('../lib/crud/defaults')
+
+const appFactory = () => {
+  let cruds
+  cruds = autoCrud._getCruds().map(defaults)
+  cruds.forEach(crud => {
+    pages(crud)
+    app.config(($routeProvider) => {
+      $routeProvider.crudRoutes(crud)
+   })
+  })
+
+  app.service('cruds', function() {
+    return cruds
+  })
+}
+module.exports = appFactory

+ 67 - 0
auto-crud/index.js

@@ -0,0 +1,67 @@
+const typeWrapper = type => {
+  const wrapper = function() {
+    return {
+      __type: type,
+      __args: Array.from(arguments)
+    }
+  }
+  wrapper.__type = type
+  return wrapper
+}
+const Sequelize = {
+  'ABSTRACT': typeWrapper('ABSTRACT'),
+  'STRING': typeWrapper('STRING'),
+  'CHAR': typeWrapper('CHAR'),
+  'TEXT': typeWrapper('TEXT'),
+  'NUMBER': typeWrapper('NUMBER'),
+  'TINYINT': typeWrapper('TINYINT'),
+  'SMALLINT': typeWrapper('SMALLINT'),
+  'MEDIUMINT': typeWrapper('MEDIUMINT'),
+  'INTEGER': typeWrapper('INTEGER'),
+  'BIGINT': typeWrapper('BIGINT'),
+  'FLOAT': typeWrapper('FLOAT'),
+  'TIME': typeWrapper('TIME'),
+  'DATE': typeWrapper('DATE'),
+  'DATEONLY': typeWrapper('DATEONLY'),
+  'BOOLEAN': typeWrapper('BOOLEAN'),
+  'NOW': typeWrapper('NOW'),
+  'BLOB': typeWrapper('BLOB'),
+  'DECIMAL': typeWrapper('DECIMAL'),
+  'NUMERIC': typeWrapper('NUMERIC'),
+  'UUID': typeWrapper('UUID'),
+  'UUIDV1': typeWrapper('UUIDV1'),
+  'UUIDV4': typeWrapper('UUIDV4'),
+  'HSTORE': typeWrapper('HSTORE'),
+  'JSON': typeWrapper('JSON'),
+  'JSONB': typeWrapper('JSONB'),
+  'VIRTUAL': typeWrapper('VIRTUAL'),
+  'ARRAY': typeWrapper('ARRAY'),
+  'NONE': typeWrapper('NONE'),
+  'ENUM': typeWrapper('ENUM'),
+  'RANGE': typeWrapper('RANGE'),
+  'REAL': typeWrapper('REAL'),
+  'DOUBLE': typeWrapper('DOUBLE'),
+  'DOUBLE PRECISION': typeWrapper('DOUBLE PRECISION'),
+  'GEOMETRY': typeWrapper('GEOMETRY'),
+  'GEOGRAPHY': typeWrapper('GEOGRAPHY'),
+}
+
+let tooLate = false
+const cruds = []
+
+const register = (opts) => {
+  if (tooLate) throw new Error('Crud registered too late.')
+  cruds.push(opts)
+}
+
+const _getCruds = () => {
+  if (tooLate) throw new Error('_getCruds called twice.')
+  tooLate = true
+  return cruds
+}
+
+module.exports = {
+  Sequelize,
+  register,
+  _getCruds
+}

+ 45 - 0
auto-crud/server-factory.js

@@ -0,0 +1,45 @@
+const autoCrud = require('./index')
+const database = require('../lib/database')
+const Sequelize = require('sequelize')
+const C = require('../lib/controllers')
+const controller = require('../lib/crud/controller')
+const { defaults, routes } = require('../lib/crud')
+
+const resolveType = (o) => {
+  let type = Sequelize[o.__type]
+  if (o.__args) {
+    type = type.apply(Sequelize, o.__args)
+  }
+  return type
+}
+
+const serverFactory = (app) => {
+  const cruds = autoCrud._getCruds()
+  cruds.forEach(crud => {
+    crud = defaults(crud)
+
+    // Schema
+    for (let key in crud.schema) {
+      const field = crud.schema[key]
+      if (field.__type) {
+        crud.schema[key] = resolveType(field)
+      } else {
+        if (field.type) field.type = resolveType(field.type)
+        if (field.defaultValue) field.defaultValue = resolveType(field.defaultValue)
+      }
+    }
+    const Type = database[crud.pascalName] = database.sequelize.define(crud.camelName, crud.schema, crud.options)
+  
+    // Controller
+    const ctrl = C[crud.camelName] = controller({
+      Type,
+      camelName: crud.camelName
+    })
+
+    // Routes
+    routes(Object.assign({ app, controller:ctrl }, crud))
+
+  })
+}
+
+module.exports = serverFactory

+ 1 - 0
lib/crud/routes.js

@@ -11,4 +11,5 @@ module.exports = (opts) => {
   if (controller.update) app.patch(`/api/${opts.paramPlural}/:${opts.routeParam}`, asyncHandler(controller.update))
   if (controller.delete) app.delete(`/api/${opts.paramPlural}/:${opts.routeParam}`, asyncHandler(controller.delete))
   if (controller.undelete) app.delete(`/api/${opts.paramPlural}/trash/:${opts.routeParam}`, asyncHandler(controller.undelete))
+  console.log(`crud: /api/${opts.paramPlural}`)
 }

+ 3 - 0
lib/server.js

@@ -6,11 +6,14 @@ const chalk = require('chalk')
 const asyncHandler = require('express-async-handler')
 const bodyParser = require('body-parser')
 const routes = require('./routes')
+const serverFactory = require('../auto-crud/server-factory')
 
 const app = express()
 app.use(bodyParser.json())
 
 routes(app)
+serverFactory(app)
+
 app.start = () => new Promise((resolve, reject) => {
   app.use(express.static('./public'))
   app.all('/api/*', (req, res) => {