Skip to content

Instantly share code, notes, and snippets.

@lwzm
Last active November 28, 2017 10:10
Show Gist options
  • Save lwzm/7fbcadce992a7e2789bf22b75e721e67 to your computer and use it in GitHub Desktop.
Save lwzm/7fbcadce992a7e2789bf22b75e721e67 to your computer and use it in GitHub Desktop.
ng-admin
<!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>
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"),
],
})
// ...
}])
{
"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"
}
}
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;
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',
],
},
},
},
],
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment