zet-lib 1.3.41 → 1.3.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1641 +1,1641 @@
1
- const express = require('express')
2
- const router = express.Router()
3
- const csrf = require('csurf')
4
- const csrfProtection = csrf({ cookie: true })
5
- const fs = require('fs-extra')
6
- const axios = require('axios')
7
- const pm2 = require('pm2')
8
- const uglifyJS = require('uglify-js')
9
- const { minify } = require('html-minifier-terser')
10
- const zRoute = require('./zRoute')
11
- const connection = require('./connection')
12
- const Util = require('./Util')
13
- const moduleLib = require('./moduleLib')
14
- const myCache = require('./cache')
15
- const ejs = require('ejs')
16
- var app = express()
17
- const path = require('path')
18
-
19
- const nots = ['index', 'uploads', 'js', 'css', 'log', 'generator', 'zmenu', 'zgenerator', 'zfields', 'zrole', 'zfunction', 'zgrid', 'zgrid_default', 'zpage', 'zlayout', 'zerror', 'zuser_company']
20
- //const nots = [];
21
- //const generatorUrl = 'http://localhost:3005';
22
- const generatorUrl = 'https://generator.cmsqu.com'
23
-
24
- const bodyView = Util.readFile(require.resolve(__dirname + '/views/generator.ejs'))
25
-
26
- router.get('/', csrfProtection, async (req, res) => {
27
- let table = req.query.table || '',
28
- route = '',
29
- jsonData = {},
30
- zForms = {},
31
- relations = {},
32
- approvalDatas = { is_approval: false }
33
- const MYMODELS = myCache.get('MYMODELS')
34
- let datas = await axios.post(`${generatorUrl}/api/generator/index`)
35
- jsonData = datas.data
36
- jsonData.rows = await zfieldsKeys()
37
- if (table) {
38
- jsonData.datas = jsonData.rows[table] || {}
39
- }
40
- jsonData.fields = await connection.query(connection.showFullFields(table))
41
- zForms.obj = {}
42
- let sorting = ''
43
- if (table) {
44
- let contentScript = `var ZFIELDS = ${JSON.stringify(jsonData.rows, null, 2)};`
45
- moduleLib.addScript(req, res, contentScript)
46
- moduleLib.editor(req, res)
47
- let MYMODEL_APPROVERS = MYMODELS['zapprovals']
48
- let zfieldData = await connection.result({
49
- table: 'zfields',
50
- where: {
51
- table: table,
52
- },
53
- })
54
- sorting = JSON.stringify(zfieldData.sorting)
55
- approvalDatas = MYMODEL_APPROVERS.datas
56
- if (zfieldData) {
57
- let approvalJSON = zfieldData.approval_json || {}
58
- approvalDatas.is_approval = zfieldData.is_approval || false
59
- approvalDatas.title = approvalJSON.title || ''
60
- approvalDatas.type = approvalJSON.type || 1
61
- approvalDatas.approvers = approvalJSON.approvers ? approvalJSON.approvers : []
62
- approvalDatas.knowings = approvalJSON.knowings || []
63
- approvalDatas.template = approvalJSON.content || ''
64
- zForms = await zRoute.formsFieldSync(req, res, MYMODEL_APPROVERS, approvalDatas)
65
- }
66
- }
67
-
68
- const jsonDatas = jsonData.datas
69
- const lock = nots.includes(table) ? 1 : 0
70
- const jsonDatasJson = jsonDatas.hasOwnProperty('json') && jsonDatas.json ? jsonDatas.json : {}
71
- const checkDummy = Object.prototype.hasOwnProperty.call(jsonDatasJson, 'dummy') && jsonDatasJson.dummy ? 'checked' : ''
72
- const renderData = {
73
- datas: jsonDatas,
74
- table: table,
75
- rows: jsonData.rows,
76
- checkDummy: checkDummy,
77
- csrfToken: req.csrfToken(),
78
- route: table,
79
- selects: jsonData.selects,
80
- zForms: zForms,
81
- relations: relations,
82
- approvalDatas: approvalDatas,
83
- sorting: sorting,
84
- lock: lock,
85
- routeName: res.locals.routeName,
86
- }
87
-
88
- const bodyHTML = ejs.render(bodyView, renderData)
89
- const endHTML = ejs.render(Util.readFile(require.resolve(__dirname + '/views/generatorjs.ejs')), renderData)
90
- let dataRender = renderData
91
- dataRender.bodyHTML = bodyHTML
92
- dataRender.endHTML = endHTML
93
- res.render(require.resolve(__dirname + '/views/generator_layout.ejs'), dataRender)
94
- })
95
-
96
- router.post('/fields', async (req, res) => {
97
- try {
98
- let body = req.body
99
- let table = body.table || ''
100
- let result = {},
101
- fields = {},
102
- rowsFields = []
103
- if (table) {
104
- result = await connection.result({ table: 'zfields', where: { table: table } })
105
- fields = await connection.query(connection.showFullFields(table))
106
- rowsFields = await connection.query(connection.describeTable(table))
107
- }
108
- let objData = {
109
- result: result,
110
- fields: fields,
111
- rowsFields: rowsFields,
112
- table: table,
113
- }
114
- let datas = await axios.post(`${generatorUrl}/api/generator/modal`, objData)
115
- res.json(datas.data)
116
- } catch (e) {
117
- console.log(e)
118
- res.json(e.toString())
119
- }
120
- })
121
-
122
- /*
123
- Create new Module/Table
124
- */
125
- router.post('/', csrfProtection, async (req, res) => {
126
- try {
127
- let results = await axios.post(`${generatorUrl}/api/generator/create`, req.body)
128
- let datas = results.data
129
- if (datas.status == 0) {
130
- res.json(datas)
131
- } else {
132
- if (nots.includes(datas.post.table)) {
133
- return res.json(Util.flashError('Table is locked'))
134
- }
135
- await connection.insert({
136
- table: 'zfields',
137
- data: datas.post,
138
- })
139
- await connection.query(datas.sql)
140
- res.json(datas)
141
- }
142
- } catch (err) {
143
- res.json(Util.flashError(err.toString()))
144
- }
145
- })
146
-
147
- router.post('/reset', async (req, res) => {
148
- try {
149
- let json = Util.jsonSuccess('Reset Success')
150
- let table = req.body.table
151
- if (nots.includes(table)) {
152
- return res.json(Util.flashError('Table is locked'))
153
- }
154
- if (table) {
155
- let results = await axios.post(`${generatorUrl}/api/generator/reset`, req.body)
156
- let datas = results.data
157
- await connection.update({
158
- table: 'zfields',
159
- data: datas,
160
- where: {
161
- table: table,
162
- },
163
- })
164
- } else {
165
- json = Util.flashError('error')
166
- }
167
- res.json(json)
168
- } catch (e) {
169
- console.log(e.toString())
170
- json = Util.flashError('error')
171
- res.json(json)
172
- }
173
- })
174
-
175
- router.post('/tabs', async (req, res) => {
176
- let json = { status: 0, title: 'error', url: '' }
177
- let body = req.body
178
- let table = body.table || ''
179
- let title = body.title || ''
180
- let tabs = body.tabs || []
181
- if (table == '') {
182
- json.title = 'table is empty'
183
- return res.send(json)
184
- }
185
- if (title == '') {
186
- json.title = 'title is empty'
187
- return res.send(json)
188
- }
189
- if (nots.includes(table)) {
190
- return res.json(Util.flashError('Table is locked'))
191
- }
192
- let post = {}
193
- post.table = table
194
- post.tabs = JSON.stringify(tabs)
195
- post.name = title
196
- if (body.hasOwnProperty('json')) {
197
- post.json = JSON.stringify(body.json)
198
- } else {
199
- post.json = JSON.stringify({ dummy: 0 })
200
- }
201
- let results = await connection.results({
202
- table: 'zfields',
203
- where: {
204
- table: table,
205
- },
206
- })
207
-
208
- if (results.length == 0) {
209
- await connection.insert({ table: 'zfields', data: post })
210
- } else {
211
- //original data
212
- let tabOri = results[0].tabs || []
213
- let detailOri = results[0].details || {}
214
- let leftOri = results[0].left || []
215
- let rightOri = results[0].right || []
216
- let oneColumnOri = results[0].one_column || []
217
- let objOri = {}
218
- let arrayOri = {}
219
- tabOri.map((item, index) => {
220
- objOri[item] = `arr${index}`
221
- arrayOri[item] = index
222
- })
223
- //end original data
224
- if (tabOri.length > 0) {
225
- if (JSON.stringify(tabs) !== JSON.stringify(tabOri)) {
226
- let details = {}
227
- //remove Object in array
228
- let left = leftOri.filter((item) => typeof item !== 'object') || [],
229
- right = rightOri.filter((item) => typeof item !== 'object') || [],
230
- oneColumn = oneColumnOri.filter((item) => typeof item !== 'object') || []
231
-
232
- details.notabs = detailOri.notabs
233
- tabs.map((item, index) => {
234
- let key = `arr${index}`
235
- let valueIndex = arrayOri[item]
236
- //details
237
- details[key] = detailOri[objOri[item]] || []
238
- //left
239
- let objLeft = leftOri[valueIndex] && leftOri[valueIndex].hasOwnProperty(`arr${arrayOri[item]}`) ? leftOri[valueIndex][`arr${arrayOri[item]}`] : []
240
- left.push({ [key]: objLeft })
241
- //right
242
- let objRight = rightOri[valueIndex] && rightOri[valueIndex].hasOwnProperty(`arr${arrayOri[item]}`) ? rightOri[valueIndex][`arr${arrayOri[item]}`] : []
243
- right.push({ [key]: objRight })
244
- //one column
245
- let objOneColumn = oneColumnOri[valueIndex] && oneColumnOri[valueIndex].hasOwnProperty(`arr${arrayOri[item]}`) ? oneColumnOri[valueIndex][`arr${arrayOri[item]}`] : []
246
- oneColumn.push({ [key]: objOneColumn })
247
- })
248
- post.details = JSON.stringify(details)
249
- post.left = JSON.stringify(left)
250
- post.right = JSON.stringify(right)
251
- post.one_column = JSON.stringify(oneColumn)
252
- }
253
- }
254
- await connection.update({ table: 'zfields', where: { id: results[0].id }, data: post })
255
- }
256
-
257
- json.status = 1
258
- json.url = '/generator?table=' + table
259
- res.send(json)
260
- })
261
-
262
- //after drag and drop then save
263
- // and generate
264
- router.post('/save_and_generate', csrfProtection, async (req, res) => {
265
- try {
266
- if (nots.includes(req.body.table)) {
267
- return res.json(Util.flashError('Table is locked'))
268
- }
269
- //console.log(JSON.stringify(req.body))
270
- const json = await generate(req, res)
271
- res.json(json)
272
- } catch (e) {
273
- console.log(e)
274
- res.status(200).json({ message: e + '' })
275
- }
276
- })
277
-
278
- const generate = async (req, res) => {
279
- const body = req.body
280
- const table = body.table
281
- const MYMODELS = myCache.get('MYMODELS')
282
- let MYMODEL = {}
283
- let chains = []
284
- let datas
285
- let results
286
- let dummy = false
287
-
288
- //save data into table zfields
289
- //console.log(JSON.stringify(body.others))
290
- const others = body.others
291
- //return;
292
- await saveToZFields(body)
293
-
294
- let exist = await connection.query(connection.describeTable(table))
295
- if (exist.length) {
296
- body.rows = await connection.results({ table: 'zfields', where: { table: table } })
297
- body.checks = await connection.query(`SELECT 'public.${table}'::regclass`)
298
- } else {
299
- let sql = `
300
- CREATE TABLE ${table} (
301
- id BIGSERIAL PRIMARY KEY,
302
- company_id BIGINT NOT NULL,
303
- lock smallint default 0,
304
- approval_status smallint DEFAULT 1,
305
- approval_history jsonb[] DEFAULT NULL,
306
- updated_by BIGINT DEFAULT NULL,
307
- created_by BIGINT DEFAULT NULL,
308
- created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
309
- updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
310
- CONSTRAINT fk_${table}_company_id FOREIGN KEY (company_id) REFERENCES zcompany (id)
311
- );`
312
- await connection.query(sql)
313
- body.checks = await connection.query(`SELECT 'public.${table}'::regclass`)
314
- body.rows = await connection.results({ table: 'zfields', where: { table: table } })
315
- }
316
- body.others = others
317
- results = await axios.post(`${generatorUrl}/api/generator/properties`, body)
318
- datas = results.data
319
- if (datas.create_table.hasOwnProperty('sql')) {
320
- await connection.query(datas.create_table.sql)
321
- return generate(body)
322
- }
323
-
324
- let result = await connection.update({
325
- table: 'zfields',
326
- data: datas.updateFields.post,
327
- where: {
328
- id: datas.updateFields.id,
329
- },
330
- })
331
- let resultJSON = Object.prototype.hasOwnProperty.call(result, 'json') ? result.json : {}
332
- if (resultJSON && Object.prototype.hasOwnProperty.call(resultJSON, 'dummy')) {
333
- dummy = resultJSON.dummy == 1 ? true : false
334
- }
335
- let properties = result.properties
336
- //update if any chains
337
- for (let key in properties) {
338
- //override
339
- properties[key].values.required = properties[key].values.required ? true : false
340
- properties[key].values.unique = properties[key].values.unique ? true : false
341
- var isChain = properties[key].values.isChain ? true : false
342
- properties[key].values.isChain = isChain
343
- if (isChain) {
344
- chains.push(key)
345
- }
346
- }
347
- if (chains.length && chains.length < 2) {
348
- return Util.flashError('Chains min 2 fields number...')
349
- }
350
- if (chains.length) {
351
- let prop = chainings(table, chains)
352
- for (const key in prop) {
353
- if (prop[key].hasOwnProperty('chains')) {
354
- chains = Object.keys(prop[key].chains)
355
- if (chains.length) {
356
- properties[key].values.chains = prop[key].chains
357
- }
358
- }
359
- }
360
- }
361
- //update properties
362
- result = await connection.update({
363
- table: 'zfields',
364
- data: {
365
- properties: JSON.stringify(properties),
366
- },
367
- where: {
368
- table: table,
369
- },
370
- })
371
- //end chains
372
-
373
- //generate file models routes views
374
- body.columns = await connection.query(connection.describeTable(table))
375
- body.constraintList = await connection.query(connection.constraintList(table))
376
- body.result = result
377
- results = await axios.post(`${generatorUrl}/api/generator/generate`, body)
378
- datas = results.data
379
- let files = datas.files
380
- for (let key in files) {
381
- let filesKey = files[key]
382
- if (key == 'model') {
383
- if (filesKey.hasOwnProperty('sql')) {
384
- const sql = filesKey.sql || []
385
- for (let i = 0; i < sql.length; i++) {
386
- console.log(i + 'sql : ' + sql[i])
387
- await connection.query(sql[i])
388
- }
389
- }
390
- if (filesKey.hasOwnProperty('alter')) {
391
- const alter = filesKey.alter || []
392
- for (let i = 0; i < alter.length; i++) {
393
- console.log(alter[i])
394
- await connection.query(alter[i])
395
- }
396
- }
397
- if (filesKey.hasOwnProperty('index')) {
398
- const index = filesKey.index || []
399
- for (let i = 0; i < index.length; i++) {
400
- console.log(index[i])
401
- await connection.query(index[i])
402
- }
403
- }
404
- if (filesKey.hasOwnProperty('fk')) {
405
- let fk = filesKey.fk || []
406
- for (let i = 0; i < fk.length; i++) {
407
- console.log(fk[i])
408
- await connection.query(fk[i])
409
- }
410
- }
411
- if (filesKey.hasOwnProperty('defaultValue')) {
412
- const defaultValue = filesKey.defaultValue || []
413
- for (let i = 0; i < defaultValue.length; i++) {
414
- console.log(defaultValue[i])
415
- await connection.query(defaultValue[i])
416
- }
417
- }
418
- //console.log(JSON.stringify(filesKey.modelObj))
419
- //check if has chains here
420
- MYMODEL = filesKey.modelObj
421
- //delete/clean zgrid after changes
422
- await connection.delete({
423
- table: 'zgrid',
424
- where: {
425
- route_name: table,
426
- },
427
- })
428
- await connection.delete({
429
- table: 'zgrid_default',
430
- where: {
431
- table: table,
432
- },
433
- })
434
- //insert into zgrid default
435
- let datagrid = {
436
- company_id: 1,
437
- updated_by: 1,
438
- created_by: 1,
439
- created_at: Util.now(),
440
- updated_at: Util.now(),
441
- }
442
- datagrid.table = table
443
- datagrid.visibles = JSON.stringify(MYMODEL.grids.visibles)
444
- datagrid.invisibles = JSON.stringify(MYMODEL.grids.invisibles)
445
- datagrid.fields = JSON.stringify([...MYMODEL.grids.visibles, ...MYMODEL.grids.invisibles])
446
- await connection.insert({
447
- table: 'zgrid_default',
448
- data: datagrid,
449
- })
450
-
451
- fs.writeFileSync(`${dirRoot}/models/${filesKey.filename}`, filesKey.content)
452
- console.log(`The file model of ${filesKey.filename} is saved!`)
453
-
454
- let widgets = MYMODEL.widgets
455
- let objChains = {}
456
- let chainsTable = []
457
- let isChain = false
458
- for (let key in widgets) {
459
- let hasChains = widgets[key].hasOwnProperty('isChain') ? widgets[key].isChain : false
460
- if (hasChains) {
461
- isChain = true
462
- if (widgets[key].hasOwnProperty('table')) {
463
- chainsTable.push(widget_table)
464
- var widget_table = widgets[key].table
465
- objChains[widget_table] = {
466
- key: key,
467
- changes: [],
468
- }
469
- }
470
- }
471
- }
472
-
473
- if (isChain) {
474
- for (let key in objChains) {
475
- const model_table = MYMODELS[key] // require(`./../models/${key}`);
476
- for (let q in model_table.widgets) {
477
- if (model_table.widgets[q].hasOwnProperty('table')) {
478
- if (Util.in_array(model_table.widgets[q].table, chainsTable)) {
479
- const objChanges = {
480
- target: objChains[key].key,
481
- table: key,
482
- column: q,
483
- name: widgets[objChains[key].key].fields[1],
484
- }
485
- objChains[model_table.widgets[q].table].changes.push(objChanges)
486
- }
487
- }
488
- }
489
- }
490
- //console.log(JSON.stringify(objChains))
491
- //update model
492
- for (let key in objChains) {
493
- const keykey = objChains[key].key
494
- widgets[keykey].chains = objChains[key].changes
495
- }
496
- MYMODEL.widgets = widgets
497
- let newModel = `module.exports = ${Util.newLine}${Util.tab}{${Util.newLine}`
498
- //newModel += JSON.stringify(MYMODEL, null, 2)
499
- newModel += zRoute.buildFileModel(MYMODEL)
500
- newModel += `${Util.tab}};`
501
-
502
- fs.writeFileSync(`${dirRoot}/models/${filesKey.filename}`, newModel)
503
- }
504
- //check model if it has select relation in concat
505
- await scanning(MYMODEL, result)
506
- }
507
- //generate views
508
- let DIR_VIEW = `${dirRoot}/views/${table}`
509
- if (key == 'views') {
510
- if (!fs.existsSync(DIR_VIEW)) {
511
- fs.mkdirSync(DIR_VIEW)
512
- }
513
- let compilesJS = ['createjs.ejs', 'updatejs.ejs', 'importjs.ejs']
514
- if (!dummy) {
515
- for (const q in filesKey) {
516
- console.log(q)
517
- if (Util.in_array(q, compilesJS)) {
518
- fs.writeFileSync(`${DIR_VIEW}/${q}`, filesKey[q])
519
- } else {
520
- fs.writeFileSync(
521
- `${DIR_VIEW}/${q}`,
522
- await minify(filesKey[q], {
523
- minifyJS: true,
524
- minifyCSS: true,
525
- collapseWhitespace: true,
526
- })
527
- )
528
- }
529
- console.log(`The files views of ${q} is saved!`)
530
- }
531
- }
532
- }
533
- if (!dummy) {
534
- if (key == 'route') {
535
- fs.writeFileSync(`${dirRoot}/routes/${filesKey.filename}`, filesKey.content)
536
- console.log(`The files route of ${filesKey.filename} is saved!`)
537
- }
538
- }
539
- }
540
-
541
- //make a directory
542
- if (!dummy) {
543
- let path_script = `${dirRoot}/public/runtime/script/${table}`
544
- Util.dirExist(path_script, true)
545
- let path_head = `${dirRoot}/public/runtime/head/${table}`
546
- Util.dirExist(path_head, true)
547
- let path_end = `${dirRoot}/public/runtime/end/${table}`
548
- Util.dirExist(path_end, true)
549
- //we need to generate javascript code into runtime
550
- let relations = await zRoute.relations(req, res, MYMODEL.table)
551
- //add script
552
- let jsObj = zRoute.generateJS(req, res, MYMODEL, relations)
553
- //minify script
554
- let script = uglifyJS.minify(jsObj.script)
555
- if (script.error) {
556
- console.log(jsObj.script)
557
- throw script.error
558
- }
559
- let time = new Date().getTime()
560
- Util.deleteAllFiles(path_script)
561
- Util.deleteAllFiles(path_head)
562
- Util.deleteAllFiles(path_end)
563
- Util.writeFile(`${path_script}/${time}.js`, script.code)
564
- Util.writeFile(`${path_head}/head.txt`, jsObj.head)
565
- Util.writeFile(`${path_end}/end.txt`, jsObj.end)
566
- }
567
-
568
- //restart pm2 module in production
569
- if (process.env.NODE_ENV == 'production') {
570
- pm2.connect(function (err) {
571
- if (err) {
572
- console.log(err.toString())
573
- }
574
- pm2.restart(process.env.PM2_NAME, (err, proc) => {
575
- //io.to(room).emit("message","Restart done")
576
- })
577
- })
578
- }
579
-
580
- return Util.jsonSuccess('Success')
581
- }
582
-
583
- router.post('/savetabs', async (req, res) => {
584
- let body = req.body
585
- let table = body.table
586
- let details = body.details
587
- let left = [],
588
- right = [],
589
- tabLeft = {},
590
- tabRight = {}
591
- let json = { status: 0, title: 'error', message: 'error', url: '' }
592
- let obj = {}
593
- obj.notabs = []
594
- let labels = {}
595
- let hasTab = false
596
- if (nots.includes(table)) {
597
- return res.json(Util.flashError('Table is locked'))
598
- }
599
-
600
- let rows = await connection.results({ table: 'zfields', where: { table: table } })
601
- if (rows.length > 0) {
602
- let tabsValue = rows[0].tabs + ''
603
- if (tabsValue.length > 5) {
604
- hasTab = true
605
- let tabs = rows[0].tabs
606
- for (let i = 0; i < tabs.length; i++) {
607
- obj['arr' + i] = []
608
- tabLeft['arr' + i] = []
609
- tabRight['arr' + i] = []
610
- }
611
- }
612
- }
613
-
614
- for (let i = 0; i < details.length; i++) {
615
- let name = details[i].name
616
- let value = details[i].value
617
- if (name.indexOf('___') > -1) {
618
- let explode = name.split('___')
619
- obj[explode[1]].push(explode[0])
620
- labels[explode[0]] = value
621
- } else {
622
- if (name == 'LEFT') {
623
- if (value.indexOf('___') > -1) {
624
- var explode = value.split('___')
625
- tabLeft[explode[1]].push(explode[0])
626
- } else {
627
- left.push(value)
628
- }
629
- } else if (name == 'RIGHT') {
630
- if (value.indexOf('___') > -1) {
631
- let explode = value.split('___')
632
- tabRight[explode[1]].push(explode[0])
633
- } else {
634
- right.push(value)
635
- }
636
- } else {
637
- obj['notabs'].push(name)
638
- labels[name] = value
639
- }
640
- }
641
- }
642
- let post = {}
643
- post.labels = JSON.stringify(labels)
644
- post.details = JSON.stringify(obj)
645
- post.left = hasTab ? JSON.stringify(tabLeft) : JSON.stringify(left)
646
- post.right = hasTab ? JSON.stringify(tabRight) : JSON.stringify(right)
647
- //console.log(post.left)
648
- //console.log(JSON.stringify(post))
649
- try {
650
- if (rows.length > 0) {
651
- await connection.update({ table: 'zfields', data: post, where: { id: rows[0].id } })
652
- } else {
653
- post.table = table
654
- await connection.insert({ table: 'zfields', data: post })
655
- }
656
- json = { status: 1, title: 'Success', message: 'Success', url: '' }
657
- } catch (error) {
658
- json = Util.flashError(error.sqlMessage)
659
- }
660
-
661
- res.send(json)
662
- })
663
-
664
- const buildJoin = async (MYMODEL, result) => {
665
- let joins = result.joins || {}
666
- let table = MYMODEL.table
667
- let table_joins = []
668
- let join_list = []
669
-
670
- if (result.joins && Object.keys(joins).length > 0) {
671
- let newDataObj = {}
672
- for (let key in joins) {
673
- let THEIR_MODEL = require(`${dirRoot}/models/${key}`)
674
- //console.log(THEIR_MODEL)
675
- let arr = joins[key] || []
676
- table_joins.push(key)
677
- if (arr.length > 0) {
678
- arr.map((item) => {
679
- //console.log(item)
680
- //console.log(typeof item)
681
- const originKey = item.key.replace(`${key}___`, '')
682
- console.log(originKey)
683
- newDataObj[item.key] = item.value
684
- MYMODEL.keys.push(item.key)
685
- //MYMODEL.keysExcel.push(item.key)
686
- MYMODEL.labels[item.key] = item.value
687
- MYMODEL.fields[item.key] = THEIR_MODEL.fields[originKey]
688
- MYMODEL.options[item.key] = THEIR_MODEL.options[originKey]
689
- MYMODEL.grids.invisibles.push(item.key)
690
- MYMODEL.datas[item.key] = THEIR_MODEL.datas[originKey]
691
- MYMODEL.widgets[item.key] = THEIR_MODEL.widgets[originKey]
692
- join_list.push(item.key)
693
- })
694
- }
695
- }
696
-
697
- let sql = []
698
- //get all foreign key
699
- let rows = await connection.query(connection.foreignKeyList(table))
700
- let foreign_table_name = {}
701
- let foreignTables = []
702
- rows.map((row) => {
703
- foreignTables.push(row.foreign_table_name)
704
- foreign_table_name[row.foreign_table_name] = ` LEFT JOIN ${row.foreign_table_name} ON ${row.foreign_table_name}.id = ${table}.${row.column_name} `
705
- })
706
-
707
- //step by step
708
- let table_steps = []
709
- table_joins.map((item) => {
710
- if (foreignTables.includes(item)) {
711
- sql.push(foreign_table_name[item])
712
- table_steps.push(item)
713
- }
714
- })
715
-
716
- if (table_steps.length > 0) {
717
- for (let table_steps_item of table_steps) {
718
- let rows = await connection.query(connection.foreignKeyList(table_steps_item))
719
- let foreign_table_name = {}
720
- let foreignTables = []
721
- rows.map((row) => {
722
- foreignTables.push(row.foreign_table_name)
723
- foreign_table_name[row.foreign_table_name] = ` LEFT JOIN ${row.foreign_table_name} ON ${row.foreign_table_name}.id = ${table_steps_item}.${row.column_name} `
724
- })
725
- console.log(foreignTables)
726
- table_joins.map((item) => {
727
- if (!table_steps.includes(item)) {
728
- if (foreignTables.includes(item)) {
729
- sql.push(foreign_table_name[item])
730
- table_steps.push(item)
731
- }
732
- }
733
- })
734
- }
735
- }
736
-
737
- if (table_steps.length > 0) {
738
- for (let table_steps_item of table_steps) {
739
- let rows = await connection.query(connection.foreignKeyList(table_steps_item))
740
- let foreign_table_name = {}
741
- let foreignTables = []
742
- rows.map((row) => {
743
- foreignTables.push(row.foreign_table_name)
744
- foreign_table_name[row.foreign_table_name] = ` LEFT JOIN ${row.foreign_table_name} ON ${row.foreign_table_name}.id = ${table_steps_item}.${row.column_name} `
745
- })
746
- //console.log(foreignTables)
747
- table_joins.map((item) => {
748
- if (!table_steps.includes(item)) {
749
- if (foreignTables.includes(item)) {
750
- sql.push(foreign_table_name[item])
751
- table_steps.push(item)
752
- }
753
- }
754
- })
755
- }
756
- }
757
-
758
- //add join
759
- let JOINS_DATA = {}
760
- JOINS_DATA.tables = table_joins
761
- JOINS_DATA.list = join_list
762
- JOINS_DATA.data = joins
763
- JOINS_DATA.sql = sql
764
-
765
- MYMODEL.joins = JOINS_DATA
766
- }
767
- return MYMODEL
768
- }
769
-
770
- const columnLR = (items, dataName) => {
771
- return `<div class="col-md-6"><ol class="mydragable divboxlittle" data-name="${dataName}">${items}</ol></div>`
772
- }
773
-
774
- const columnOne = (items) => {
775
- return `<div class="row sortable"><i class="fa fa-arrows icon-float"></i><div class="col-md-12"><ol class="mydragable divboxlittle" data-name="ONE_COLUMN">${items}</ol></div></div>`
776
- }
777
-
778
- const reformatProperties = async (position, item, table, arr) => {
779
- const newData = JSON.stringify(Util.arrayDelete(arr, item))
780
- const data = {
781
- [position]: newData,
782
- }
783
- await connection.update({
784
- table: 'zfields',
785
- data: data,
786
- where: {
787
- table: table,
788
- },
789
- })
790
- }
791
-
792
- router.delete('/delete-table', csrfProtection, async (req, res) => {
793
- let table = req.body.table
794
- let json = Util.jsonSuccess('Successfully delete module')
795
- if (Util.in_array(table, nots)) {
796
- return res.json(Util.flashError('Can not be deleted!'))
797
- }
798
- if (nots.includes(table)) {
799
- return res.json(Util.flashError('Table is locked'))
800
- }
801
- try {
802
- await connection.delete({
803
- table: 'zfields',
804
- where: {
805
- table: table,
806
- },
807
- })
808
- //await connection.query("DELETE FROM zfields WHERE `table` = ?", [table]);
809
- await connection.query(`DROP table "${table}";`)
810
- //delete file
811
- let modelFile = dirRoot + '/models/' + table + '.js'
812
- fs.stat(modelFile, function (err, stats) {
813
- console.log(stats) //here we got all information of file in stats variable
814
- if (err) {
815
- return console.error(err)
816
- } else {
817
- fs.unlink(modelFile, function (err) {
818
- if (err) return console.log(err)
819
- console.log('file deleted successfully')
820
- })
821
- }
822
- })
823
-
824
- let routesFile = dirRoot + '/routes/' + table + '.js'
825
- fs.stat(routesFile, function (err, stats) {
826
- console.log(stats) //here we got all information of file in stats variable
827
- if (err) {
828
- return console.error(err)
829
- } else {
830
- fs.unlink(routesFile, function (err) {
831
- if (err) return console.log(err)
832
- console.log('file deleted successfully')
833
- })
834
- }
835
- })
836
-
837
- let runtimeFile = dirRoot + '/public/runtime/script/' + table
838
- fs.rm(
839
- runtimeFile,
840
- {
841
- recursive: true,
842
- },
843
- (error) => {
844
- if (error) {
845
- console.log(error)
846
- } else {
847
- console.log('Recursive: Directories Deleted!')
848
- }
849
- }
850
- )
851
- let runtimeFileHead = dirRoot + '/public/runtime/head/' + table
852
- fs.rm(
853
- runtimeFileHead,
854
- {
855
- recursive: true,
856
- },
857
- (error) => {
858
- if (error) {
859
- console.log(error)
860
- } else {
861
- console.log('Recursive: Directories Deleted!')
862
- }
863
- }
864
- )
865
- let runtimeFileEnd = dirRoot + '/public/runtime/end/' + table
866
- fs.rm(
867
- runtimeFileEnd,
868
- {
869
- recursive: true,
870
- },
871
- (error) => {
872
- if (error) {
873
- console.log(error)
874
- } else {
875
- console.log('Recursive: Directories Deleted!')
876
- }
877
- }
878
- )
879
-
880
- await connection.delete({
881
- table: 'zgrid',
882
- where: { route_name: table },
883
- })
884
- if (table) {
885
- const viewsFile = dirRoot + '/views/' + table
886
- fs.rm(
887
- viewsFile,
888
- {
889
- recursive: true,
890
- },
891
- (error) => {
892
- if (error) {
893
- console.log(error)
894
- } else {
895
- console.log('Recursive: Directories Deleted!')
896
- }
897
- }
898
- )
899
- }
900
- await connection.delete({
901
- table: 'zgrid_default',
902
- where: { table: table },
903
- })
904
- } catch (e) {
905
- json = Util.flashError(e.toString(), '')
906
- }
907
-
908
- res.json(json)
909
- })
910
-
911
- router.post('/add_field', csrfProtection, async (req, res) => {
912
- try {
913
- const body = req.body
914
- console.log(JSON.stringify(body))
915
- const table = body.table
916
- if (nots.includes(table)) {
917
- return res.json(Util.flashError('Table is locked'))
918
- }
919
- body.zFields = await connection.results({ table: 'zfields', where: { table: table } })
920
- const results = await axios.post(`${generatorUrl}/api/generator/create_field`, body)
921
- const datas = results.data
922
- if (datas.status == 1) {
923
- await connection.update({ table: 'zfields', where: { table: table }, data: datas.post })
924
- }
925
- res.json(datas)
926
- } catch (e) {
927
- res.json(Util.flashError(e.toString()))
928
- }
929
- })
930
-
931
- router.post('/add_container', async (req, res) => {
932
- let others = req.body.others
933
- let table = req.body.table
934
- //console.log(JSON.stringify(req.body))
935
- try {
936
- if (others && table) {
937
- await connection.update({
938
- table: 'zfields',
939
- data: {
940
- others: others,
941
- },
942
- where: {
943
- table: table,
944
- },
945
- })
946
- }
947
- } catch (e) {
948
- return res.json(Util.flashError(e.toString()))
949
- }
950
-
951
- res.json(Util.jsonSuccess('Success'))
952
- })
953
-
954
- router.post('/setting_field', csrfProtection, async (req, res) => {
955
- if (nots.includes(req.body.table)) {
956
- return res.json(Util.flashError('Table is locked'))
957
- }
958
- const body = req.body
959
- const table = body.table
960
- const html = ''
961
- body.result = await connection.result({ table: 'zfields', where: { table: table } })
962
- const results = await axios.post(`${generatorUrl}/api/generator/modal_settings`, body)
963
- const datas = results.data
964
- res.json(datas.html)
965
- })
966
-
967
- router.post('/save_setting', async (req, res) => {
968
- const html = '',
969
- table = req.query.table || ''
970
- let json = Util.jsonSuccess('Success to update')
971
- try {
972
- if (nots.includes(req.body.table)) {
973
- return res.json(Util.flashError('Table is locked'))
974
- }
975
- const post = req.body
976
- let data = await connection.result({
977
- table: 'zfields',
978
- where: { table: table },
979
- })
980
- let properties = data.properties ? data.properties : {}
981
- let propertyKey = ''
982
- for (var key in post) {
983
- propertyKey = key
984
- }
985
-
986
- properties[propertyKey].values = post[propertyKey]
987
- let insert = {
988
- properties: JSON.stringify(properties),
989
- }
990
- await connection.update({
991
- table: 'zfields',
992
- data: insert,
993
- where: { table: table },
994
- })
995
- } catch (e) {
996
- json = Util.flashError(e.toString())
997
- }
998
-
999
- res.json(json)
1000
- })
1001
-
1002
- router.delete('/delete_field', csrfProtection, async (req, res) => {
1003
- let json = Util.jsonSuccess('Success to update')
1004
- try {
1005
- if (nots.includes(req.body.table)) {
1006
- return res.json(Util.flashError('Table is locked'))
1007
- }
1008
- const table = req.body.table,
1009
- name = req.body.name
1010
- let data = await connection.result({
1011
- table: 'zfields',
1012
- where: { table: table },
1013
- })
1014
- let properties = data.properties ? data.properties : {}
1015
- delete properties[name]
1016
- let labels = data.labels ? data.labels : {}
1017
- delete labels[name]
1018
-
1019
- let left = data.left ? data.left : []
1020
- left = Util.arrayDelete(left, name)
1021
- let right = data.right ? data.right : []
1022
- right = Util.arrayDelete(right, name)
1023
- let oneColumn = data.one_column ? data.one_column : []
1024
- oneColumn = Util.arrayDelete(oneColumn, name)
1025
- let details = data.details ? data.details : {}
1026
- let detailsTemp = {}
1027
- for (var keys in details) {
1028
- detailsTemp[keys] = Util.arrayDelete(details[keys], name)
1029
- }
1030
- let newProperty = {}
1031
- newProperty.properties = JSON.stringify(properties)
1032
- newProperty.labels = JSON.stringify(labels)
1033
- newProperty.left = JSON.stringify(left)
1034
- newProperty.right = JSON.stringify(right)
1035
- newProperty.one_column = JSON.stringify(oneColumn)
1036
- newProperty.details = JSON.stringify(detailsTemp)
1037
- newProperty.sorting = JSON.stringify(data.sorting)
1038
- await connection.update({
1039
- table: 'zfields',
1040
- data: newProperty,
1041
- where: { table: table },
1042
- })
1043
- //DROP COULUMN
1044
- //ALTER TABLE table_name DROP COLUMN IF EXISTS column_name;
1045
- await connection.query(`ALTER TABLE "${table}" DROP COLUMN IF EXISTS "${name}";`)
1046
- } catch (err) {
1047
- json = Util.flashError(err.toString())
1048
- console.log(err)
1049
- console.log('ada error di update zfields')
1050
- }
1051
- res.json(json)
1052
- })
1053
-
1054
- router.post('/tab_rename', csrfProtection, async (req, res) => {
1055
- const html = '',
1056
- table = req.body.table || '',
1057
- name = req.body.name || '',
1058
- id = req.body.id || 0
1059
- let json = Util.jsonSuccess('Success to rename')
1060
- try {
1061
- if (table == '') {
1062
- return res.json(Util.flashError('table empty'))
1063
- }
1064
- if (name == '') {
1065
- return res.json(Util.flashError('name empty'))
1066
- }
1067
- let data = await connection.result({
1068
- table: 'zfields',
1069
- where: { table: table },
1070
- })
1071
- const tabs = data.tabs || []
1072
- let arr = []
1073
- tabs.forEach(function (item, index) {
1074
- if (index == id) {
1075
- arr.push(name)
1076
- } else {
1077
- arr.push(item)
1078
- }
1079
- })
1080
- let post = {
1081
- tabs: JSON.stringify(arr),
1082
- }
1083
- await connection.update({
1084
- table: 'zfields',
1085
- data: post,
1086
- where: {
1087
- table: table,
1088
- },
1089
- })
1090
- } catch (e) {
1091
- json = Util.flashError(e.toString())
1092
- }
1093
- res.json(json)
1094
- })
1095
-
1096
- const zfields = async () => {
1097
- return await connection.results({
1098
- select: `id, "table", "name", "route",tabs,labels, details, "left","right",one_column, sorting, properties,others,json`,
1099
- table: 'zfields',
1100
- orderBy: ['table', 'asc'],
1101
- })
1102
- }
1103
-
1104
- const zfieldsKeys = async () => {
1105
- return Util.arrayToObject(await zfields(), 'table')
1106
- }
1107
-
1108
- router.post('/load-form', async (req, res) => {
1109
- const table = req.body.table
1110
- let json = Util.flashError('error')
1111
- const result = await connection.result({
1112
- table: 'zfields',
1113
- where: {
1114
- table: table,
1115
- },
1116
- })
1117
- if (result.id) {
1118
- json = Util.jsonSuccess('success')
1119
- json.data = result
1120
- }
1121
- res.json(json)
1122
- })
1123
-
1124
- //save to table zfields
1125
- var saveToZFields = async (body) => {
1126
- const table = body.table
1127
- let is_approval = body.is_approval
1128
- if (typeof body.is_approval == 'string') {
1129
- if (body.is_approval == 'false') {
1130
- is_approval = 0
1131
- } else if (body.is_approval == 'true') {
1132
- is_approval = 1
1133
- }
1134
- }
1135
-
1136
- const zapprovals = {}
1137
- zapprovals.title = body.approval_title
1138
- zapprovals.type = body.type
1139
- zapprovals.approvers = body.approvers
1140
- zapprovals.knowings = body.knowings
1141
- zapprovals.content = body.template
1142
- var data = {
1143
- index_ejs: body.index_ejs,
1144
- indexcss_ejs: body.indexcss_ejs,
1145
- indexjs_ejs: body.indexjs_ejs,
1146
- form_ejs: body.form_ejs,
1147
- create_ejs: body.create_ejs,
1148
- createjs_ejs: body.createjs_ejs,
1149
- update_ejs: body.update_ejs,
1150
- updatejs_ejs: body.updatejs_ejs,
1151
- import_ejs: body.import_ejs,
1152
- importjs_ejs: body.importjs_ejs,
1153
- view_ejs: body.view_ejs,
1154
- is_approval: is_approval || 0,
1155
- approval_json: JSON.stringify(zapprovals),
1156
- others: body.others,
1157
- }
1158
-
1159
- let joinsTables = {}
1160
- let bodyJoins = body.joins || []
1161
- let bodyJoinsObj = {}
1162
- if (bodyJoins.length > 0) {
1163
- bodyJoins.map((item) => {
1164
- bodyJoinsObj[item.name] = item.value
1165
- })
1166
- }
1167
- for (let key in bodyJoinsObj) {
1168
- if (key.includes('joins_checks___')) {
1169
- let tablekeys = key.split('___')
1170
- let keyName = key.replace('joins_checks___', '')
1171
- if (!joinsTables[tablekeys[1]]) {
1172
- joinsTables[tablekeys[1]] = []
1173
- }
1174
- joinsTables[tablekeys[1]].push({ key: keyName, value: bodyJoinsObj[`joins_labels___${keyName}`] })
1175
- }
1176
- }
1177
- //console.log(joinsTables);
1178
- if (Object.keys(joinsTables).length > 0) {
1179
- data.joins = JSON.stringify(joinsTables)
1180
- }
1181
-
1182
- let result = await connection.update({
1183
- table: 'zfields',
1184
- data: data,
1185
- where: {
1186
- table: table,
1187
- },
1188
- })
1189
-
1190
- return result
1191
- }
1192
-
1193
- //drop down chains effect
1194
- const chainings = async (table, arr) => {
1195
- const results = await connection.query(connection.showFields(table))
1196
- const obj = {}
1197
- const tableObj = {}
1198
- for (let i = 0; i < results.length; i++) {
1199
- const result = results[i]
1200
- if (Util.in_array(result.COLUMN_NAME, arr)) {
1201
- obj[result.COLUMN_NAME] = {
1202
- table: result.REFERENCED_TABLE_NAME,
1203
- }
1204
- tableObj[result.REFERENCED_TABLE_NAME] = result.COLUMN_NAME
1205
- }
1206
- }
1207
-
1208
- for (const key in obj) {
1209
- const rows = await connection.query(connection.showFields(obj[key].table))
1210
- rows.forEach(function (row) {
1211
- for (var q in obj) {
1212
- if (row.REFERENCED_TABLE_NAME == obj[q].table) {
1213
- if (!obj[q].chains) {
1214
- obj[q].chains = {}
1215
- }
1216
- obj[q].chains[key] = {
1217
- column: row.COLUMN_NAME,
1218
- table: row.TABLE_NAME,
1219
- }
1220
- }
1221
- }
1222
- })
1223
- }
1224
- return obj
1225
- }
1226
-
1227
- router.post('/sorting', async (req, res) => {
1228
- let sorting = req.body.sorting
1229
- let table = req.body.table
1230
- await connection.update({
1231
- table: 'zfields',
1232
- data: {
1233
- sorting: sorting,
1234
- },
1235
- where: { table: table },
1236
- })
1237
- res.send('OK')
1238
- })
1239
-
1240
- router.post('/export', async (req, res) => {
1241
- const table = req.body.table
1242
- let json = Util.jsonSuccess('file Complete')
1243
- if (table) {
1244
- const result = await connection.result({
1245
- table: 'zfields',
1246
- where: {
1247
- table: table,
1248
- },
1249
- })
1250
- const dir = `${dirRoot}/public/uploads/zgenerator`
1251
- if (!fs.existsSync(dir)) {
1252
- fs.mkdirSync(dir)
1253
- }
1254
- const text = JSON.stringify(result)
1255
- fs.writeFileSync(`${dir}/${table}.json`, text)
1256
- } else {
1257
- json = Util.flashError('no table selected')
1258
- }
1259
- res.json(json)
1260
- })
1261
-
1262
- router.post('/import', async (req, res) => {
1263
- let json = Util.flashError('Error File')
1264
- let table = ''
1265
- try {
1266
- let isEmptyFiles = Util.isEmptyObject(req.files)
1267
- if (!isEmptyFiles) {
1268
- const file = req.files['import-file']
1269
- const name = file.name
1270
- const mime = file.mimetype
1271
- if (mime == 'application/json') {
1272
- const string = file.data.toString('utf8')
1273
- const jsonFile = JSON.parse(string)
1274
- table = jsonFile.table
1275
- delete jsonFile.id
1276
- const data = {}
1277
- for (const key in jsonFile) {
1278
- let value = jsonFile[key]
1279
- if (typeof value == 'object') {
1280
- value = JSON.stringify(value)
1281
- }
1282
- data[key] = value
1283
- }
1284
- if (!data.tabs) {
1285
- data.tabs = '[]'
1286
- }
1287
- data.company_id = 1
1288
- data.created_by = res.locals.userId || 1
1289
- data.updated_by = res.locals.userId || 1
1290
- data.created_at = Util.now()
1291
- data.updated_at = Util.now()
1292
- data.is_approval = data.is_approval == 'null' ? 0 : data.is_approval
1293
- delete data.approval_history
1294
- const results = await connection.results({
1295
- table: 'zfields',
1296
- where: {
1297
- table: table,
1298
- },
1299
- })
1300
- if (results.length) {
1301
- await connection.update({
1302
- table: 'zfields',
1303
- data: data,
1304
- where: {
1305
- table: table,
1306
- },
1307
- })
1308
- } else {
1309
- await connection.insert({
1310
- table: 'zfields',
1311
- data: data,
1312
- })
1313
- }
1314
- json = Util.jsonSuccess('Success to add module, please generate tax to make a file')
1315
- }
1316
- }
1317
- } catch (e) {
1318
- console.log(e)
1319
- json.message = e.toString()
1320
- }
1321
- json.table = table
1322
- res.json(json)
1323
- })
1324
-
1325
- /*
1326
- Scanning relation id to name
1327
- */
1328
- const scanning = async (MYMODEL, result) => {
1329
- //let MYMODEL = require(`${dirRoot}/models/${table}`);
1330
- let table = MYMODEL.table
1331
- const widgets = MYMODEL.widgets
1332
- const not_scanning = ['created_by', 'updated_by']
1333
- const concat_bracket = /(?<=\().+?(?=\))/g
1334
- let changeWidgets = {}
1335
- let changes = []
1336
- /*for (let key in widgets) {
1337
- if (widgets[key].name == 'relation' || widgets[key].name == 'dropdown_multi' || widgets[key].name == 'typeahead') {
1338
- if (!Util.in_array(key, not_scanning)) {
1339
- let fields = widgets[key].fields
1340
- //let concat = fields[1].indexOf('CONCAT(') > -1 ? fields[1].substring()
1341
- let arr = fields[1].match(concat_bracket) || []
1342
- if (arr.length) {
1343
- let str = Util.replaceAll(arr[0], '"', '')
1344
- let mysplits = str.indexOf(',') > -1 ? str.split(',') : [str]
1345
- let MYMODEL_TABLE = require(`${dirRoot}/models/${widgets[key].table}`)
1346
- let widgetsRelations = MYMODEL_TABLE.widgets
1347
- let relationsKeys = []
1348
- let relationsKeysObject = {}
1349
- for (let k in widgetsRelations) {
1350
- if (widgetsRelations[k].name == 'relation') {
1351
- if (!Util.in_array(k, not_scanning)) {
1352
- relationsKeys.push(k)
1353
- relationsKeysObject[k] = `(SELECT ${widgetsRelations[k].fields[1]} FROM ${widgetsRelations[k].table} where id = `
1354
- }
1355
- }
1356
- }
1357
- let myarr = []
1358
- mysplits.forEach(function (item) {
1359
- if (Util.in_array(item, relationsKeys)) {
1360
- changes.push(key)
1361
- myarr.push(relationsKeysObject[item] + ` ${item} )`)
1362
- } else {
1363
- myarr.push(item)
1364
- }
1365
- })
1366
- let myjoin = `CONCAT(${myarr.join(',')})`
1367
- widgets[key].fields = ['id', myjoin]
1368
- }
1369
- }
1370
- }
1371
- }*/
1372
-
1373
- if (changes.length) {
1374
- //rewrite model
1375
- MYMODEL.widgets = widgets
1376
- let newModel = `module.exports = { ${Util.newLine}`
1377
- newModel += zRoute.buildFileModel(MYMODEL)
1378
- newModel += `${Util.newLine}`
1379
- newModel += `}`
1380
- fs.writeFileSync(`${dirRoot}/models/${MYMODEL.table}.js`, newModel)
1381
- }
1382
-
1383
- //check if has join
1384
- //build join
1385
- //console.log(JSON.stringify(MYMODEL))
1386
- MYMODEL = await buildJoin(MYMODEL, result)
1387
- //console.log(JSON.stringify(MYMODEL))
1388
-
1389
- let newModel = `module.exports = { ${Util.newLine}`
1390
- newModel += zRoute.buildFileModel(MYMODEL)
1391
- newModel += `${Util.newLine}`
1392
- newModel += `}`
1393
- fs.writeFileSync(`${dirRoot}/models/${MYMODEL.table}.js`, newModel)
1394
- //return MYMODEL;
1395
- }
1396
-
1397
- //generate all css/js assets
1398
- router.post('/generate-assets', async (req, res) => {
1399
- let notifObj = Util.jsonSuccess('Success, generate all assets')
1400
- try {
1401
- let MYMODELS = zRoute.MYMODELS()
1402
- delete MYMODELS.zrole
1403
- for (let key in MYMODELS) {
1404
- let MYMODEL = MYMODELS[key]
1405
- let table = MYMODEL.table
1406
- let path_script = `${dirRoot}/public/runtime/script/${table}`
1407
- Util.dirExist(path_script, true)
1408
- let path_head = `${dirRoot}/public/runtime/head/${table}`
1409
- Util.dirExist(path_head, true)
1410
- let path_end = `${dirRoot}/public/runtime/end/${table}`
1411
- Util.dirExist(path_end, true)
1412
- //we need to generate javascript code into runtime
1413
- let relations = await zRoute.relations(req, res, MYMODEL.table)
1414
- //add script
1415
- let jsObj = zRoute.generateJS(req, res, MYMODEL, relations)
1416
- let time = new Date().getTime()
1417
- Util.deleteAllFiles(path_head)
1418
- Util.deleteAllFiles(path_end)
1419
- Util.deleteAllFiles(path_script)
1420
-
1421
- //minify script
1422
- let script = uglifyJS.minify(jsObj.script)
1423
- if (script.error) throw script.error
1424
- Util.writeFile(`${path_script}/${time}.js`, script.code)
1425
- Util.writeFile(`${path_head}/head.txt`, jsObj.head)
1426
- Util.writeFile(`${path_end}/end.txt`, jsObj.end)
1427
- }
1428
- } catch (e) {
1429
- notifObj = Util.flashError(e.toString())
1430
- }
1431
- res.json(notifObj)
1432
- })
1433
-
1434
- router.post('/minify', async (req, res) => {
1435
- let notifyObj = Util.jsonSuccess('Success to cached')
1436
- try {
1437
- notifyObj = await viewsMini()
1438
- } catch (e) {
1439
- console.log(e)
1440
- notifyObj = Util.flashError(e.toString())
1441
- }
1442
- res.json(notifyObj)
1443
- })
1444
-
1445
- const viewsMini = async () => {
1446
- let notifyObj = Util.jsonSuccess('Success')
1447
- const viewDir = `${dirRoot}/views`
1448
- const layoutsDir = `${dirRoot}/views/layouts`
1449
- let item
1450
- try {
1451
- let views = Util.getAllFiles(viewDir)
1452
- let options = {
1453
- minifyJS: true,
1454
- minifyCSS: true,
1455
- collapseWhitespace: true,
1456
- }
1457
- const notViewDir = ['zgenerator', 'layouts', 'index', 'zindex']
1458
- for (const dir of views) {
1459
- console.log('dir :', dir)
1460
- if (!Util.in_array(dir, notViewDir)) {
1461
- let files = Util.getAllFiles(`${viewDir}/${dir}`)
1462
- //console.log(files);
1463
- for (item of files) {
1464
- if (item.includes('.ejs')) {
1465
- let filename = `${viewDir}/${dir}/${item}`
1466
- let content = Util.readFile(filename)
1467
- let contentChange = await minify(content, options)
1468
- fs.writeFileSync(filename, contentChange)
1469
- }
1470
- }
1471
- }
1472
- }
1473
-
1474
- let layouts = Util.getAllFiles(layoutsDir)
1475
- for (item of layouts) {
1476
- if (item.includes('.ejs')) {
1477
- let filename = `${layoutsDir}//${item}`
1478
- let content = Util.readFile(filename)
1479
- let contentChange = await minify(content, options)
1480
- fs.writeFileSync(filename, contentChange)
1481
- }
1482
- }
1483
- } catch (e) {
1484
- notifyObj = Util.flashError(`error in item : ${item} , error str :${e.toString()}`)
1485
- }
1486
- return notifyObj
1487
- }
1488
-
1489
- router.post('/load-joins', async (req, res) => {
1490
- let jsonNotif = Util.jsonSuccess('Success')
1491
- let html = ''
1492
- try {
1493
- let body = req.body
1494
- console.log(body)
1495
- let table = body.table
1496
- html = await loadJoins(table)
1497
- jsonNotif.html = html
1498
- } catch (e) {
1499
- console.log(e)
1500
- }
1501
- res.json(jsonNotif)
1502
- })
1503
-
1504
- router.post('/remove-joins', async (req, res) => {
1505
- let jsonNotif = Util.jsonSuccess('Success')
1506
- let html = ''
1507
- try {
1508
- let body = req.body
1509
- console.log(body)
1510
- let table = body.table
1511
- let table_join = body.table_join
1512
- let result = await connection.result({
1513
- table: 'zfields',
1514
- where: {
1515
- table: table,
1516
- },
1517
- })
1518
- let resultJoins = result.joins || {}
1519
- delete resultJoins[table_join]
1520
- await connection.update({
1521
- table: 'zfields',
1522
- data: {
1523
- joins: JSON.stringify(resultJoins),
1524
- },
1525
- where: {
1526
- table: table,
1527
- },
1528
- })
1529
- } catch (e) {
1530
- console.log(e)
1531
- }
1532
- res.json(jsonNotif)
1533
- })
1534
-
1535
- router.post('/joins', async (req, res) => {
1536
- let jsonNotif = Util.jsonSuccess('Success')
1537
- let html = ''
1538
- try {
1539
- let body = req.body
1540
- console.log(body)
1541
- let table = body.table
1542
- let table_join = body.table_join
1543
- let result = await connection.result({
1544
- table: 'zfields',
1545
- where: {
1546
- table: table,
1547
- },
1548
- })
1549
- let resultJoins = result.joins || {}
1550
- resultJoins[table_join] = []
1551
- let myzfield = await connection.update({
1552
- table: 'zfields',
1553
- data: {
1554
- joins: JSON.stringify(resultJoins),
1555
- },
1556
- where: {
1557
- table: table,
1558
- },
1559
- })
1560
- jsonNotif.json = resultJoins
1561
- html = await joinHTML(resultJoins, myzfield)
1562
- } catch (e) {
1563
- console.log(e)
1564
- jsonNotif = Util.flashError(e + '')
1565
- }
1566
- jsonNotif.html = html
1567
- res.json(jsonNotif)
1568
- })
1569
-
1570
- async function loadJoins(table) {
1571
- let html = ''
1572
- try {
1573
- /* let sql = `select ${table}.* from ${table} `;
1574
- console.log(sql)*/
1575
- let result = await connection.result({
1576
- table: 'zfields',
1577
- where: {
1578
- table: table,
1579
- },
1580
- })
1581
- let joinsObj = result.joins || {}
1582
- html = await joinHTML(joinsObj, result)
1583
- } catch (e) {
1584
- console.log(e)
1585
- html = e + ''
1586
- }
1587
- return html
1588
- }
1589
-
1590
- async function joinHTML(json, myzfield) {
1591
- let html = ``
1592
- try {
1593
- let zfields = await connection.results({
1594
- table: 'zfields',
1595
- })
1596
- let zfieldsObj = Util.arrayToObject(zfields, 'table')
1597
- for (let key in json) {
1598
- html += `<div class="joinContainer col-md-4">`
1599
- html += `<h5>${zfieldsObj[key].name} <button type="button" class="btn btn-danger" onclick="removeJoins('${key}')"><i class="fa fa-trash "></i> </button></h5>`
1600
- html += fieldHTML(zfieldsObj[key], myzfield)
1601
- html += `</div>`
1602
- }
1603
- } catch (e) {
1604
- html = e + ''
1605
- }
1606
- return html
1607
- }
1608
-
1609
- function fieldHTML(obj, myzfield) {
1610
- let html = ``
1611
- try {
1612
- let labels = obj.labels
1613
- let table = obj.table
1614
- let myzfieldJoins = myzfield.joins || {}
1615
- for (let key in labels) {
1616
- let mylabel = labels[key]
1617
- let selected = ''
1618
- if (myzfieldJoins[table]) {
1619
- let arr = myzfieldJoins[table] || []
1620
- arr.map((item) => {
1621
- if (item.key == `${table}___${key}`) {
1622
- selected = ` checked `
1623
- mylabel = item.value
1624
- }
1625
- })
1626
- }
1627
- html += `<div class="input-group">
1628
- <div class="input-group-prepend">
1629
- <span class="input-group-text"><input type="checkbox" ${selected} name="joins_checks___${table}___${key}"></span>
1630
- <span class="input-group-text">${key}</span>
1631
- <input type="text" class="form-control" name="joins_labels___${table}___${key}" id="joins___${table}___${key}" value="${mylabel}">
1632
- </div>
1633
- </div>`
1634
- }
1635
- } catch (e) {
1636
- html = e + ''
1637
- }
1638
- return html
1639
- }
1640
-
1641
- module.exports = router
1
+ const express = require('express')
2
+ const router = express.Router()
3
+ const csrf = require('csurf')
4
+ const csrfProtection = csrf({ cookie: true })
5
+ const fs = require('fs-extra')
6
+ const axios = require('axios')
7
+ const pm2 = require('pm2')
8
+ const uglifyJS = require('uglify-js')
9
+ const { minify } = require('html-minifier-terser')
10
+ const zRoute = require('./zRoute')
11
+ const connection = require('./connection')
12
+ const Util = require('./Util')
13
+ const moduleLib = require('./moduleLib')
14
+ const myCache = require('./cache')
15
+ const ejs = require('ejs')
16
+ var app = express()
17
+ const path = require('path')
18
+
19
+ const nots = ['index', 'uploads', 'js', 'css', 'log', 'generator', 'zmenu', 'zgenerator', 'zfields', 'zrole', 'zfunction', 'zgrid', 'zgrid_default', 'zpage', 'zlayout', 'zerror', 'zuser_company']
20
+ //const nots = [];
21
+ //const generatorUrl = 'http://localhost:3005';
22
+ const generatorUrl = 'https://generator.cmsqu.com'
23
+
24
+ const bodyView = Util.readFile(require.resolve(__dirname + '/views/generator.ejs'))
25
+
26
+ router.get('/', csrfProtection, async (req, res) => {
27
+ let table = req.query.table || '',
28
+ route = '',
29
+ jsonData = {},
30
+ zForms = {},
31
+ relations = {},
32
+ approvalDatas = { is_approval: false }
33
+ const MYMODELS = myCache.get('MYMODELS')
34
+ let datas = await axios.post(`${generatorUrl}/api/generator/index`)
35
+ jsonData = datas.data
36
+ jsonData.rows = await zfieldsKeys()
37
+ if (table) {
38
+ jsonData.datas = jsonData.rows[table] || {}
39
+ }
40
+ jsonData.fields = await connection.query(connection.showFullFields(table))
41
+ zForms.obj = {}
42
+ let sorting = ''
43
+ if (table) {
44
+ let contentScript = `var ZFIELDS = ${JSON.stringify(jsonData.rows, null, 2)};`
45
+ moduleLib.addScript(req, res, contentScript)
46
+ moduleLib.editor(req, res)
47
+ let MYMODEL_APPROVERS = MYMODELS['zapprovals']
48
+ let zfieldData = await connection.result({
49
+ table: 'zfields',
50
+ where: {
51
+ table: table,
52
+ },
53
+ })
54
+ sorting = JSON.stringify(zfieldData.sorting)
55
+ approvalDatas = MYMODEL_APPROVERS.datas
56
+ if (zfieldData) {
57
+ let approvalJSON = zfieldData.approval_json || {}
58
+ approvalDatas.is_approval = zfieldData.is_approval || false
59
+ approvalDatas.title = approvalJSON.title || ''
60
+ approvalDatas.type = approvalJSON.type || 1
61
+ approvalDatas.approvers = approvalJSON.approvers ? approvalJSON.approvers : []
62
+ approvalDatas.knowings = approvalJSON.knowings || []
63
+ approvalDatas.template = approvalJSON.content || ''
64
+ zForms = await zRoute.formsFieldSync(req, res, MYMODEL_APPROVERS, approvalDatas)
65
+ }
66
+ }
67
+
68
+ const jsonDatas = jsonData.datas
69
+ const lock = nots.includes(table) ? 1 : 0
70
+ const jsonDatasJson = jsonDatas.hasOwnProperty('json') && jsonDatas.json ? jsonDatas.json : {}
71
+ const checkDummy = Object.prototype.hasOwnProperty.call(jsonDatasJson, 'dummy') && jsonDatasJson.dummy ? 'checked' : ''
72
+ const renderData = {
73
+ datas: jsonDatas,
74
+ table: table,
75
+ rows: jsonData.rows,
76
+ checkDummy: checkDummy,
77
+ csrfToken: req.csrfToken(),
78
+ route: table,
79
+ selects: jsonData.selects,
80
+ zForms: zForms,
81
+ relations: relations,
82
+ approvalDatas: approvalDatas,
83
+ sorting: sorting,
84
+ lock: lock,
85
+ routeName: res.locals.routeName,
86
+ }
87
+
88
+ const bodyHTML = ejs.render(bodyView, renderData)
89
+ const endHTML = ejs.render(Util.readFile(require.resolve(__dirname + '/views/generatorjs.ejs')), renderData)
90
+ let dataRender = renderData
91
+ dataRender.bodyHTML = bodyHTML
92
+ dataRender.endHTML = endHTML
93
+ res.render(require.resolve(__dirname + '/views/generator_layout.ejs'), dataRender)
94
+ })
95
+
96
+ router.post('/fields', async (req, res) => {
97
+ try {
98
+ let body = req.body
99
+ let table = body.table || ''
100
+ let result = {},
101
+ fields = {},
102
+ rowsFields = []
103
+ if (table) {
104
+ result = await connection.result({ table: 'zfields', where: { table: table } })
105
+ fields = await connection.query(connection.showFullFields(table))
106
+ rowsFields = await connection.query(connection.describeTable(table))
107
+ }
108
+ let objData = {
109
+ result: result,
110
+ fields: fields,
111
+ rowsFields: rowsFields,
112
+ table: table,
113
+ }
114
+ let datas = await axios.post(`${generatorUrl}/api/generator/modal`, objData)
115
+ res.json(datas.data)
116
+ } catch (e) {
117
+ console.log(e)
118
+ res.json(e.toString())
119
+ }
120
+ })
121
+
122
+ /*
123
+ Create new Module/Table
124
+ */
125
+ router.post('/', csrfProtection, async (req, res) => {
126
+ try {
127
+ let results = await axios.post(`${generatorUrl}/api/generator/create`, req.body)
128
+ let datas = results.data
129
+ if (datas.status == 0) {
130
+ res.json(datas)
131
+ } else {
132
+ if (nots.includes(datas.post.table)) {
133
+ return res.json(Util.flashError('Table is locked'))
134
+ }
135
+ await connection.insert({
136
+ table: 'zfields',
137
+ data: datas.post,
138
+ })
139
+ await connection.query(datas.sql)
140
+ res.json(datas)
141
+ }
142
+ } catch (err) {
143
+ res.json(Util.flashError(err.toString()))
144
+ }
145
+ })
146
+
147
+ router.post('/reset', async (req, res) => {
148
+ try {
149
+ let json = Util.jsonSuccess('Reset Success')
150
+ let table = req.body.table
151
+ if (nots.includes(table)) {
152
+ return res.json(Util.flashError('Table is locked'))
153
+ }
154
+ if (table) {
155
+ let results = await axios.post(`${generatorUrl}/api/generator/reset`, req.body)
156
+ let datas = results.data
157
+ await connection.update({
158
+ table: 'zfields',
159
+ data: datas,
160
+ where: {
161
+ table: table,
162
+ },
163
+ })
164
+ } else {
165
+ json = Util.flashError('error')
166
+ }
167
+ res.json(json)
168
+ } catch (e) {
169
+ console.log(e.toString())
170
+ json = Util.flashError('error')
171
+ res.json(json)
172
+ }
173
+ })
174
+
175
+ router.post('/tabs', async (req, res) => {
176
+ let json = { status: 0, title: 'error', url: '' }
177
+ let body = req.body
178
+ let table = body.table || ''
179
+ let title = body.title || ''
180
+ let tabs = body.tabs || []
181
+ if (table == '') {
182
+ json.title = 'table is empty'
183
+ return res.send(json)
184
+ }
185
+ if (title == '') {
186
+ json.title = 'title is empty'
187
+ return res.send(json)
188
+ }
189
+ if (nots.includes(table)) {
190
+ return res.json(Util.flashError('Table is locked'))
191
+ }
192
+ let post = {}
193
+ post.table = table
194
+ post.tabs = JSON.stringify(tabs)
195
+ post.name = title
196
+ if (body.hasOwnProperty('json')) {
197
+ post.json = JSON.stringify(body.json)
198
+ } else {
199
+ post.json = JSON.stringify({ dummy: 0 })
200
+ }
201
+ let results = await connection.results({
202
+ table: 'zfields',
203
+ where: {
204
+ table: table,
205
+ },
206
+ })
207
+
208
+ if (results.length == 0) {
209
+ await connection.insert({ table: 'zfields', data: post })
210
+ } else {
211
+ //original data
212
+ let tabOri = results[0].tabs || []
213
+ let detailOri = results[0].details || {}
214
+ let leftOri = results[0].left || []
215
+ let rightOri = results[0].right || []
216
+ let oneColumnOri = results[0].one_column || []
217
+ let objOri = {}
218
+ let arrayOri = {}
219
+ tabOri.map((item, index) => {
220
+ objOri[item] = `arr${index}`
221
+ arrayOri[item] = index
222
+ })
223
+ //end original data
224
+ if (tabOri.length > 0) {
225
+ if (JSON.stringify(tabs) !== JSON.stringify(tabOri)) {
226
+ let details = {}
227
+ //remove Object in array
228
+ let left = leftOri.filter((item) => typeof item !== 'object') || [],
229
+ right = rightOri.filter((item) => typeof item !== 'object') || [],
230
+ oneColumn = oneColumnOri.filter((item) => typeof item !== 'object') || []
231
+
232
+ details.notabs = detailOri.notabs
233
+ tabs.map((item, index) => {
234
+ let key = `arr${index}`
235
+ let valueIndex = arrayOri[item]
236
+ //details
237
+ details[key] = detailOri[objOri[item]] || []
238
+ //left
239
+ let objLeft = leftOri[valueIndex] && leftOri[valueIndex].hasOwnProperty(`arr${arrayOri[item]}`) ? leftOri[valueIndex][`arr${arrayOri[item]}`] : []
240
+ left.push({ [key]: objLeft })
241
+ //right
242
+ let objRight = rightOri[valueIndex] && rightOri[valueIndex].hasOwnProperty(`arr${arrayOri[item]}`) ? rightOri[valueIndex][`arr${arrayOri[item]}`] : []
243
+ right.push({ [key]: objRight })
244
+ //one column
245
+ let objOneColumn = oneColumnOri[valueIndex] && oneColumnOri[valueIndex].hasOwnProperty(`arr${arrayOri[item]}`) ? oneColumnOri[valueIndex][`arr${arrayOri[item]}`] : []
246
+ oneColumn.push({ [key]: objOneColumn })
247
+ })
248
+ post.details = JSON.stringify(details)
249
+ post.left = JSON.stringify(left)
250
+ post.right = JSON.stringify(right)
251
+ post.one_column = JSON.stringify(oneColumn)
252
+ }
253
+ }
254
+ await connection.update({ table: 'zfields', where: { id: results[0].id }, data: post })
255
+ }
256
+
257
+ json.status = 1
258
+ json.url = '/generator?table=' + table
259
+ res.send(json)
260
+ })
261
+
262
+ //after drag and drop then save
263
+ // and generate
264
+ router.post('/save_and_generate', csrfProtection, async (req, res) => {
265
+ try {
266
+ if (nots.includes(req.body.table)) {
267
+ return res.json(Util.flashError('Table is locked'))
268
+ }
269
+ //console.log(JSON.stringify(req.body))
270
+ const json = await generate(req, res)
271
+ res.json(json)
272
+ } catch (e) {
273
+ console.log(e)
274
+ res.status(200).json({ message: e + '' })
275
+ }
276
+ })
277
+
278
+ const generate = async (req, res) => {
279
+ const body = req.body
280
+ const table = body.table
281
+ const MYMODELS = myCache.get('MYMODELS')
282
+ let MYMODEL = {}
283
+ let chains = []
284
+ let datas
285
+ let results
286
+ let dummy = false
287
+
288
+ //save data into table zfields
289
+ //console.log(JSON.stringify(body.others))
290
+ const others = body.others
291
+ //return;
292
+ await saveToZFields(body)
293
+
294
+ let exist = await connection.query(connection.describeTable(table))
295
+ if (exist.length) {
296
+ body.rows = await connection.results({ table: 'zfields', where: { table: table } })
297
+ body.checks = await connection.query(`SELECT 'public.${table}'::regclass`)
298
+ } else {
299
+ let sql = `
300
+ CREATE TABLE ${table} (
301
+ id BIGSERIAL PRIMARY KEY,
302
+ company_id BIGINT NOT NULL,
303
+ lock smallint default 0,
304
+ approval_status smallint DEFAULT 1,
305
+ approval_history jsonb[] DEFAULT NULL,
306
+ updated_by BIGINT DEFAULT NULL,
307
+ created_by BIGINT DEFAULT NULL,
308
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
309
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
310
+ CONSTRAINT fk_${table}_company_id FOREIGN KEY (company_id) REFERENCES zcompany (id)
311
+ );`
312
+ await connection.query(sql)
313
+ body.checks = await connection.query(`SELECT 'public.${table}'::regclass`)
314
+ body.rows = await connection.results({ table: 'zfields', where: { table: table } })
315
+ }
316
+ body.others = others
317
+ results = await axios.post(`${generatorUrl}/api/generator/properties`, body)
318
+ datas = results.data
319
+ if (datas.create_table.hasOwnProperty('sql')) {
320
+ await connection.query(datas.create_table.sql)
321
+ return generate(body)
322
+ }
323
+
324
+ let result = await connection.update({
325
+ table: 'zfields',
326
+ data: datas.updateFields.post,
327
+ where: {
328
+ id: datas.updateFields.id,
329
+ },
330
+ })
331
+ let resultJSON = Object.prototype.hasOwnProperty.call(result, 'json') ? result.json : {}
332
+ if (resultJSON && Object.prototype.hasOwnProperty.call(resultJSON, 'dummy')) {
333
+ dummy = resultJSON.dummy == 1 ? true : false
334
+ }
335
+ let properties = result.properties
336
+ //update if any chains
337
+ for (let key in properties) {
338
+ //override
339
+ properties[key].values.required = properties[key].values.required ? true : false
340
+ properties[key].values.unique = properties[key].values.unique ? true : false
341
+ var isChain = properties[key].values.isChain ? true : false
342
+ properties[key].values.isChain = isChain
343
+ if (isChain) {
344
+ chains.push(key)
345
+ }
346
+ }
347
+ if (chains.length && chains.length < 2) {
348
+ return Util.flashError('Chains min 2 fields number...')
349
+ }
350
+ if (chains.length) {
351
+ let prop = chainings(table, chains)
352
+ for (const key in prop) {
353
+ if (prop[key].hasOwnProperty('chains')) {
354
+ chains = Object.keys(prop[key].chains)
355
+ if (chains.length) {
356
+ properties[key].values.chains = prop[key].chains
357
+ }
358
+ }
359
+ }
360
+ }
361
+ //update properties
362
+ result = await connection.update({
363
+ table: 'zfields',
364
+ data: {
365
+ properties: JSON.stringify(properties),
366
+ },
367
+ where: {
368
+ table: table,
369
+ },
370
+ })
371
+ //end chains
372
+
373
+ //generate file models routes views
374
+ body.columns = await connection.query(connection.describeTable(table))
375
+ body.constraintList = await connection.query(connection.constraintList(table))
376
+ body.result = result
377
+ results = await axios.post(`${generatorUrl}/api/generator/generate`, body)
378
+ datas = results.data
379
+ let files = datas.files
380
+ for (let key in files) {
381
+ let filesKey = files[key]
382
+ if (key == 'model') {
383
+ if (filesKey.hasOwnProperty('sql')) {
384
+ const sql = filesKey.sql || []
385
+ for (let i = 0; i < sql.length; i++) {
386
+ console.log(i + 'sql : ' + sql[i])
387
+ await connection.query(sql[i])
388
+ }
389
+ }
390
+ if (filesKey.hasOwnProperty('alter')) {
391
+ const alter = filesKey.alter || []
392
+ for (let i = 0; i < alter.length; i++) {
393
+ console.log(alter[i])
394
+ await connection.query(alter[i])
395
+ }
396
+ }
397
+ if (filesKey.hasOwnProperty('index')) {
398
+ const index = filesKey.index || []
399
+ for (let i = 0; i < index.length; i++) {
400
+ console.log(index[i])
401
+ await connection.query(index[i])
402
+ }
403
+ }
404
+ if (filesKey.hasOwnProperty('fk')) {
405
+ let fk = filesKey.fk || []
406
+ for (let i = 0; i < fk.length; i++) {
407
+ console.log(fk[i])
408
+ await connection.query(fk[i])
409
+ }
410
+ }
411
+ if (filesKey.hasOwnProperty('defaultValue')) {
412
+ const defaultValue = filesKey.defaultValue || []
413
+ for (let i = 0; i < defaultValue.length; i++) {
414
+ console.log(defaultValue[i])
415
+ await connection.query(defaultValue[i])
416
+ }
417
+ }
418
+ //console.log(JSON.stringify(filesKey.modelObj))
419
+ //check if has chains here
420
+ MYMODEL = filesKey.modelObj
421
+ //delete/clean zgrid after changes
422
+ await connection.delete({
423
+ table: 'zgrid',
424
+ where: {
425
+ route_name: table,
426
+ },
427
+ })
428
+ await connection.delete({
429
+ table: 'zgrid_default',
430
+ where: {
431
+ table: table,
432
+ },
433
+ })
434
+ //insert into zgrid default
435
+ let datagrid = {
436
+ company_id: 1,
437
+ updated_by: 1,
438
+ created_by: 1,
439
+ created_at: Util.now(),
440
+ updated_at: Util.now(),
441
+ }
442
+ datagrid.table = table
443
+ datagrid.visibles = JSON.stringify(MYMODEL.grids.visibles)
444
+ datagrid.invisibles = JSON.stringify(MYMODEL.grids.invisibles)
445
+ datagrid.fields = JSON.stringify([...MYMODEL.grids.visibles, ...MYMODEL.grids.invisibles])
446
+ await connection.insert({
447
+ table: 'zgrid_default',
448
+ data: datagrid,
449
+ })
450
+
451
+ fs.writeFileSync(`${dirRoot}/models/${filesKey.filename}`, filesKey.content)
452
+ console.log(`The file model of ${filesKey.filename} is saved!`)
453
+
454
+ let widgets = MYMODEL.widgets
455
+ let objChains = {}
456
+ let chainsTable = []
457
+ let isChain = false
458
+ for (let key in widgets) {
459
+ let hasChains = widgets[key].hasOwnProperty('isChain') ? widgets[key].isChain : false
460
+ if (hasChains) {
461
+ isChain = true
462
+ if (widgets[key].hasOwnProperty('table')) {
463
+ chainsTable.push(widget_table)
464
+ var widget_table = widgets[key].table
465
+ objChains[widget_table] = {
466
+ key: key,
467
+ changes: [],
468
+ }
469
+ }
470
+ }
471
+ }
472
+
473
+ if (isChain) {
474
+ for (let key in objChains) {
475
+ const model_table = MYMODELS[key] // require(`./../models/${key}`);
476
+ for (let q in model_table.widgets) {
477
+ if (model_table.widgets[q].hasOwnProperty('table')) {
478
+ if (Util.in_array(model_table.widgets[q].table, chainsTable)) {
479
+ const objChanges = {
480
+ target: objChains[key].key,
481
+ table: key,
482
+ column: q,
483
+ name: widgets[objChains[key].key].fields[1],
484
+ }
485
+ objChains[model_table.widgets[q].table].changes.push(objChanges)
486
+ }
487
+ }
488
+ }
489
+ }
490
+ //console.log(JSON.stringify(objChains))
491
+ //update model
492
+ for (let key in objChains) {
493
+ const keykey = objChains[key].key
494
+ widgets[keykey].chains = objChains[key].changes
495
+ }
496
+ MYMODEL.widgets = widgets
497
+ let newModel = `module.exports = ${Util.newLine}${Util.tab}{${Util.newLine}`
498
+ //newModel += JSON.stringify(MYMODEL, null, 2)
499
+ newModel += zRoute.buildFileModel(MYMODEL)
500
+ newModel += `${Util.tab}};`
501
+
502
+ fs.writeFileSync(`${dirRoot}/models/${filesKey.filename}`, newModel)
503
+ }
504
+ //check model if it has select relation in concat
505
+ await scanning(MYMODEL, result)
506
+ }
507
+ //generate views
508
+ let DIR_VIEW = `${dirRoot}/views/${table}`
509
+ if (key == 'views') {
510
+ if (!fs.existsSync(DIR_VIEW)) {
511
+ fs.mkdirSync(DIR_VIEW)
512
+ }
513
+ let compilesJS = ['createjs.ejs', 'updatejs.ejs', 'importjs.ejs']
514
+ if (!dummy) {
515
+ for (const q in filesKey) {
516
+ console.log(q)
517
+ if (Util.in_array(q, compilesJS)) {
518
+ fs.writeFileSync(`${DIR_VIEW}/${q}`, filesKey[q])
519
+ } else {
520
+ fs.writeFileSync(
521
+ `${DIR_VIEW}/${q}`,
522
+ await minify(filesKey[q], {
523
+ minifyJS: true,
524
+ minifyCSS: true,
525
+ collapseWhitespace: true,
526
+ })
527
+ )
528
+ }
529
+ console.log(`The files views of ${q} is saved!`)
530
+ }
531
+ }
532
+ }
533
+ if (!dummy) {
534
+ if (key == 'route') {
535
+ fs.writeFileSync(`${dirRoot}/routes/${filesKey.filename}`, filesKey.content)
536
+ console.log(`The files route of ${filesKey.filename} is saved!`)
537
+ }
538
+ }
539
+ }
540
+
541
+ //make a directory
542
+ if (!dummy) {
543
+ let path_script = `${dirRoot}/public/runtime/script/${table}`
544
+ Util.dirExist(path_script, true)
545
+ let path_head = `${dirRoot}/public/runtime/head/${table}`
546
+ Util.dirExist(path_head, true)
547
+ let path_end = `${dirRoot}/public/runtime/end/${table}`
548
+ Util.dirExist(path_end, true)
549
+ //we need to generate javascript code into runtime
550
+ let relations = await zRoute.relations(req, res, MYMODEL.table)
551
+ //add script
552
+ let jsObj = zRoute.generateJS(req, res, MYMODEL, relations)
553
+ //minify script
554
+ let script = uglifyJS.minify(jsObj.script)
555
+ if (script.error) {
556
+ console.log(jsObj.script)
557
+ throw script.error
558
+ }
559
+ let time = new Date().getTime()
560
+ Util.deleteAllFiles(path_script)
561
+ Util.deleteAllFiles(path_head)
562
+ Util.deleteAllFiles(path_end)
563
+ Util.writeFile(`${path_script}/${time}.js`, script.code)
564
+ Util.writeFile(`${path_head}/head.txt`, jsObj.head)
565
+ Util.writeFile(`${path_end}/end.txt`, jsObj.end)
566
+ }
567
+
568
+ //restart pm2 module in production
569
+ if (process.env.NODE_ENV == 'production') {
570
+ pm2.connect(function (err) {
571
+ if (err) {
572
+ console.log(err.toString())
573
+ }
574
+ pm2.restart(process.env.PM2_NAME, (err, proc) => {
575
+ //io.to(room).emit("message","Restart done")
576
+ })
577
+ })
578
+ }
579
+
580
+ return Util.jsonSuccess('Success')
581
+ }
582
+
583
+ router.post('/savetabs', async (req, res) => {
584
+ let body = req.body
585
+ let table = body.table
586
+ let details = body.details
587
+ let left = [],
588
+ right = [],
589
+ tabLeft = {},
590
+ tabRight = {}
591
+ let json = { status: 0, title: 'error', message: 'error', url: '' }
592
+ let obj = {}
593
+ obj.notabs = []
594
+ let labels = {}
595
+ let hasTab = false
596
+ if (nots.includes(table)) {
597
+ return res.json(Util.flashError('Table is locked'))
598
+ }
599
+
600
+ let rows = await connection.results({ table: 'zfields', where: { table: table } })
601
+ if (rows.length > 0) {
602
+ let tabsValue = rows[0].tabs + ''
603
+ if (tabsValue.length > 5) {
604
+ hasTab = true
605
+ let tabs = rows[0].tabs
606
+ for (let i = 0; i < tabs.length; i++) {
607
+ obj['arr' + i] = []
608
+ tabLeft['arr' + i] = []
609
+ tabRight['arr' + i] = []
610
+ }
611
+ }
612
+ }
613
+
614
+ for (let i = 0; i < details.length; i++) {
615
+ let name = details[i].name
616
+ let value = details[i].value
617
+ if (name.indexOf('___') > -1) {
618
+ let explode = name.split('___')
619
+ obj[explode[1]].push(explode[0])
620
+ labels[explode[0]] = value
621
+ } else {
622
+ if (name == 'LEFT') {
623
+ if (value.indexOf('___') > -1) {
624
+ var explode = value.split('___')
625
+ tabLeft[explode[1]].push(explode[0])
626
+ } else {
627
+ left.push(value)
628
+ }
629
+ } else if (name == 'RIGHT') {
630
+ if (value.indexOf('___') > -1) {
631
+ let explode = value.split('___')
632
+ tabRight[explode[1]].push(explode[0])
633
+ } else {
634
+ right.push(value)
635
+ }
636
+ } else {
637
+ obj['notabs'].push(name)
638
+ labels[name] = value
639
+ }
640
+ }
641
+ }
642
+ let post = {}
643
+ post.labels = JSON.stringify(labels)
644
+ post.details = JSON.stringify(obj)
645
+ post.left = hasTab ? JSON.stringify(tabLeft) : JSON.stringify(left)
646
+ post.right = hasTab ? JSON.stringify(tabRight) : JSON.stringify(right)
647
+ //console.log(post.left)
648
+ //console.log(JSON.stringify(post))
649
+ try {
650
+ if (rows.length > 0) {
651
+ await connection.update({ table: 'zfields', data: post, where: { id: rows[0].id } })
652
+ } else {
653
+ post.table = table
654
+ await connection.insert({ table: 'zfields', data: post })
655
+ }
656
+ json = { status: 1, title: 'Success', message: 'Success', url: '' }
657
+ } catch (error) {
658
+ json = Util.flashError(error.sqlMessage)
659
+ }
660
+
661
+ res.send(json)
662
+ })
663
+
664
+ const buildJoin = async (MYMODEL, result) => {
665
+ let joins = result.joins || {}
666
+ let table = MYMODEL.table
667
+ let table_joins = []
668
+ let join_list = []
669
+
670
+ if (result.joins && Object.keys(joins).length > 0) {
671
+ let newDataObj = {}
672
+ for (let key in joins) {
673
+ let THEIR_MODEL = require(`${dirRoot}/models/${key}`)
674
+ //console.log(THEIR_MODEL)
675
+ let arr = joins[key] || []
676
+ table_joins.push(key)
677
+ if (arr.length > 0) {
678
+ arr.map((item) => {
679
+ //console.log(item)
680
+ //console.log(typeof item)
681
+ const originKey = item.key.replace(`${key}___`, '')
682
+ console.log(originKey)
683
+ newDataObj[item.key] = item.value
684
+ MYMODEL.keys.push(item.key)
685
+ //MYMODEL.keysExcel.push(item.key)
686
+ MYMODEL.labels[item.key] = item.value
687
+ MYMODEL.fields[item.key] = THEIR_MODEL.fields[originKey]
688
+ MYMODEL.options[item.key] = THEIR_MODEL.options[originKey]
689
+ MYMODEL.grids.invisibles.push(item.key)
690
+ MYMODEL.datas[item.key] = THEIR_MODEL.datas[originKey]
691
+ MYMODEL.widgets[item.key] = THEIR_MODEL.widgets[originKey]
692
+ join_list.push(item.key)
693
+ })
694
+ }
695
+ }
696
+
697
+ let sql = []
698
+ //get all foreign key
699
+ let rows = await connection.query(connection.foreignKeyList(table))
700
+ let foreign_table_name = {}
701
+ let foreignTables = []
702
+ rows.map((row) => {
703
+ foreignTables.push(row.foreign_table_name)
704
+ foreign_table_name[row.foreign_table_name] = ` LEFT JOIN ${row.foreign_table_name} ON ${row.foreign_table_name}.id = ${table}.${row.column_name} `
705
+ })
706
+
707
+ //step by step
708
+ let table_steps = []
709
+ table_joins.map((item) => {
710
+ if (foreignTables.includes(item)) {
711
+ sql.push(foreign_table_name[item])
712
+ table_steps.push(item)
713
+ }
714
+ })
715
+
716
+ if (table_steps.length > 0) {
717
+ for (let table_steps_item of table_steps) {
718
+ let rows = await connection.query(connection.foreignKeyList(table_steps_item))
719
+ let foreign_table_name = {}
720
+ let foreignTables = []
721
+ rows.map((row) => {
722
+ foreignTables.push(row.foreign_table_name)
723
+ foreign_table_name[row.foreign_table_name] = ` LEFT JOIN ${row.foreign_table_name} ON ${row.foreign_table_name}.id = ${table_steps_item}.${row.column_name} `
724
+ })
725
+ console.log(foreignTables)
726
+ table_joins.map((item) => {
727
+ if (!table_steps.includes(item)) {
728
+ if (foreignTables.includes(item)) {
729
+ sql.push(foreign_table_name[item])
730
+ table_steps.push(item)
731
+ }
732
+ }
733
+ })
734
+ }
735
+ }
736
+
737
+ if (table_steps.length > 0) {
738
+ for (let table_steps_item of table_steps) {
739
+ let rows = await connection.query(connection.foreignKeyList(table_steps_item))
740
+ let foreign_table_name = {}
741
+ let foreignTables = []
742
+ rows.map((row) => {
743
+ foreignTables.push(row.foreign_table_name)
744
+ foreign_table_name[row.foreign_table_name] = ` LEFT JOIN ${row.foreign_table_name} ON ${row.foreign_table_name}.id = ${table_steps_item}.${row.column_name} `
745
+ })
746
+ //console.log(foreignTables)
747
+ table_joins.map((item) => {
748
+ if (!table_steps.includes(item)) {
749
+ if (foreignTables.includes(item)) {
750
+ sql.push(foreign_table_name[item])
751
+ table_steps.push(item)
752
+ }
753
+ }
754
+ })
755
+ }
756
+ }
757
+
758
+ //add join
759
+ let JOINS_DATA = {}
760
+ JOINS_DATA.tables = table_joins
761
+ JOINS_DATA.list = join_list
762
+ JOINS_DATA.data = joins
763
+ JOINS_DATA.sql = sql
764
+
765
+ MYMODEL.joins = JOINS_DATA
766
+ }
767
+ return MYMODEL
768
+ }
769
+
770
+ const columnLR = (items, dataName) => {
771
+ return `<div class="col-md-6"><ol class="mydragable divboxlittle" data-name="${dataName}">${items}</ol></div>`
772
+ }
773
+
774
+ const columnOne = (items) => {
775
+ return `<div class="row sortable"><i class="fa fa-arrows icon-float"></i><div class="col-md-12"><ol class="mydragable divboxlittle" data-name="ONE_COLUMN">${items}</ol></div></div>`
776
+ }
777
+
778
+ const reformatProperties = async (position, item, table, arr) => {
779
+ const newData = JSON.stringify(Util.arrayDelete(arr, item))
780
+ const data = {
781
+ [position]: newData,
782
+ }
783
+ await connection.update({
784
+ table: 'zfields',
785
+ data: data,
786
+ where: {
787
+ table: table,
788
+ },
789
+ })
790
+ }
791
+
792
+ router.delete('/delete-table', csrfProtection, async (req, res) => {
793
+ let table = req.body.table
794
+ let json = Util.jsonSuccess('Successfully delete module')
795
+ if (Util.in_array(table, nots)) {
796
+ return res.json(Util.flashError('Can not be deleted!'))
797
+ }
798
+ if (nots.includes(table)) {
799
+ return res.json(Util.flashError('Table is locked'))
800
+ }
801
+ try {
802
+ await connection.delete({
803
+ table: 'zfields',
804
+ where: {
805
+ table: table,
806
+ },
807
+ })
808
+ //await connection.query("DELETE FROM zfields WHERE `table` = ?", [table]);
809
+ await connection.query(`DROP table "${table}";`)
810
+ //delete file
811
+ let modelFile = dirRoot + '/models/' + table + '.js'
812
+ fs.stat(modelFile, function (err, stats) {
813
+ console.log(stats) //here we got all information of file in stats variable
814
+ if (err) {
815
+ return console.error(err)
816
+ } else {
817
+ fs.unlink(modelFile, function (err) {
818
+ if (err) return console.log(err)
819
+ console.log('file deleted successfully')
820
+ })
821
+ }
822
+ })
823
+
824
+ let routesFile = dirRoot + '/routes/' + table + '.js'
825
+ fs.stat(routesFile, function (err, stats) {
826
+ console.log(stats) //here we got all information of file in stats variable
827
+ if (err) {
828
+ return console.error(err)
829
+ } else {
830
+ fs.unlink(routesFile, function (err) {
831
+ if (err) return console.log(err)
832
+ console.log('file deleted successfully')
833
+ })
834
+ }
835
+ })
836
+
837
+ let runtimeFile = dirRoot + '/public/runtime/script/' + table
838
+ fs.rm(
839
+ runtimeFile,
840
+ {
841
+ recursive: true,
842
+ },
843
+ (error) => {
844
+ if (error) {
845
+ console.log(error)
846
+ } else {
847
+ console.log('Recursive: Directories Deleted!')
848
+ }
849
+ }
850
+ )
851
+ let runtimeFileHead = dirRoot + '/public/runtime/head/' + table
852
+ fs.rm(
853
+ runtimeFileHead,
854
+ {
855
+ recursive: true,
856
+ },
857
+ (error) => {
858
+ if (error) {
859
+ console.log(error)
860
+ } else {
861
+ console.log('Recursive: Directories Deleted!')
862
+ }
863
+ }
864
+ )
865
+ let runtimeFileEnd = dirRoot + '/public/runtime/end/' + table
866
+ fs.rm(
867
+ runtimeFileEnd,
868
+ {
869
+ recursive: true,
870
+ },
871
+ (error) => {
872
+ if (error) {
873
+ console.log(error)
874
+ } else {
875
+ console.log('Recursive: Directories Deleted!')
876
+ }
877
+ }
878
+ )
879
+
880
+ await connection.delete({
881
+ table: 'zgrid',
882
+ where: { route_name: table },
883
+ })
884
+ if (table) {
885
+ const viewsFile = dirRoot + '/views/' + table
886
+ fs.rm(
887
+ viewsFile,
888
+ {
889
+ recursive: true,
890
+ },
891
+ (error) => {
892
+ if (error) {
893
+ console.log(error)
894
+ } else {
895
+ console.log('Recursive: Directories Deleted!')
896
+ }
897
+ }
898
+ )
899
+ }
900
+ await connection.delete({
901
+ table: 'zgrid_default',
902
+ where: { table: table },
903
+ })
904
+ } catch (e) {
905
+ json = Util.flashError(e.toString(), '')
906
+ }
907
+
908
+ res.json(json)
909
+ })
910
+
911
+ router.post('/add_field', csrfProtection, async (req, res) => {
912
+ try {
913
+ const body = req.body
914
+ console.log(JSON.stringify(body))
915
+ const table = body.table
916
+ if (nots.includes(table)) {
917
+ return res.json(Util.flashError('Table is locked'))
918
+ }
919
+ body.zFields = await connection.results({ table: 'zfields', where: { table: table } })
920
+ const results = await axios.post(`${generatorUrl}/api/generator/create_field`, body)
921
+ const datas = results.data
922
+ if (datas.status == 1) {
923
+ await connection.update({ table: 'zfields', where: { table: table }, data: datas.post })
924
+ }
925
+ res.json(datas)
926
+ } catch (e) {
927
+ res.json(Util.flashError(e.toString()))
928
+ }
929
+ })
930
+
931
+ router.post('/add_container', async (req, res) => {
932
+ let others = req.body.others
933
+ let table = req.body.table
934
+ //console.log(JSON.stringify(req.body))
935
+ try {
936
+ if (others && table) {
937
+ await connection.update({
938
+ table: 'zfields',
939
+ data: {
940
+ others: others,
941
+ },
942
+ where: {
943
+ table: table,
944
+ },
945
+ })
946
+ }
947
+ } catch (e) {
948
+ return res.json(Util.flashError(e.toString()))
949
+ }
950
+
951
+ res.json(Util.jsonSuccess('Success'))
952
+ })
953
+
954
+ router.post('/setting_field', csrfProtection, async (req, res) => {
955
+ if (nots.includes(req.body.table)) {
956
+ return res.json(Util.flashError('Table is locked'))
957
+ }
958
+ const body = req.body
959
+ const table = body.table
960
+ const html = ''
961
+ body.result = await connection.result({ table: 'zfields', where: { table: table } })
962
+ const results = await axios.post(`${generatorUrl}/api/generator/modal_settings`, body)
963
+ const datas = results.data
964
+ res.json(datas.html)
965
+ })
966
+
967
+ router.post('/save_setting', async (req, res) => {
968
+ const html = '',
969
+ table = req.query.table || ''
970
+ let json = Util.jsonSuccess('Success to update')
971
+ try {
972
+ if (nots.includes(req.body.table)) {
973
+ return res.json(Util.flashError('Table is locked'))
974
+ }
975
+ const post = req.body
976
+ let data = await connection.result({
977
+ table: 'zfields',
978
+ where: { table: table },
979
+ })
980
+ let properties = data.properties ? data.properties : {}
981
+ let propertyKey = ''
982
+ for (var key in post) {
983
+ propertyKey = key
984
+ }
985
+
986
+ properties[propertyKey].values = post[propertyKey]
987
+ let insert = {
988
+ properties: JSON.stringify(properties),
989
+ }
990
+ await connection.update({
991
+ table: 'zfields',
992
+ data: insert,
993
+ where: { table: table },
994
+ })
995
+ } catch (e) {
996
+ json = Util.flashError(e.toString())
997
+ }
998
+
999
+ res.json(json)
1000
+ })
1001
+
1002
+ router.delete('/delete_field', csrfProtection, async (req, res) => {
1003
+ let json = Util.jsonSuccess('Success to update')
1004
+ try {
1005
+ if (nots.includes(req.body.table)) {
1006
+ return res.json(Util.flashError('Table is locked'))
1007
+ }
1008
+ const table = req.body.table,
1009
+ name = req.body.name
1010
+ let data = await connection.result({
1011
+ table: 'zfields',
1012
+ where: { table: table },
1013
+ })
1014
+ let properties = data.properties ? data.properties : {}
1015
+ delete properties[name]
1016
+ let labels = data.labels ? data.labels : {}
1017
+ delete labels[name]
1018
+
1019
+ let left = data.left ? data.left : []
1020
+ left = Util.arrayDelete(left, name)
1021
+ let right = data.right ? data.right : []
1022
+ right = Util.arrayDelete(right, name)
1023
+ let oneColumn = data.one_column ? data.one_column : []
1024
+ oneColumn = Util.arrayDelete(oneColumn, name)
1025
+ let details = data.details ? data.details : {}
1026
+ let detailsTemp = {}
1027
+ for (var keys in details) {
1028
+ detailsTemp[keys] = Util.arrayDelete(details[keys], name)
1029
+ }
1030
+ let newProperty = {}
1031
+ newProperty.properties = JSON.stringify(properties)
1032
+ newProperty.labels = JSON.stringify(labels)
1033
+ newProperty.left = JSON.stringify(left)
1034
+ newProperty.right = JSON.stringify(right)
1035
+ newProperty.one_column = JSON.stringify(oneColumn)
1036
+ newProperty.details = JSON.stringify(detailsTemp)
1037
+ newProperty.sorting = JSON.stringify(data.sorting)
1038
+ await connection.update({
1039
+ table: 'zfields',
1040
+ data: newProperty,
1041
+ where: { table: table },
1042
+ })
1043
+ //DROP COULUMN
1044
+ //ALTER TABLE table_name DROP COLUMN IF EXISTS column_name;
1045
+ await connection.query(`ALTER TABLE "${table}" DROP COLUMN IF EXISTS "${name}";`)
1046
+ } catch (err) {
1047
+ json = Util.flashError(err.toString())
1048
+ console.log(err)
1049
+ console.log('ada error di update zfields')
1050
+ }
1051
+ res.json(json)
1052
+ })
1053
+
1054
+ router.post('/tab_rename', csrfProtection, async (req, res) => {
1055
+ const html = '',
1056
+ table = req.body.table || '',
1057
+ name = req.body.name || '',
1058
+ id = req.body.id || 0
1059
+ let json = Util.jsonSuccess('Success to rename')
1060
+ try {
1061
+ if (table == '') {
1062
+ return res.json(Util.flashError('table empty'))
1063
+ }
1064
+ if (name == '') {
1065
+ return res.json(Util.flashError('name empty'))
1066
+ }
1067
+ let data = await connection.result({
1068
+ table: 'zfields',
1069
+ where: { table: table },
1070
+ })
1071
+ const tabs = data.tabs || []
1072
+ let arr = []
1073
+ tabs.forEach(function (item, index) {
1074
+ if (index == id) {
1075
+ arr.push(name)
1076
+ } else {
1077
+ arr.push(item)
1078
+ }
1079
+ })
1080
+ let post = {
1081
+ tabs: JSON.stringify(arr),
1082
+ }
1083
+ await connection.update({
1084
+ table: 'zfields',
1085
+ data: post,
1086
+ where: {
1087
+ table: table,
1088
+ },
1089
+ })
1090
+ } catch (e) {
1091
+ json = Util.flashError(e.toString())
1092
+ }
1093
+ res.json(json)
1094
+ })
1095
+
1096
+ const zfields = async () => {
1097
+ return await connection.results({
1098
+ select: `id, "table", "name", "route",tabs,labels, details, "left","right",one_column, sorting, properties,others,json`,
1099
+ table: 'zfields',
1100
+ orderBy: ['table', 'asc'],
1101
+ })
1102
+ }
1103
+
1104
+ const zfieldsKeys = async () => {
1105
+ return Util.arrayToObject(await zfields(), 'table')
1106
+ }
1107
+
1108
+ router.post('/load-form', async (req, res) => {
1109
+ const table = req.body.table
1110
+ let json = Util.flashError('error')
1111
+ const result = await connection.result({
1112
+ table: 'zfields',
1113
+ where: {
1114
+ table: table,
1115
+ },
1116
+ })
1117
+ if (result.id) {
1118
+ json = Util.jsonSuccess('success')
1119
+ json.data = result
1120
+ }
1121
+ res.json(json)
1122
+ })
1123
+
1124
+ //save to table zfields
1125
+ var saveToZFields = async (body) => {
1126
+ const table = body.table
1127
+ let is_approval = body.is_approval
1128
+ if (typeof body.is_approval == 'string') {
1129
+ if (body.is_approval == 'false') {
1130
+ is_approval = 0
1131
+ } else if (body.is_approval == 'true') {
1132
+ is_approval = 1
1133
+ }
1134
+ }
1135
+
1136
+ const zapprovals = {}
1137
+ zapprovals.title = body.approval_title
1138
+ zapprovals.type = body.type
1139
+ zapprovals.approvers = body.approvers
1140
+ zapprovals.knowings = body.knowings
1141
+ zapprovals.content = body.template
1142
+ var data = {
1143
+ index_ejs: body.index_ejs,
1144
+ indexcss_ejs: body.indexcss_ejs,
1145
+ indexjs_ejs: body.indexjs_ejs,
1146
+ form_ejs: body.form_ejs,
1147
+ create_ejs: body.create_ejs,
1148
+ createjs_ejs: body.createjs_ejs,
1149
+ update_ejs: body.update_ejs,
1150
+ updatejs_ejs: body.updatejs_ejs,
1151
+ import_ejs: body.import_ejs,
1152
+ importjs_ejs: body.importjs_ejs,
1153
+ view_ejs: body.view_ejs,
1154
+ is_approval: is_approval || 0,
1155
+ approval_json: JSON.stringify(zapprovals),
1156
+ others: body.others,
1157
+ }
1158
+
1159
+ let joinsTables = {}
1160
+ let bodyJoins = body.joins || []
1161
+ let bodyJoinsObj = {}
1162
+ if (bodyJoins.length > 0) {
1163
+ bodyJoins.map((item) => {
1164
+ bodyJoinsObj[item.name] = item.value
1165
+ })
1166
+ }
1167
+ for (let key in bodyJoinsObj) {
1168
+ if (key.includes('joins_checks___')) {
1169
+ let tablekeys = key.split('___')
1170
+ let keyName = key.replace('joins_checks___', '')
1171
+ if (!joinsTables[tablekeys[1]]) {
1172
+ joinsTables[tablekeys[1]] = []
1173
+ }
1174
+ joinsTables[tablekeys[1]].push({ key: keyName, value: bodyJoinsObj[`joins_labels___${keyName}`] })
1175
+ }
1176
+ }
1177
+ //console.log(joinsTables);
1178
+ if (Object.keys(joinsTables).length > 0) {
1179
+ data.joins = JSON.stringify(joinsTables)
1180
+ }
1181
+
1182
+ let result = await connection.update({
1183
+ table: 'zfields',
1184
+ data: data,
1185
+ where: {
1186
+ table: table,
1187
+ },
1188
+ })
1189
+
1190
+ return result
1191
+ }
1192
+
1193
+ //drop down chains effect
1194
+ const chainings = async (table, arr) => {
1195
+ const results = await connection.query(connection.showFields(table))
1196
+ const obj = {}
1197
+ const tableObj = {}
1198
+ for (let i = 0; i < results.length; i++) {
1199
+ const result = results[i]
1200
+ if (Util.in_array(result.COLUMN_NAME, arr)) {
1201
+ obj[result.COLUMN_NAME] = {
1202
+ table: result.REFERENCED_TABLE_NAME,
1203
+ }
1204
+ tableObj[result.REFERENCED_TABLE_NAME] = result.COLUMN_NAME
1205
+ }
1206
+ }
1207
+
1208
+ for (const key in obj) {
1209
+ const rows = await connection.query(connection.showFields(obj[key].table))
1210
+ rows.forEach(function (row) {
1211
+ for (var q in obj) {
1212
+ if (row.REFERENCED_TABLE_NAME == obj[q].table) {
1213
+ if (!obj[q].chains) {
1214
+ obj[q].chains = {}
1215
+ }
1216
+ obj[q].chains[key] = {
1217
+ column: row.COLUMN_NAME,
1218
+ table: row.TABLE_NAME,
1219
+ }
1220
+ }
1221
+ }
1222
+ })
1223
+ }
1224
+ return obj
1225
+ }
1226
+
1227
+ router.post('/sorting', async (req, res) => {
1228
+ let sorting = req.body.sorting
1229
+ let table = req.body.table
1230
+ await connection.update({
1231
+ table: 'zfields',
1232
+ data: {
1233
+ sorting: sorting,
1234
+ },
1235
+ where: { table: table },
1236
+ })
1237
+ res.send('OK')
1238
+ })
1239
+
1240
+ router.post('/export', async (req, res) => {
1241
+ const table = req.body.table
1242
+ let json = Util.jsonSuccess('file Complete')
1243
+ if (table) {
1244
+ const result = await connection.result({
1245
+ table: 'zfields',
1246
+ where: {
1247
+ table: table,
1248
+ },
1249
+ })
1250
+ const dir = `${dirRoot}/public/uploads/zgenerator`
1251
+ if (!fs.existsSync(dir)) {
1252
+ fs.mkdirSync(dir)
1253
+ }
1254
+ const text = JSON.stringify(result)
1255
+ fs.writeFileSync(`${dir}/${table}.json`, text)
1256
+ } else {
1257
+ json = Util.flashError('no table selected')
1258
+ }
1259
+ res.json(json)
1260
+ })
1261
+
1262
+ router.post('/import', async (req, res) => {
1263
+ let json = Util.flashError('Error File')
1264
+ let table = ''
1265
+ try {
1266
+ let isEmptyFiles = Util.isEmptyObject(req.files)
1267
+ if (!isEmptyFiles) {
1268
+ const file = req.files['import-file']
1269
+ const name = file.name
1270
+ const mime = file.mimetype
1271
+ if (mime == 'application/json') {
1272
+ const string = file.data.toString('utf8')
1273
+ const jsonFile = JSON.parse(string)
1274
+ table = jsonFile.table
1275
+ delete jsonFile.id
1276
+ const data = {}
1277
+ for (const key in jsonFile) {
1278
+ let value = jsonFile[key]
1279
+ if (typeof value == 'object') {
1280
+ value = JSON.stringify(value)
1281
+ }
1282
+ data[key] = value
1283
+ }
1284
+ if (!data.tabs) {
1285
+ data.tabs = '[]'
1286
+ }
1287
+ data.company_id = 1
1288
+ data.created_by = res.locals.userId || 1
1289
+ data.updated_by = res.locals.userId || 1
1290
+ data.created_at = Util.now()
1291
+ data.updated_at = Util.now()
1292
+ data.is_approval = data.is_approval == 'null' ? 0 : data.is_approval
1293
+ delete data.approval_history
1294
+ const results = await connection.results({
1295
+ table: 'zfields',
1296
+ where: {
1297
+ table: table,
1298
+ },
1299
+ })
1300
+ if (results.length) {
1301
+ await connection.update({
1302
+ table: 'zfields',
1303
+ data: data,
1304
+ where: {
1305
+ table: table,
1306
+ },
1307
+ })
1308
+ } else {
1309
+ await connection.insert({
1310
+ table: 'zfields',
1311
+ data: data,
1312
+ })
1313
+ }
1314
+ json = Util.jsonSuccess('Success to add module, please generate tax to make a file')
1315
+ }
1316
+ }
1317
+ } catch (e) {
1318
+ console.log(e)
1319
+ json.message = e.toString()
1320
+ }
1321
+ json.table = table
1322
+ res.json(json)
1323
+ })
1324
+
1325
+ /*
1326
+ Scanning relation id to name
1327
+ */
1328
+ const scanning = async (MYMODEL, result) => {
1329
+ //let MYMODEL = require(`${dirRoot}/models/${table}`);
1330
+ let table = MYMODEL.table
1331
+ const widgets = MYMODEL.widgets
1332
+ const not_scanning = ['created_by', 'updated_by']
1333
+ const concat_bracket = /(?<=\().+?(?=\))/g
1334
+ let changeWidgets = {}
1335
+ let changes = []
1336
+ /*for (let key in widgets) {
1337
+ if (widgets[key].name == 'relation' || widgets[key].name == 'dropdown_multi' || widgets[key].name == 'typeahead') {
1338
+ if (!Util.in_array(key, not_scanning)) {
1339
+ let fields = widgets[key].fields
1340
+ //let concat = fields[1].indexOf('CONCAT(') > -1 ? fields[1].substring()
1341
+ let arr = fields[1].match(concat_bracket) || []
1342
+ if (arr.length) {
1343
+ let str = Util.replaceAll(arr[0], '"', '')
1344
+ let mysplits = str.indexOf(',') > -1 ? str.split(',') : [str]
1345
+ let MYMODEL_TABLE = require(`${dirRoot}/models/${widgets[key].table}`)
1346
+ let widgetsRelations = MYMODEL_TABLE.widgets
1347
+ let relationsKeys = []
1348
+ let relationsKeysObject = {}
1349
+ for (let k in widgetsRelations) {
1350
+ if (widgetsRelations[k].name == 'relation') {
1351
+ if (!Util.in_array(k, not_scanning)) {
1352
+ relationsKeys.push(k)
1353
+ relationsKeysObject[k] = `(SELECT ${widgetsRelations[k].fields[1]} FROM ${widgetsRelations[k].table} where id = `
1354
+ }
1355
+ }
1356
+ }
1357
+ let myarr = []
1358
+ mysplits.forEach(function (item) {
1359
+ if (Util.in_array(item, relationsKeys)) {
1360
+ changes.push(key)
1361
+ myarr.push(relationsKeysObject[item] + ` ${item} )`)
1362
+ } else {
1363
+ myarr.push(item)
1364
+ }
1365
+ })
1366
+ let myjoin = `CONCAT(${myarr.join(',')})`
1367
+ widgets[key].fields = ['id', myjoin]
1368
+ }
1369
+ }
1370
+ }
1371
+ }*/
1372
+
1373
+ if (changes.length) {
1374
+ //rewrite model
1375
+ MYMODEL.widgets = widgets
1376
+ let newModel = `module.exports = { ${Util.newLine}`
1377
+ newModel += zRoute.buildFileModel(MYMODEL)
1378
+ newModel += `${Util.newLine}`
1379
+ newModel += `}`
1380
+ fs.writeFileSync(`${dirRoot}/models/${MYMODEL.table}.js`, newModel)
1381
+ }
1382
+
1383
+ //check if has join
1384
+ //build join
1385
+ //console.log(JSON.stringify(MYMODEL))
1386
+ MYMODEL = await buildJoin(MYMODEL, result)
1387
+ //console.log(JSON.stringify(MYMODEL))
1388
+
1389
+ let newModel = `module.exports = { ${Util.newLine}`
1390
+ newModel += zRoute.buildFileModel(MYMODEL)
1391
+ newModel += `${Util.newLine}`
1392
+ newModel += `}`
1393
+ fs.writeFileSync(`${dirRoot}/models/${MYMODEL.table}.js`, newModel)
1394
+ //return MYMODEL;
1395
+ }
1396
+
1397
+ //generate all css/js assets
1398
+ router.post('/generate-assets', async (req, res) => {
1399
+ let notifObj = Util.jsonSuccess('Success, generate all assets')
1400
+ try {
1401
+ let MYMODELS = zRoute.MYMODELS()
1402
+ delete MYMODELS.zrole
1403
+ for (let key in MYMODELS) {
1404
+ let MYMODEL = MYMODELS[key]
1405
+ let table = MYMODEL.table
1406
+ let path_script = `${dirRoot}/public/runtime/script/${table}`
1407
+ Util.dirExist(path_script, true)
1408
+ let path_head = `${dirRoot}/public/runtime/head/${table}`
1409
+ Util.dirExist(path_head, true)
1410
+ let path_end = `${dirRoot}/public/runtime/end/${table}`
1411
+ Util.dirExist(path_end, true)
1412
+ //we need to generate javascript code into runtime
1413
+ let relations = await zRoute.relations(req, res, MYMODEL.table)
1414
+ //add script
1415
+ let jsObj = zRoute.generateJS(req, res, MYMODEL, relations)
1416
+ let time = new Date().getTime()
1417
+ Util.deleteAllFiles(path_head)
1418
+ Util.deleteAllFiles(path_end)
1419
+ Util.deleteAllFiles(path_script)
1420
+
1421
+ //minify script
1422
+ let script = uglifyJS.minify(jsObj.script)
1423
+ if (script.error) throw script.error
1424
+ Util.writeFile(`${path_script}/${time}.js`, script.code)
1425
+ Util.writeFile(`${path_head}/head.txt`, jsObj.head)
1426
+ Util.writeFile(`${path_end}/end.txt`, jsObj.end)
1427
+ }
1428
+ } catch (e) {
1429
+ notifObj = Util.flashError(e.toString())
1430
+ }
1431
+ res.json(notifObj)
1432
+ })
1433
+
1434
+ router.post('/minify', async (req, res) => {
1435
+ let notifyObj = Util.jsonSuccess('Success to cached')
1436
+ try {
1437
+ notifyObj = await viewsMini()
1438
+ } catch (e) {
1439
+ console.log(e)
1440
+ notifyObj = Util.flashError(e.toString())
1441
+ }
1442
+ res.json(notifyObj)
1443
+ })
1444
+
1445
+ const viewsMini = async () => {
1446
+ let notifyObj = Util.jsonSuccess('Success')
1447
+ const viewDir = `${dirRoot}/views`
1448
+ const layoutsDir = `${dirRoot}/views/layouts`
1449
+ let item
1450
+ try {
1451
+ let views = Util.getAllFiles(viewDir)
1452
+ let options = {
1453
+ minifyJS: true,
1454
+ minifyCSS: true,
1455
+ collapseWhitespace: true,
1456
+ }
1457
+ const notViewDir = ['zgenerator', 'layouts', 'index', 'zindex']
1458
+ for (const dir of views) {
1459
+ console.log('dir :', dir)
1460
+ if (!Util.in_array(dir, notViewDir)) {
1461
+ let files = Util.getAllFiles(`${viewDir}/${dir}`)
1462
+ //console.log(files);
1463
+ for (item of files) {
1464
+ if (item.includes('.ejs')) {
1465
+ let filename = `${viewDir}/${dir}/${item}`
1466
+ let content = Util.readFile(filename)
1467
+ let contentChange = await minify(content, options)
1468
+ fs.writeFileSync(filename, contentChange)
1469
+ }
1470
+ }
1471
+ }
1472
+ }
1473
+
1474
+ let layouts = Util.getAllFiles(layoutsDir)
1475
+ for (item of layouts) {
1476
+ if (item.includes('.ejs')) {
1477
+ let filename = `${layoutsDir}//${item}`
1478
+ let content = Util.readFile(filename)
1479
+ let contentChange = await minify(content, options)
1480
+ fs.writeFileSync(filename, contentChange)
1481
+ }
1482
+ }
1483
+ } catch (e) {
1484
+ notifyObj = Util.flashError(`error in item : ${item} , error str :${e.toString()}`)
1485
+ }
1486
+ return notifyObj
1487
+ }
1488
+
1489
+ router.post('/load-joins', async (req, res) => {
1490
+ let jsonNotif = Util.jsonSuccess('Success')
1491
+ let html = ''
1492
+ try {
1493
+ let body = req.body
1494
+ console.log(body)
1495
+ let table = body.table
1496
+ html = await loadJoins(table)
1497
+ jsonNotif.html = html
1498
+ } catch (e) {
1499
+ console.log(e)
1500
+ }
1501
+ res.json(jsonNotif)
1502
+ })
1503
+
1504
+ router.post('/remove-joins', async (req, res) => {
1505
+ let jsonNotif = Util.jsonSuccess('Success')
1506
+ let html = ''
1507
+ try {
1508
+ let body = req.body
1509
+ console.log(body)
1510
+ let table = body.table
1511
+ let table_join = body.table_join
1512
+ let result = await connection.result({
1513
+ table: 'zfields',
1514
+ where: {
1515
+ table: table,
1516
+ },
1517
+ })
1518
+ let resultJoins = result.joins || {}
1519
+ delete resultJoins[table_join]
1520
+ await connection.update({
1521
+ table: 'zfields',
1522
+ data: {
1523
+ joins: JSON.stringify(resultJoins),
1524
+ },
1525
+ where: {
1526
+ table: table,
1527
+ },
1528
+ })
1529
+ } catch (e) {
1530
+ console.log(e)
1531
+ }
1532
+ res.json(jsonNotif)
1533
+ })
1534
+
1535
+ router.post('/joins', async (req, res) => {
1536
+ let jsonNotif = Util.jsonSuccess('Success')
1537
+ let html = ''
1538
+ try {
1539
+ let body = req.body
1540
+ console.log(body)
1541
+ let table = body.table
1542
+ let table_join = body.table_join
1543
+ let result = await connection.result({
1544
+ table: 'zfields',
1545
+ where: {
1546
+ table: table,
1547
+ },
1548
+ })
1549
+ let resultJoins = result.joins || {}
1550
+ resultJoins[table_join] = []
1551
+ let myzfield = await connection.update({
1552
+ table: 'zfields',
1553
+ data: {
1554
+ joins: JSON.stringify(resultJoins),
1555
+ },
1556
+ where: {
1557
+ table: table,
1558
+ },
1559
+ })
1560
+ jsonNotif.json = resultJoins
1561
+ html = await joinHTML(resultJoins, myzfield)
1562
+ } catch (e) {
1563
+ console.log(e)
1564
+ jsonNotif = Util.flashError(e + '')
1565
+ }
1566
+ jsonNotif.html = html
1567
+ res.json(jsonNotif)
1568
+ })
1569
+
1570
+ async function loadJoins(table) {
1571
+ let html = ''
1572
+ try {
1573
+ /* let sql = `select ${table}.* from ${table} `;
1574
+ console.log(sql)*/
1575
+ let result = await connection.result({
1576
+ table: 'zfields',
1577
+ where: {
1578
+ table: table,
1579
+ },
1580
+ })
1581
+ let joinsObj = result.joins || {}
1582
+ html = await joinHTML(joinsObj, result)
1583
+ } catch (e) {
1584
+ console.log(e)
1585
+ html = e + ''
1586
+ }
1587
+ return html
1588
+ }
1589
+
1590
+ async function joinHTML(json, myzfield) {
1591
+ let html = ``
1592
+ try {
1593
+ let zfields = await connection.results({
1594
+ table: 'zfields',
1595
+ })
1596
+ let zfieldsObj = Util.arrayToObject(zfields, 'table')
1597
+ for (let key in json) {
1598
+ html += `<div class="joinContainer col-md-4">`
1599
+ html += `<h5>${zfieldsObj[key].name} <button type="button" class="btn btn-danger" onclick="removeJoins('${key}')"><i class="fa fa-trash "></i> </button></h5>`
1600
+ html += fieldHTML(zfieldsObj[key], myzfield)
1601
+ html += `</div>`
1602
+ }
1603
+ } catch (e) {
1604
+ html = e + ''
1605
+ }
1606
+ return html
1607
+ }
1608
+
1609
+ function fieldHTML(obj, myzfield) {
1610
+ let html = ``
1611
+ try {
1612
+ let labels = obj.labels
1613
+ let table = obj.table
1614
+ let myzfieldJoins = myzfield.joins || {}
1615
+ for (let key in labels) {
1616
+ let mylabel = labels[key]
1617
+ let selected = ''
1618
+ if (myzfieldJoins[table]) {
1619
+ let arr = myzfieldJoins[table] || []
1620
+ arr.map((item) => {
1621
+ if (item.key == `${table}___${key}`) {
1622
+ selected = ` checked `
1623
+ mylabel = item.value
1624
+ }
1625
+ })
1626
+ }
1627
+ html += `<div class="input-group">
1628
+ <div class="input-group-prepend">
1629
+ <span class="input-group-text"><input type="checkbox" ${selected} name="joins_checks___${table}___${key}"></span>
1630
+ <span class="input-group-text">${key}</span>
1631
+ <input type="text" class="form-control" name="joins_labels___${table}___${key}" id="joins___${table}___${key}" value="${mylabel}">
1632
+ </div>
1633
+ </div>`
1634
+ }
1635
+ } catch (e) {
1636
+ html = e + ''
1637
+ }
1638
+ return html
1639
+ }
1640
+
1641
+ module.exports = router