lwzm
9/6/2017 - 12:44 PM

ng-admin

ng-admin


const path = require('path')

module.exports = {
    watch: true,
    entry: './index.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },

    module: {
        loaders: [
            {
                test: /\.(js|jsx)$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: [
                            'env',
                        ],
                    },
                },
            },
        ],

    },
}
drop table api.log;
drop table api.patient;
drop table api.doctor;
drop table api.zone;

BEGIN;

CREATE TABLE api.zone (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    beds INTEGER
);

CREATE TABLE api.doctor (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL UNIQUE,
    zone INTEGER REFERENCES api.zone,
    info JSONB
);

CREATE TABLE api.patient (
    id SERIAL PRIMARY KEY,
    bed INTEGER,
    state TEXT NOT NULL DEFAULT 'pending',
    zone INTEGER NOT NULL REFERENCES api.zone,
    info JSONB
);


CREATE TABLE api.log (
    id SERIAL PRIMARY KEY,
    datetime TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
    key TEXT,
    patient INTEGER NOT NULL REFERENCES api.patient,
    info JSONB
);


grant all on api.zone to web_anon;
grant all on api.zone_id_seq to web_anon;
grant all on api.doctor to web_anon;
grant all on api.doctor_id_seq to web_anon;
grant all on api.patient to web_anon;
grant all on api.patient_id_seq to web_anon;
grant all on api.log to web_anon;
grant all on api.log_id_seq to web_anon;
COMMIT;
{
  "name": "my-admin",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
  },
  "devDependencies": {
      "babel-core": "^6.26.0",
      "babel-loader": "^7.1.2",
      "babel-polyfill": "^6.26.0",
      "babel-preset-env": "^1.6.1",
      "webpack": "^3.8.1"
  }
}
import 'babel-polyfill'
import chunk from 'lodash/map'

const app = angular.module('myApp', ['ng-admin'])

//console.log(async () => 1)

app.config(["$httpProvider", (http) => {
    const myInterceptor = {
        request: (config) => {
            if (config.params && config.params.___strip_id_todo) {
                delete config.params.___strip_id_todo
                const url = config.url
                config.url = url.slice(0, url.lastIndexOf("/"))
            }
            return config
        },
    }

    http.interceptors.push(() => myInterceptor)
}])


app.config(['NgAdminConfigurationProvider', "RestangularProvider", (nga, rest) => {
    // create an admin application
    const admin = nga.application('test', false)
        .baseApiUrl('/api/')

    nga.configure(admin)

    rest.addFullRequestInterceptor((element, operation, what, url, headers, params, httpConfig) => {
        headers = headers || {}

        switch (operation) {
            case 'get':
            case 'patch':
            case 'remove':
                headers["Accept"] = "application/vnd.pgrst.object+json"
                const idKey = admin.getEntity(what).identifier().name()
                const idValue = decodeURI(url.slice(url.lastIndexOf("/") + 1))
                params[idKey] = `eq.${idValue}`
                params.___strip_id_todo = true
                break
            case 'getList':
                headers['Prefer'] = "count=exact"

                const filters = params._filters
                delete params._filters

                for (const key in filters) {
                    let v = filters[key]
                    if (v != null) {
                        const _ = key.split('...')
                        const k = _[0]
                        const operator = _[1] || 'eq'
                        if (v instanceof Date) {
                            v = v.toISOString()
                        }
                        params[k] = `${operator}.${v}`
                    }
                }

                //headers['Range-Unit'] = what
                const p = params._page
                const u = params._perPage
                headers['Range'] = `${(p - 1) * u}-${p * u - 1}`
                delete params._page
                delete params._perPage
                if (params._sortField) {
                    params.order = params._sortField + '.' + params._sortDir.toLowerCase()
                    delete params._sortField
                    delete params._sortDir
                }
                break
        }
    })

    rest.addResponseInterceptor((data, operation, what, url, response, deferred) => {
        switch (operation) {
            case 'getList':
                response.totalCount = response.headers('Content-Range').split('/')[1]
                break
        }
        return data
    })



    const addEntity = (name, opts) => {
        const {fields1, fields2, idToken} = opts
        const entity = nga.entity(name).updateMethod('patch')
        const filters = []

        if (!idToken) {
            const id = nga.field('id')
                .label("ID")
                .pinned(true)  // place ID-searching at top-right corner forever
            fields1.unshift(id)
            filters.unshift(id)
        }

        const fields = fields1.concat(fields2 || [])

        for (const field of fields1) {  // or `field of fields`
            const name = field.name()
            const type = field.type()

            field.label(name)  // patch it, prefer raw rather than capitalized

            switch (type) {
                case 'number':
                case 'float':
                case 'date':
                case 'datetime':
                    filters.push(field)
                    filters.push(
                        nga.field(`${name}...gte`, type)
                        .label(`${name} >=`)
                    )
                    filters.push(
                        nga.field(`${name}...lte`, type)
                        .label(`${name} <=`)
                    )
                    break
                case 'string':
                case 'text':
                case 'wysiwyg':
                case 'email':
                    filters.push(
                        nga.field(`${name}...like`, type)
                        .label(`${name} ~=`)
                    )
                    break
                default:
                    filters.push(field)
                    break
            }
        }


        entity.listView().fields(fields1)
            .filters(filters)
            .perPage(10)  // 10 lines is height enough, i hate scrolling
            .exportFields(fields1)
        entity.editionView().fields(fields)
        entity.creationView().fields(fields)

        // at last
        // sortField, isDetailLink, identifier
        if (idToken) {
            const table = entity.listView()
            const id = table.getField(idToken)
            table.sortField(idToken)
            id.isDetailLink(true)
            entity.identifier(id)
        }

        admin.addEntity(entity)
        return entity
    }


    /*
     * append at here
     * ...
     */

    const todo = addEntity("todos", {
        fields1: [
            nga.field('task', 'text').isDetailLink(true).sortable(false),
            nga.field('done', 'boolean').choices([
                { value: false, label: 'false'},
                { value: true, label: 'true'},
            ]),
            nga.field('due', 'datetime'),
        ],
        fields2: [
            nga.field('others', 'json'),
        ],
    })

    const user = addEntity("users", {
        idToken: "name",
        fields1: [
            nga.field('name', 'string'),
            nga.field('password', 'string'),
        ],
    })

    const zone = addEntity("zone", {
        fields1: [
            nga.field('name', 'string'),
            nga.field('beds', 'number'),
        ],
    })

    const targetFiledID = nga.field('id')

    const zoneReference = nga.field('zone', 'reference')
        .targetEntity(zone)
        .targetField(nga.field('name'))

    const remoteCompleteID = {
        searchQuery: (search) => {
            return {
                'id...eq': search,
            }
        },
        refreshDelay: 300,
    }

    const doctor = addEntity("doctor", {
        fields1: [
            zoneReference,
            nga.field('name', 'string'),
            nga.field('info', 'json'),
        ],
    })

    const patient = addEntity("patient", {
        fields1: [
            nga.field('bed', 'number'),
            nga.field('state', 'string'),
            zoneReference,
            nga.field('info', 'json'),
        ],
    })

    const log = addEntity("log", {
        fields1: [
            nga.field('datetime', 'datetime'),
            nga.field('key', 'string'),
            nga.field('patient', 'reference')
            .targetEntity(patient)
            .targetField(targetFiledID)
            .perPage(100)
            ,
            nga.field('info', 'json'),
        ],
    })

    //const cfg = addEntity("cfg", [
    //    nga.field('k', 'string'),
    //    nga.field('v', 'json'),
    //    nga.field('comment', 'text'),
    //], "k")

    const post = addEntity("posts", {
        fields1: [
            nga.field('title', 'string'),
            nga.field('content', 'wysiwyg'),
            //nga.field('user', 'string'),
            nga.field('user', 'reference')
            .targetEntity(user)
            .targetField(nga.field('name'))
            .label("User Name")
            .perPage(5)
            .remoteComplete(true, {
                searchQuery: (search) => {
                    return {
                        'name...like': `*${search}*`,
                    }
                },
                refreshDelay: 300,
            })
            ,
            //nga.field('d', 'reference')
            //    .targetEntity(doctor)
            //    .targetField(targetFiledID)
            //    .perPage(2)
            //    .remoteComplete(true, remoteCompleteID)
            //,
        ],
    })

    const mapdata = addEntity("mapdata", {
        fields1: [
            nga.field("nid"),
            nga.field("title"),
            nga.field("location_type"),
            nga.field("province_state"),
            nga.field("city"),
        ],
        fields2: [
            nga.field("address_line_1"),
            nga.field("address_line_2"),
            nga.field("latitude"),
            nga.field("longitude"),
            nga.field("hours"),
            nga.field("tel"),
            nga.field("otherinfo", "text"),
            nga.field("location_id"),
            nga.field("citycode"),
            nga.field("locked"),
            nga.field("lockid"),
            nga.field("psw"),
        ],
    })



    // ...


}])

<!doctype html>
<html lang="zh">
  <head>
    <title>My Ng Admin</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ng-admin@1.0.9/build/ng-admin.min.css">
  </head>
  <body ng-app="myApp" ng-strict-di>
    <div ui-view="ng-admin"></div>
    <script src="https://cdn.jsdelivr.net/npm/ng-admin@1.0.9/build/ng-admin.min.js"></script>
    <script src="dist/bundle.js"></script>
  </body>
</html>