zet-lib 1.0.22 → 1.0.24

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.
@@ -0,0 +1,1249 @@
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
+
15
+ const nots = ['index','uploads','js','css','log','generator','zmenu','zgenerator','zfields','zrole','zfunction','zgrid','zgrid_default', 'zuser','zreport','zpage','zlayout','zerror','zuser_company','zconfig'];
16
+ const nots = [];
17
+ const generatorUrl = 'https://appmaker.monster';
18
+ //const generatorUrl = 'http://localhost:3000';
19
+
20
+ router.get('/', csrfProtection, async (req, res) => {
21
+ let table = req.query.table || "", route = "", jsonData = {}, zForms = {}, relations = {},
22
+ approvalDatas = {is_approval: false};
23
+ let datas = await axios.post(`${generatorUrl}/api/generator/index`, {
24
+ results: await zfields(),
25
+ fields: await connection.query(connection.showFullFields(table)),
26
+ table: table
27
+ });
28
+ const MYMODELS = myCache.get('MYMODELS');
29
+ zForms.obj = {};
30
+ jsonData = datas.data;
31
+ let sorting = "";
32
+ if (table) {
33
+ let contentScript = `var ZFIELDS = ${JSON.stringify(jsonData.rows, null, 2)};`
34
+ moduleLib.addScript(req, res, contentScript);
35
+ moduleLib.editor(req, res);
36
+ let MYMODEL_APPROVERS = MYMODELS['zapprovals'];
37
+ let zfieldData = await connection.result({
38
+ table: "zfields",
39
+ where: {
40
+ table: table
41
+ }
42
+ });
43
+ sorting = JSON.stringify(zfieldData.sorting);
44
+ approvalDatas = MYMODEL_APPROVERS.datas;
45
+ if (zfieldData) {
46
+ let approvalJSON = zfieldData.approval_json || {};
47
+ approvalDatas.is_approval = zfieldData.is_approval || false;
48
+ approvalDatas.title = approvalJSON.title || "";
49
+ approvalDatas.type = approvalJSON.type || 1;
50
+ approvalDatas.approvers = approvalJSON.approvers ? approvalJSON.approvers : [];
51
+ approvalDatas.knowings = approvalJSON.knowings || [];
52
+ approvalDatas.template = approvalJSON.content || "";
53
+ zForms = await zRoute.formsFieldSync(req, res, MYMODEL_APPROVERS, approvalDatas);
54
+ }
55
+ }
56
+
57
+ const jsonDatas = jsonData.datas;
58
+ const lock = nots.includes(table) ? 1 : 0;
59
+ const jsonDatasJson = jsonDatas.hasOwnProperty('json') && jsonDatas.json ? jsonDatas.json : {};
60
+ const checkDummy = Object.prototype.hasOwnProperty.call(jsonDatasJson, 'dummy') && jsonDatasJson.dummy ? 'checked' : '';
61
+ const renderData = {
62
+ datas: jsonDatas,
63
+ table: table,
64
+ rows: jsonData.rows,
65
+ checkDummy: checkDummy,
66
+ csrfToken: req.csrfToken(),
67
+ route: jsonData.route,
68
+ selects: jsonData.selects,
69
+ zForms: zForms,
70
+ relations: relations,
71
+ approvalDatas: approvalDatas,
72
+ sorting: sorting,
73
+ lock: lock,
74
+ routeName:res.locals.routeName,
75
+ bodyHTML : Util.readFile(`./views/generator.ejs`),
76
+ endHTML : Util.readFile(`./views/generatorjs.ejs`)
77
+ //renderBody: "zgenerator/index.ejs",
78
+ //renderEnd: "zgenerator/indexjs.ejs"
79
+ };
80
+ let dataRender = zRoute.renderHTML(renderData);
81
+
82
+ res.render('layout/generator',dataRender);
83
+ });
84
+
85
+ router.post('/fields', async (req, res) => {
86
+ try {
87
+ let body = req.body;
88
+ let table = body.table || "";
89
+ let result = {}, fields = {}, rowsFields = [];
90
+ if (table) {
91
+ result = await connection.result({table: 'zfields', where: {table: table}});
92
+ fields = await connection.query(connection.showFullFields(table));
93
+ rowsFields = await connection.query(connection.describeTable(table))
94
+ }
95
+ let objData = {
96
+ result: result,
97
+ fields: fields,
98
+ rowsFields: rowsFields,
99
+ table: table
100
+ };
101
+ let datas = await axios.post(`${generatorUrl}/api/generator/modal`, objData);
102
+ res.json(datas.data)
103
+ } catch (e) {
104
+ console.log(e);
105
+ res.json(e.toString())
106
+ }
107
+ });
108
+
109
+ /*
110
+ Create new Module/Table
111
+ */
112
+ router.post("/", csrfProtection, async (req, res) => {
113
+ try {
114
+ let results = await axios.post(`${generatorUrl}/api/generator/create`, req.body);
115
+ let datas = results.data;
116
+ if (datas.status == 0) {
117
+ res.json(datas)
118
+ } else {
119
+ if (nots.includes(datas.post.table)) {
120
+ return res.json(Util.flashError("Table is locked"));
121
+ }
122
+ await connection.insert({
123
+ table: "zfields",
124
+ data: datas.post
125
+ });
126
+ await connection.query(datas.sql);
127
+ res.json(datas);
128
+ }
129
+ } catch (err) {
130
+ res.json(Util.flashError(err.toString()));
131
+ }
132
+ });
133
+
134
+ router.post("/reset", async (req, res) => {
135
+ try {
136
+ let json = Util.jsonSuccess("Reset Success");
137
+ let table = req.body.table;
138
+ if (nots.includes(table)) {
139
+ return res.json(Util.flashError("Table is locked"));
140
+ }
141
+ if (table) {
142
+ let results = await axios.post(`${generatorUrl}/api/generator/reset`, req.body);
143
+ let datas = results.data;
144
+ await connection.update({
145
+ table: "zfields",
146
+ data: datas,
147
+ where: {
148
+ table: table
149
+ }
150
+ });
151
+ } else {
152
+ json = Util.flashError("error");
153
+ }
154
+ res.json(json)
155
+ } catch (e) {
156
+ console.log(e.toString())
157
+ json = Util.flashError("error");
158
+ res.json(json)
159
+ }
160
+ });
161
+
162
+ router.post('/tabs', async (req, res) => {
163
+ let json = {status: 0, title: 'error', url: ''}
164
+ let body = req.body;
165
+ let table = body.table || "";
166
+ let title = body.title || "";
167
+ let tabs = body.tabs || [];
168
+ if (table == "") {
169
+ json.title = "table is empty";
170
+ return res.send(json)
171
+ }
172
+ if (title == "") {
173
+ json.title = "title is empty";
174
+ return res.send(json)
175
+ }
176
+ if (nots.includes(table)) {
177
+ return res.json(Util.flashError("Table is locked"));
178
+ }
179
+ let post = {};
180
+ post.table = table;
181
+ post.tabs = JSON.stringify(tabs);
182
+ post.name = title;
183
+ if (body.hasOwnProperty('json')) {
184
+ post.json = JSON.stringify(body.json);
185
+ } else {
186
+ post.json = JSON.stringify({dummy: 0});
187
+ }
188
+ let results = await connection.results({
189
+ table: "zfields",
190
+ where: {
191
+ table: table
192
+ }
193
+ });
194
+ if (results.length == 0) {
195
+ await connection.insert({table: "zfields", data: post})
196
+ } else {
197
+ await connection.update({table: "zfields", where: {id: results[0].id}, data: post});
198
+ }
199
+ json.status = 1;
200
+ json.url = '/generator?table=' + table;
201
+ res.send(json)
202
+ });
203
+
204
+
205
+ //after drag and drop then save
206
+ // and generate
207
+ router.post("/save_and_generate", csrfProtection, async (req, res) => {
208
+ try {
209
+ if (nots.includes(req.body.table)) {
210
+ return res.json(Util.flashError("Table is locked"));
211
+ }
212
+ const json = await generate(req, res);
213
+ res.json(json);
214
+ } catch (e) {
215
+ console.log(e);
216
+ res.status(400).json({message: e.toString()})
217
+ }
218
+ });
219
+
220
+ const generate = async (req, res) => {
221
+ const body = req.body;
222
+ const table = body.table;
223
+ const MYMODELS = myCache.get('MYMODELS');
224
+ let MYMODEL = {};
225
+ let chains = [];
226
+ let datas;
227
+ let results;
228
+ let dummy = false;
229
+ //save data into table zfields
230
+ //console.log(JSON.stringify(body.others))
231
+ const others = body.others;
232
+ //return;
233
+ await saveToZFields(body);
234
+
235
+ let exist = await connection.query(connection.describeTable(table));
236
+ if (exist.length) {
237
+ body.rows = await connection.results({table: "zfields", where: {table: table}});
238
+ body.checks = await connection.query(`SELECT 'public.${table}'::regclass`);
239
+ } else {
240
+ let sql = `
241
+ CREATE TABLE ${table} (
242
+ id BIGSERIAL PRIMARY KEY,
243
+ company_id BIGINT NOT NULL,
244
+ updated_by BIGINT DEFAULT NULL,
245
+ created_by BIGINT DEFAULT NULL,
246
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
247
+ updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
248
+ CONSTRAINT fk_${table}_company_id FOREIGN KEY (company_id) REFERENCES zcompany (id)
249
+ );`;
250
+ await connection.query(sql);
251
+ body.checks = await connection.query(`SELECT 'public.${table}'::regclass`);
252
+ body.rows = await connection.results({table: "zfields", where: {table: table}});
253
+ }
254
+ body.others = others;
255
+ results = await axios.post(`${generatorUrl}/api/generator/properties`, body);
256
+ datas = results.data;
257
+ if (datas.create_table.hasOwnProperty("sql")) {
258
+ await connection.query(datas.create_table.sql);
259
+ return generate(body);
260
+ }
261
+
262
+ let result = await connection.update({
263
+ table: 'zfields',
264
+ data: datas.updateFields.post,
265
+ where: {
266
+ id: datas.updateFields.id
267
+ }
268
+ });
269
+
270
+ let properties = result.properties;
271
+ //update if any chains
272
+ for (let key in properties) {
273
+ //override
274
+ properties[key].values.required = properties[key].values.required ? true : false;
275
+ properties[key].values.unique = properties[key].values.unique ? true : false;
276
+ var isChain = properties[key].values.isChain ? true : false;
277
+ properties[key].values.isChain = isChain;
278
+ if (isChain) {
279
+ chains.push(key)
280
+ }
281
+ }
282
+ if (chains.length && chains.length < 2) {
283
+ return Util.flashError("Chains min 2 fields number...");
284
+ }
285
+ if (chains.length) {
286
+ let prop = chainings(table, chains);
287
+ for (const key in prop) {
288
+ if (prop[key].hasOwnProperty("chains")) {
289
+ chains = Object.keys(prop[key].chains);
290
+ if (chains.length) {
291
+ properties[key].values.chains = prop[key].chains;
292
+ }
293
+ }
294
+ }
295
+ }
296
+ //update properties
297
+ result = await connection.update({
298
+ table: "zfields",
299
+ data: {
300
+ properties: JSON.stringify(properties)
301
+ },
302
+ where: {
303
+ table: table
304
+ }
305
+ });
306
+ //end chains
307
+
308
+ //generate file models routes views
309
+ body.columns = await connection.query(connection.describeTable(table));
310
+ body.constraintList = await connection.query(connection.constraintList(table));
311
+ body.result = result;
312
+ results = await axios.post(`${generatorUrl}/api/generator/generate`, body);
313
+ datas = results.data;
314
+ let files = datas.files;
315
+ for (let key in files) {
316
+ let filesKey = files[key];
317
+ if (key == "model") {
318
+ if (filesKey.hasOwnProperty("sql")) {
319
+ const sql = filesKey.sql || [];
320
+ for (let i = 0; i < sql.length; i++) {
321
+ console.log(i + "sql : " + sql[i])
322
+ await connection.query(sql[i]);
323
+ }
324
+ }
325
+ if (filesKey.hasOwnProperty("alter")) {
326
+ const alter = filesKey.alter || [];
327
+ for (let i = 0; i < alter.length; i++) {
328
+ console.log(alter[i])
329
+ await connection.query(alter[i]);
330
+ }
331
+ }
332
+ if (filesKey.hasOwnProperty("index")) {
333
+ const index = filesKey.index || [];
334
+ for (let i = 0; i < index.length; i++) {
335
+ console.log(index[i])
336
+ await connection.query(index[i]);
337
+ }
338
+ }
339
+ if (filesKey.hasOwnProperty("fk")) {
340
+ let fk = filesKey.fk || [];
341
+ for (let i = 0; i < fk.length; i++) {
342
+ console.log(fk[i])
343
+ await connection.query(fk[i]);
344
+ }
345
+ }
346
+ if (filesKey.hasOwnProperty("defaultValue")) {
347
+ const defaultValue = filesKey.defaultValue || [];
348
+ for (let i = 0; i < defaultValue.length; i++) {
349
+ console.log(defaultValue[i])
350
+ await connection.query(defaultValue[i]);
351
+ }
352
+ }
353
+ //console.log(JSON.stringify(filesKey.modelObj))
354
+ //check if has chains here
355
+ MYMODEL = filesKey.modelObj;
356
+
357
+ //delete/clean zgrid after changes
358
+ await connection.delete({
359
+ table: "zgrid",
360
+ where: {
361
+ route_name: table
362
+ }
363
+ });
364
+ await connection.delete({
365
+ table: 'zgrid_default',
366
+ where: {
367
+ table: table
368
+ }
369
+ });
370
+ //insert into zgrid default
371
+ let datagrid = {
372
+ company_id: 1,
373
+ updated_by: 1,
374
+ created_by: 1,
375
+ created_at: Util.now(),
376
+ updated_at: Util.now()
377
+ };
378
+ datagrid.table = table;
379
+ datagrid.visibles = JSON.stringify(MYMODEL.grids.visibles);
380
+ datagrid.invisibles = JSON.stringify(MYMODEL.grids.invisibles);
381
+ datagrid.fields = JSON.stringify([...MYMODEL.grids.visibles, ...MYMODEL.grids.invisibles]);
382
+ await connection.insert({
383
+ table: 'zgrid_default',
384
+ data: datagrid
385
+ });
386
+
387
+ fs.writeFileSync(`${dirRoot}/models/${filesKey.filename}`, filesKey.content);
388
+ console.log(`The file model of ${filesKey.filename} is saved!`);
389
+
390
+ let widgets = MYMODEL.widgets;
391
+ let objChains = {}
392
+ let chainsTable = [];
393
+ let isChain = false;
394
+ for (let key in widgets) {
395
+ let hasChains = widgets[key].hasOwnProperty("isChain") ? widgets[key].isChain : false;
396
+ if (hasChains) {
397
+ isChain = true;
398
+ if (widgets[key].hasOwnProperty("table")) {
399
+ chainsTable.push(widget_table);
400
+ var widget_table = widgets[key].table;
401
+ objChains[widget_table] = {
402
+ key: key,
403
+ changes: []
404
+ }
405
+ }
406
+ }
407
+ }
408
+
409
+ if (isChain) {
410
+ for (let key in objChains) {
411
+ const model_table = MYMODELS[key];// require(`./../models/${key}`);
412
+ for (let q in model_table.widgets) {
413
+ if (model_table.widgets[q].hasOwnProperty("table")) {
414
+ if (Util.in_array(model_table.widgets[q].table, chainsTable)) {
415
+ const objChanges = {
416
+ target: objChains[key].key,
417
+ table: key,
418
+ column: q,
419
+ name: widgets[objChains[key].key].fields[1]
420
+ };
421
+ objChains[model_table.widgets[q].table].changes.push(objChanges);
422
+ }
423
+ }
424
+ }
425
+ }
426
+ //console.log(JSON.stringify(objChains))
427
+ //update model
428
+ for (let key in objChains) {
429
+ const keykey = objChains[key].key;
430
+ widgets[keykey].chains = objChains[key].changes
431
+ }
432
+ MYMODEL.widgets = widgets;
433
+ let newModel = `module.exports = ${Util.newLine}${Util.tab}{${Util.newLine}`;
434
+ //newModel += JSON.stringify(MYMODEL, null, 2)
435
+ newModel += zRoute.buildFileModel(MYMODEL);
436
+ newModel += `${Util.tab}};`;
437
+
438
+ fs.writeFileSync(`${dirRoot}/models/${filesKey.filename}`, newModel);
439
+ //console.log(JSON.stringify(objChains))
440
+ }
441
+ //check model if it has select relation in concat
442
+ await scanning(MYMODEL);
443
+ }
444
+ //generate views
445
+ let DIR_VIEW = `${dirRoot}/views/${table}`;
446
+ if (key == "views") {
447
+ if (!fs.existsSync(DIR_VIEW)) {
448
+ fs.mkdirSync(DIR_VIEW);
449
+ }
450
+ let compilesJS = ['createjs.ejs', 'updatejs.ejs', 'importjs.ejs'];
451
+
452
+ let resultJSON = Object.prototype.hasOwnProperty.call(result,'json') ? result.json : {};
453
+ if(resultJSON.hasOwnProperty('dummy')) {
454
+ dummy = resultJSON.dummy;
455
+ }
456
+ if(!dummy) {
457
+ for (const q in filesKey) {
458
+ console.log(q);
459
+ if (Util.in_array(q, compilesJS)) {
460
+ fs.writeFileSync(`${DIR_VIEW}/${q}`, filesKey[q]);
461
+ /* console.log(filesKey[q]);
462
+ let myscript = filesKey[q];
463
+ myscript = myscript.replaceAll(`<script>`,'').replaceAll(`</script>`,'');
464
+ console.log(myscript);
465
+ let script = uglifyJS.minify(myscript);
466
+ if (script.error) throw script.error;
467
+ fs.writeFileSync(`${DIR_VIEW}/${q}`, script.code);*/
468
+ } else {
469
+ fs.writeFileSync(`${DIR_VIEW}/${q}`, await minify(filesKey[q],
470
+ {
471
+ minifyJS: true,
472
+ minifyCSS: true,
473
+ collapseWhitespace: true
474
+ }
475
+ ));
476
+ }
477
+ console.log(`The files views of ${q} is saved!`);
478
+ }
479
+ }
480
+ }
481
+ if (key == "route") {
482
+ if(!dummy) {
483
+ fs.writeFileSync(`${dirRoot}/routes/${filesKey.filename}`, filesKey.content);
484
+ }
485
+ //console.log(`The files route of ${filesKey.filename} is saved!`);
486
+ }
487
+ }
488
+
489
+ //make a directory
490
+ if(!dummy) {
491
+ let path_script = `${dirRoot}/public/runtime/script/${table}`;
492
+ Util.dirExist(path_script, true);
493
+ let path_head = `${dirRoot}/public/runtime/head/${table}`;
494
+ Util.dirExist(path_head, true);
495
+ let path_end = `${dirRoot}/public/runtime/end/${table}`;
496
+ Util.dirExist(path_end, true);
497
+ //we need to generate javascript code into runtime
498
+ let relations = await zRoute.relations(req, res, MYMODEL.table);
499
+ //add script
500
+ let jsObj = zRoute.generateJS(req, res, MYMODEL, relations);
501
+ //minify script
502
+ let script = uglifyJS.minify(jsObj.script);
503
+ if (script.error) {
504
+ console.log(jsObj.script);
505
+ throw script.error;
506
+ }
507
+ let time = new Date().getTime();
508
+ Util.deleteAllFiles(path_script);
509
+ Util.deleteAllFiles(path_head);
510
+ Util.deleteAllFiles(path_end);
511
+ Util.writeFile(`${path_script}/${time}.js`, script.code);
512
+ Util.writeFile(`${path_head}/head.txt`, jsObj.head);
513
+ Util.writeFile(`${path_end}/end.txt`, jsObj.end);
514
+ }
515
+
516
+ //restart pm2 module in production
517
+ if (process.env.NODE_ENV == "production") {
518
+ pm2.connect(function (err) {
519
+ if (err) {
520
+ console.log(err.toString());
521
+ }
522
+ pm2.restart(process.env.PM2_NAME, (err, proc) => {
523
+ //io.to(room).emit("message","Restart done")
524
+ });
525
+ });
526
+ }
527
+
528
+ return Util.jsonSuccess("Success");
529
+ };
530
+
531
+ router.post('/savetabs', async (req, res) => {
532
+ let body = req.body;
533
+ let table = body.table;
534
+ let details = body.details;
535
+ let left = [], right = [], tabLeft = {}, tabRight = {};
536
+ let json = {status: 0, title: 'error', message: 'error', url: ''};
537
+ let obj = {}
538
+ obj.notabs = []
539
+ let labels = {};
540
+ let hasTab = false;
541
+ if (nots.includes(table)) {
542
+ return res.json(Util.flashError("Table is locked"));
543
+ }
544
+
545
+ let rows = await connection.results({table: "zfields", where: {table: table}});
546
+ if (rows.length > 0) {
547
+ let tabsValue = rows[0].tabs + "";
548
+ if (tabsValue.length > 5) {
549
+ hasTab = true;
550
+ let tabs = rows[0].tabs;
551
+ for (let i = 0; i < tabs.length; i++) {
552
+ obj['arr' + i] = [];
553
+ tabLeft['arr' + i] = [];
554
+ tabRight['arr' + i] = [];
555
+ }
556
+ }
557
+ }
558
+
559
+ for (let i = 0; i < details.length; i++) {
560
+ let name = details[i].name;
561
+ let value = details[i].value;
562
+ if (name.indexOf("___") > -1) {
563
+ let explode = name.split("___");
564
+ obj[explode[1]].push(explode[0])
565
+ labels[explode[0]] = value;
566
+ } else {
567
+ if (name == 'LEFT') {
568
+ if (value.indexOf("___") > -1) {
569
+ var explode = value.split("___");
570
+ tabLeft[explode[1]].push(explode[0])
571
+ } else {
572
+ left.push(value);
573
+ }
574
+ } else if (name == 'RIGHT') {
575
+ if (value.indexOf("___") > -1) {
576
+ let explode = value.split("___");
577
+ tabRight[explode[1]].push(explode[0])
578
+ } else {
579
+ right.push(value);
580
+ }
581
+ } else {
582
+ obj['notabs'].push(name);
583
+ labels[name] = value;
584
+ }
585
+ }
586
+ }
587
+ let post = {}
588
+ post.labels = JSON.stringify(labels);
589
+ post.details = JSON.stringify(obj);
590
+ post.left = hasTab ? JSON.stringify(tabLeft) : JSON.stringify(left);
591
+ post.right = hasTab ? JSON.stringify(tabRight) : JSON.stringify(right);
592
+ //console.log(post.left)
593
+ //console.log(JSON.stringify(post))
594
+ try {
595
+ if (rows.length > 0) {
596
+ await connection.update({table: "zfields", data: post, where: {id: rows[0].id}})
597
+ } else {
598
+ post.table = table;
599
+ await connection.insert({table: "zfields", data: post})
600
+ }
601
+ json = {status: 1, title: 'Success', message: 'Success', url: ''}
602
+ } catch (error) {
603
+ json = Util.flashError(error.sqlMessage);
604
+ }
605
+
606
+ res.send(json)
607
+ });
608
+
609
+ const columnLR = (items, dataName) => {
610
+ return `<div class="col-md-6"><ol class="mydragable divboxlittle" data-name="${dataName}">${items}</ol></div>`;
611
+ };
612
+
613
+ const columnOne = (items) => {
614
+ 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>`;
615
+ };
616
+
617
+ const reformatProperties = async (position, item, table, arr) => {
618
+ const newData = JSON.stringify(Util.arrayDelete(arr, item));
619
+ const data = {
620
+ [position]: newData
621
+ };
622
+ await connection.update({
623
+ table: "zfields",
624
+ data: data,
625
+ where: {
626
+ table: table
627
+ }
628
+ })
629
+ };
630
+
631
+ router.delete("/delete-table", csrfProtection, async (req, res) => {
632
+ let table = req.body.table;
633
+ let json = Util.jsonSuccess("Successfully delete module");
634
+ if (Util.in_array(table, nots)) {
635
+ return res.json(Util.flashError("Can not be deleted!"))
636
+ }
637
+ if (nots.includes(table)) {
638
+ return res.json(Util.flashError("Table is locked"));
639
+ }
640
+ try {
641
+ await connection.delete({
642
+ table: "zfields",
643
+ where: {
644
+ table: table
645
+ }
646
+ });
647
+ //await connection.query("DELETE FROM zfields WHERE `table` = ?", [table]);
648
+ await connection.query(`DROP table "${table}";`);
649
+ //delete file
650
+ let modelFile = dirRoot + "/models/" + table + ".js";
651
+ fs.stat(modelFile, function (err, stats) {
652
+ console.log(stats);//here we got all information of file in stats variable
653
+ if (err) {
654
+ return console.error(err);
655
+ } else {
656
+ fs.unlink(modelFile, function (err) {
657
+ if (err) return console.log(err);
658
+ console.log('file deleted successfully');
659
+ });
660
+ }
661
+ });
662
+
663
+ let routesFile = dirRoot + "/routes/" + table + ".js";
664
+ fs.stat(routesFile, function (err, stats) {
665
+ console.log(stats);//here we got all information of file in stats variable
666
+ if (err) {
667
+ return console.error(err);
668
+ } else {
669
+ fs.unlink(routesFile, function (err) {
670
+ if (err) return console.log(err);
671
+ console.log('file deleted successfully');
672
+ });
673
+ }
674
+ });
675
+
676
+ let runtimeFile = dirRoot + "/runtime/scripts/" + table + ".js";
677
+ fs.stat(runtimeFile, function (err, stats) {
678
+ if (err) {
679
+ return console.error(err);
680
+ } else {
681
+ fs.unlink(runtimeFile, function (err) {
682
+ if (err) return console.log(err);
683
+ console.log('file deleted successfully');
684
+ });
685
+ }
686
+
687
+ });
688
+ await connection.delete({
689
+ table: "zgrid",
690
+ where: {route_name: table}
691
+ });
692
+ if (table) {
693
+ const viewsFile = dirRoot + "/views/" + table;
694
+ fs.stat(viewsFile, function (err, stats) {
695
+ if (err) {
696
+ return console.error(err);
697
+ } else {
698
+ fs.rmdirSync(viewsFile, {recursive: true});
699
+ }
700
+ });
701
+ }
702
+ await connection.delete({
703
+ table: "zgrid_default",
704
+ where: {table: table}
705
+ });
706
+ } catch (e) {
707
+ json = Util.flashError(e.toString(), "")
708
+ }
709
+
710
+ res.json(json)
711
+ });
712
+
713
+ router.post("/add_field", csrfProtection, async (req, res) => {
714
+ try {
715
+ const body = req.body;
716
+ //console.log(JSON.stringify(body.others))
717
+ const table = body.table;
718
+ if (nots.includes(table)) {
719
+ return res.json(Util.flashError("Table is locked"));
720
+ }
721
+ body.zFields = await connection.results({table: "zfields", where: {table: table}});
722
+ const results = await axios.post(`${generatorUrl}/api/generator/create_field`, body);
723
+ const datas = results.data;
724
+ if (datas.status == 1) {
725
+ await connection.update({table: 'zfields', where: {table: table}, data: datas.post})
726
+ }
727
+ res.json(datas)
728
+ } catch (e) {
729
+ res.json(Util.flashError(e.toString()));
730
+ }
731
+ });
732
+
733
+ router.post('/add_container', async (req, res) => {
734
+ let others = req.body.others;
735
+ let table = req.body.table;
736
+ //console.log(JSON.stringify(req.body))
737
+ try {
738
+ if (others && table) {
739
+ await connection.update({
740
+ table: 'zfields',
741
+ data: {
742
+ others: others
743
+ },
744
+ where: {
745
+ table: table
746
+ }
747
+ })
748
+ }
749
+ } catch (e) {
750
+ return res.json(Util.flashError(e.toString()))
751
+ }
752
+
753
+ res.json(Util.jsonSuccess("Success"));
754
+ });
755
+
756
+
757
+ router.post("/setting_field", csrfProtection, async (req, res) => {
758
+ if (nots.includes(req.body.table)) {
759
+ return res.json(Util.flashError("Table is locked"));
760
+ }
761
+ const body = req.body;
762
+ const table = body.table;
763
+ const html = "";
764
+ body.result = await connection.result({table: "zfields", where: {table: table}});
765
+ const results = await axios.post(`${generatorUrl}/api/generator/modal_settings`, body);
766
+ const datas = results.data;
767
+ res.json(datas.html)
768
+ });
769
+
770
+
771
+ router.post("/save_setting", async (req, res) => {
772
+ const html = "", table = req.query.table || "";
773
+ let json = Util.jsonSuccess("Success to update");
774
+ try {
775
+ if (nots.includes(req.body.table)) {
776
+ return res.json(Util.flashError("Table is locked"));
777
+ }
778
+ const post = req.body;
779
+ let data = await connection.result({
780
+ table: "zfields",
781
+ where: {table: table}
782
+ })
783
+ let properties = data.properties ? data.properties : {};
784
+ let propertyKey = "";
785
+ for (var key in post) {
786
+ propertyKey = key;
787
+ }
788
+
789
+ properties[propertyKey].values = post[propertyKey];
790
+ let insert = {
791
+ properties: JSON.stringify(properties)
792
+ };
793
+ await connection.update({
794
+ table: "zfields",
795
+ data: insert,
796
+ where: {table: table}
797
+ });
798
+
799
+ } catch (e) {
800
+ json = Util.flashError(e.toString())
801
+ }
802
+
803
+ res.json(json);
804
+ });
805
+
806
+
807
+ router.delete("/delete_field", csrfProtection, async (req, res) => {
808
+ let json = Util.jsonSuccess("Success to update");
809
+ try {
810
+ if (nots.includes(req.body.table)) {
811
+ return res.json(Util.flashError("Table is locked"));
812
+ }
813
+ const table = req.body.table, name = req.body.name;
814
+ let data = await connection.result({
815
+ table: "zfields",
816
+ where: {table: table}
817
+ });
818
+ let properties = data.properties ? data.properties : {};
819
+ delete properties[name];
820
+ let labels = data.labels ? data.labels : {};
821
+ delete labels[name];
822
+
823
+ let left = data.left ? data.left : [];
824
+ left = Util.arrayDelete(left, name);
825
+ let right = data.right ? data.right : [];
826
+ right = Util.arrayDelete(right, name);
827
+ let oneColumn = data.one_column ? data.one_column : [];
828
+ oneColumn = Util.arrayDelete(oneColumn, name);
829
+ let details = data.details ? data.details : {};
830
+ let detailsTemp = {}
831
+ for (var keys in details) {
832
+ detailsTemp[keys] = Util.arrayDelete(details[keys], name);
833
+ }
834
+ let newProperty = {};
835
+ newProperty.properties = JSON.stringify(properties);
836
+ newProperty.labels = JSON.stringify(labels);
837
+ newProperty.left = JSON.stringify(left);
838
+ newProperty.right = JSON.stringify(right);
839
+ newProperty.one_column = JSON.stringify(oneColumn);
840
+ newProperty.details = JSON.stringify(detailsTemp);
841
+ newProperty.sorting = JSON.stringify(data.sorting);
842
+ await connection.update({
843
+ table: "zfields",
844
+ data: newProperty,
845
+ where: {table: table}
846
+ });
847
+ //DROP COULUMN
848
+ //ALTER TABLE table_name DROP COLUMN IF EXISTS column_name;
849
+ await connection.query(`ALTER TABLE "${table}" DROP COLUMN IF EXISTS "${name}";`)
850
+ } catch (err) {
851
+ json = Util.flashError(err.toString())
852
+ console.log(err);
853
+ console.log("ada error di update zfields");
854
+ }
855
+ res.json(json);
856
+ });
857
+
858
+
859
+ router.post("/tab_rename", csrfProtection, async (req, res) => {
860
+ const html = "", table = req.body.table || "", name = req.body.name || "", id = req.body.id || 0;
861
+ let json = Util.jsonSuccess("Success to rename");
862
+ try {
863
+ if (table == "") {
864
+ return res.json(Util.flashError("table empty"))
865
+ }
866
+ if (name == "") {
867
+ return res.json(Util.flashError("name empty"));
868
+ }
869
+ let data = await connection.result({
870
+ table: "zfields",
871
+ where: {table: table}
872
+ });
873
+ const tabs = data.tabs || [];
874
+ let arr = []
875
+ tabs.forEach(function (item, index) {
876
+ if (index == id) {
877
+ arr.push(name);
878
+ } else {
879
+ arr.push(item);
880
+ }
881
+ });
882
+ let post = {
883
+ tabs: JSON.stringify(arr)
884
+ }
885
+ await connection.update({
886
+ table: "zfields",
887
+ data: post,
888
+ where: {
889
+ table: table
890
+ }
891
+ });
892
+ } catch (e) {
893
+ json = Util.flashError(e.toString())
894
+ }
895
+ res.json(json);
896
+ });
897
+
898
+ const zfields = async () => {
899
+ return await connection.results({
900
+ select: `id, "table", "name", "route",tabs,labels, details, "left","right",one_column, sorting, properties,hardcode_grid,others,json`,
901
+ table: "zfields",
902
+ orderBy: ['table', 'asc']
903
+ });
904
+ };
905
+
906
+ router.post('/load-form', async (req, res) => {
907
+ const table = req.body.table;
908
+ let json = Util.flashError("error");
909
+ const result = await connection.result({
910
+ table: "zfields",
911
+ where: {
912
+ table: table
913
+ }
914
+ });
915
+ if (result.id) {
916
+ json = Util.jsonSuccess("success");
917
+ json.data = result;
918
+ }
919
+ res.json(json)
920
+ });
921
+
922
+ var saveToZFields = async (body) => {
923
+ const table = body.table;
924
+ let is_approval = body.is_approval;
925
+ if (typeof body.is_approval == "string") {
926
+ if (body.is_approval == "false") {
927
+ is_approval = 0;
928
+ } else if (body.is_approval == "true") {
929
+ is_approval = 1;
930
+ }
931
+ }
932
+
933
+ const zapprovals = {};
934
+ zapprovals.title = body.approval_title;
935
+ zapprovals.type = body.type;
936
+ zapprovals.approvers = body.approvers;
937
+ zapprovals.knowings = body.knowings;
938
+ zapprovals.content = body.template;
939
+ var data = {
940
+ index_ejs: body.index_ejs,
941
+ indexcss_ejs: body.indexcss_ejs,
942
+ indexjs_ejs: body.indexjs_ejs,
943
+ form_ejs: body.form_ejs,
944
+ create_ejs: body.create_ejs,
945
+ createjs_ejs: body.createjs_ejs,
946
+ update_ejs: body.update_ejs,
947
+ updatejs_ejs: body.updatejs_ejs,
948
+ import_ejs: body.import_ejs,
949
+ importjs_ejs: body.importjs_ejs,
950
+ view_ejs: body.view_ejs,
951
+ is_approval: is_approval || 0,
952
+ approval_json: JSON.stringify(zapprovals),
953
+ others: body.others
954
+ }
955
+
956
+ await connection.update({
957
+ table: "zfields",
958
+ data: data,
959
+ where: {
960
+ table: table
961
+ }
962
+ })
963
+ };
964
+
965
+
966
+ //drop down chains effect
967
+ const chainings = async (table, arr) => {
968
+ const results = await connection.query(connection.showFields(table));
969
+ const obj = {};
970
+ const tableObj = {};
971
+ for (let i = 0; i < results.length; i++) {
972
+ const result = results[i];
973
+ if (Util.in_array(result.COLUMN_NAME, arr)) {
974
+ obj[result.COLUMN_NAME] = {
975
+ table: result.REFERENCED_TABLE_NAME
976
+ }
977
+ tableObj[result.REFERENCED_TABLE_NAME] = result.COLUMN_NAME;
978
+ }
979
+ }
980
+
981
+ for (const key in obj) {
982
+ const rows = await connection.query(connection.showFields(obj[key].table));
983
+ rows.forEach(function (row) {
984
+ for (var q in obj) {
985
+ if (row.REFERENCED_TABLE_NAME == obj[q].table) {
986
+ if (!obj[q].chains) {
987
+ obj[q].chains = {};
988
+ }
989
+ obj[q].chains[key] = {
990
+ column: row.COLUMN_NAME,
991
+ table: row.TABLE_NAME
992
+ }
993
+ }
994
+ }
995
+ });
996
+ }
997
+ return obj;
998
+ };
999
+
1000
+ router.post('/sorting', async (req, res) => {
1001
+ let sorting = req.body.sorting;
1002
+ let table = req.body.table;
1003
+ await connection.update({
1004
+ table: "zfields",
1005
+ data: {
1006
+ sorting: sorting
1007
+ },
1008
+ where: {table: table}
1009
+ });
1010
+ res.send("OK")
1011
+ });
1012
+
1013
+ router.post("/export", async (req, res) => {
1014
+ const table = req.body.table;
1015
+ let json = Util.jsonSuccess("file Complete");
1016
+ if (table) {
1017
+ const result = await connection.result({
1018
+ table: "zfields",
1019
+ where: {
1020
+ table: table
1021
+ }
1022
+ });
1023
+ const dir = `${dirRoot}/public/uploads/zgenerator`;
1024
+ if (!fs.existsSync(dir)) {
1025
+ fs.mkdirSync(dir);
1026
+ }
1027
+ const text = JSON.stringify(result);
1028
+ fs.writeFileSync(`${dir}/${table}.json`, text);
1029
+ } else {
1030
+ json = Util.flashError("no table selected")
1031
+ }
1032
+ res.json(json)
1033
+ })
1034
+
1035
+ router.post("/import", async (req, res) => {
1036
+ let json = Util.flashError("Error File")
1037
+ let table = "";
1038
+ try {
1039
+ let isEmptyFiles = Util.isEmptyObject(req.files);
1040
+ if (!isEmptyFiles) {
1041
+ const file = req.files["import-file"];
1042
+ const name = file.name;
1043
+ const mime = file.mimetype;
1044
+ if (mime == "application/json") {
1045
+ const string = file.data.toString('utf8');
1046
+ const jsonFile = JSON.parse(string);
1047
+ table = jsonFile.table;
1048
+ delete jsonFile.id;
1049
+ const data = {}
1050
+ for (const key in jsonFile) {
1051
+ let value = jsonFile[key];
1052
+ if (typeof value == "object") {
1053
+ value = JSON.stringify(value)
1054
+ }
1055
+ data[key] = value;
1056
+ }
1057
+ if (!data.tabs) {
1058
+ data.tabs = "[]";
1059
+ }
1060
+ data.company_id = 1;
1061
+ data.created_by = res.locals.userId || 1;
1062
+ data.updated_by = res.locals.userId || 1;
1063
+ const results = await connection.results({
1064
+ table: "zfields",
1065
+ where: {
1066
+ table: table
1067
+ }
1068
+ })
1069
+ if (results.length) {
1070
+ await connection.update({
1071
+ table: "zfields",
1072
+ data: data,
1073
+ where: {
1074
+ table: table
1075
+ }
1076
+ })
1077
+ } else {
1078
+ await connection.insert({
1079
+ table: "zfields",
1080
+ data: data,
1081
+ })
1082
+ }
1083
+ json = Util.jsonSuccess("Success to add module, please generate tax to make a file")
1084
+ }
1085
+ }
1086
+ } catch (e) {
1087
+ console.log(e)
1088
+ json.message = e.toString();
1089
+ }
1090
+ json.table = table;
1091
+ res.json(json)
1092
+ });
1093
+
1094
+ /*
1095
+ Scanning relation id to name
1096
+ */
1097
+ const scanning = async (MYMODEL) => {
1098
+ //let MYMODEL = require(`./../models/${table}`);
1099
+ //console.log(JSON.stringify(MYMODEL))
1100
+ let table = MYMODEL.table;
1101
+ const widgets = MYMODEL.widgets;
1102
+ const not_scanning = ['created_by', 'updated_by'];
1103
+ const concat_bracket = /(?<=\().+?(?=\))/g;
1104
+ let changeWidgets = {}
1105
+ let changes = [];
1106
+ for (let key in widgets) {
1107
+ if (widgets[key].name == "relation" || widgets[key].name == "dropdown_multi" || widgets[key].name == "typeahead") {
1108
+ if (!Util.in_array(key, not_scanning)) {
1109
+ let fields = widgets[key].fields;
1110
+ //let concat = fields[1].indexOf('CONCAT(') > -1 ? fields[1].substring()
1111
+ let arr = fields[1].match(concat_bracket) || [];
1112
+ if (arr.length) {
1113
+ let str = Util.replaceAll(arr[0], '"', '');
1114
+ let mysplits = str.indexOf(',') > -1 ? str.split(',') : [str];
1115
+ let MYMODEL_TABLE = require(`./../models/${widgets[key].table}`);
1116
+ let widgetsRelations = MYMODEL_TABLE.widgets;
1117
+ let relationsKeys = [];
1118
+ let relationsKeysObject = {}
1119
+ for (let k in widgetsRelations) {
1120
+ if (widgetsRelations[k].name == 'relation') {
1121
+ if (!Util.in_array(k, not_scanning)) {
1122
+ relationsKeys.push(k);
1123
+ relationsKeysObject[k] = `(SELECT ${widgetsRelations[k].fields[1]} FROM ${widgetsRelations[k].table} where id = `
1124
+ }
1125
+ }
1126
+ }
1127
+ let myarr = [];
1128
+ mysplits.forEach(function (item) {
1129
+ if (Util.in_array(item, relationsKeys)) {
1130
+ changes.push(key)
1131
+ myarr.push(relationsKeysObject[item] + ` ${item} )`)
1132
+ } else {
1133
+ myarr.push(item)
1134
+ }
1135
+ });
1136
+ let myjoin = `CONCAT(${myarr.join(',')})`;
1137
+ widgets[key].fields = ['id', myjoin];
1138
+ }
1139
+ }
1140
+ }
1141
+ }
1142
+
1143
+ if (changes.length) {
1144
+ //rewrite model
1145
+ MYMODEL.widgets = widgets;
1146
+ let newModel = `module.exports = { ${Util.newLine}`;
1147
+ newModel += zRoute.buildFileModel(MYMODEL);
1148
+ newModel += `${Util.newLine}`;
1149
+ newModel += `}`;
1150
+ fs.writeFileSync(`${dirRoot}/models/${MYMODEL.table}.js`, newModel);
1151
+ }
1152
+
1153
+ //return MYMODEL;
1154
+ };
1155
+
1156
+ //generate all css/js assets
1157
+ router.post('/generate-assets', async (req, res) => {
1158
+ let notifObj = Util.jsonSuccess("Success, generate all assets");
1159
+ try {
1160
+ let MYMODELS = zRoute.MYMODELS();
1161
+ delete MYMODELS.zrole;
1162
+ for (let key in MYMODELS) {
1163
+ let MYMODEL = MYMODELS[key];
1164
+ let table = MYMODEL.table;
1165
+ let path_script = `${dirRoot}/public/runtime/script/${table}`;
1166
+ Util.dirExist(path_script, true);
1167
+ let path_head = `${dirRoot}/public/runtime/head/${table}`;
1168
+ Util.dirExist(path_head, true);
1169
+ let path_end = `${dirRoot}/public/runtime/end/${table}`;
1170
+ Util.dirExist(path_end, true);
1171
+ //we need to generate javascript code into runtime
1172
+ let relations = await zRoute.relations(req, res, MYMODEL.table);
1173
+ //add script
1174
+ let jsObj = zRoute.generateJS(req, res, MYMODEL, relations);
1175
+ let time = new Date().getTime();
1176
+ Util.deleteAllFiles(path_head);
1177
+ Util.deleteAllFiles(path_end);
1178
+ Util.deleteAllFiles(path_script);
1179
+
1180
+ //minify script
1181
+ let script = uglifyJS.minify(jsObj.script);
1182
+ if (script.error) throw script.error;
1183
+ Util.writeFile(`${path_script}/${time}.js`, script.code);
1184
+ Util.writeFile(`${path_head}/head.txt`, jsObj.head);
1185
+ Util.writeFile(`${path_end}/end.txt`, jsObj.end);
1186
+ }
1187
+ } catch (e) {
1188
+ notifObj = Util.flashError(e.toString());
1189
+ }
1190
+ res.json(notifObj);
1191
+ });
1192
+
1193
+
1194
+ router.post('/minify', async (req, res) => {
1195
+ let notifyObj = Util.jsonSuccess("Success to cached");
1196
+ try {
1197
+ notifyObj = await viewsMini();
1198
+ } catch (e) {
1199
+ console.log(e);
1200
+ notifyObj = Util.flashError(e.toString())
1201
+ }
1202
+ res.json(notifyObj);
1203
+ });
1204
+
1205
+ const viewsMini = async () => {
1206
+ let notifyObj = Util.jsonSuccess("Success");
1207
+ const viewDir = `${dirRoot}/views`;
1208
+ const layoutsDir = `${dirRoot}/views/layouts`;
1209
+ let item;
1210
+ try {
1211
+ let views = Util.getAllFiles(viewDir);
1212
+ let options = {
1213
+ minifyJS: true,
1214
+ minifyCSS: true,
1215
+ collapseWhitespace: true
1216
+ };
1217
+ const notViewDir = ['zgenerator', 'layouts', 'index', 'zindex'];
1218
+ for (const dir of views) {
1219
+ console.log('dir :', dir);
1220
+ if (!Util.in_array(dir, notViewDir)) {
1221
+ let files = Util.getAllFiles(`${viewDir}/${dir}`);
1222
+ //console.log(files);
1223
+ for (item of files) {
1224
+ if (item.includes('.ejs')) {
1225
+ let filename = `${viewDir}/${dir}/${item}`;
1226
+ let content = Util.readFile(filename);
1227
+ let contentChange = await minify(content, options);
1228
+ fs.writeFileSync(filename, contentChange);
1229
+ }
1230
+ }
1231
+ }
1232
+ }
1233
+
1234
+ let layouts = Util.getAllFiles(layoutsDir);
1235
+ for (item of layouts) {
1236
+ if (item.includes('.ejs')) {
1237
+ let filename = `${layoutsDir}//${item}`;
1238
+ let content = Util.readFile(filename);
1239
+ let contentChange = await minify(content, options);
1240
+ fs.writeFileSync(filename, contentChange);
1241
+ }
1242
+ }
1243
+ } catch (e) {
1244
+ notifyObj = Util.flashError(`error in item : ${item} , error str :${e.toString()}`);
1245
+ }
1246
+ return notifyObj;
1247
+ };
1248
+
1249
+ module.exports = router;