zet-lib 1.0.23 → 1.0.25

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