zet-lib 1.3.43 → 1.4.0

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,1064 @@
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 Util = require("./Util");
7
+ const connection = require("./connection");
8
+ const myCache = require("./cache");
9
+ const moduleLib = require("./moduleLib");
10
+ const Model = require('./Model')
11
+ const ejs = require('ejs')
12
+
13
+ router.get('/', csrfProtection, async (req, res) => {
14
+ const nots = ['index', 'uploads', 'js', 'css', 'log', 'generator', 'zmenu', 'zgenerator', 'zfields', 'zrole', 'zfunction', 'zgrid', 'zgrid_default', 'zpage', 'zlayout', 'zerror', 'zuser_company']
15
+ let table = req.query.table || '';
16
+ let view = req.query.view || '';
17
+ let route = '';
18
+ let jsonData = {}
19
+ let zForms = {}
20
+ let relations = {}
21
+ const MYMODELS = myCache.get('MYMODELS')
22
+ let datas = await viewAttributes(view)
23
+ zForms.obj = {}
24
+ let sorting = ''
25
+ let rows = await connection.results({
26
+ select: `id, "name", "route",labels, details`,
27
+ table: 'zviews',
28
+ orderBy: ['name', 'asc'],
29
+ })
30
+ if (view) {
31
+ table = view;
32
+ let queries = datas.datas.queries;
33
+ let contentScript = `var ZFIELDS = ${JSON.stringify(rows, null, 2)};${Util.newLine} var queries = ${JSON.stringify(datas.datas.queries)}`
34
+ moduleLib.addScript(req, res, contentScript)
35
+ moduleLib.editor(req, res)
36
+ }
37
+ let selectView = `<select name="table" id="table" class="form-control"><option value="">Please Select</option>`
38
+ rows.map((row) => {
39
+ let selected = view == row.route ? " selected " : ""
40
+ selectView += `<option value="${row.route}" ${selected} >${row.name}</option>`
41
+ })
42
+ selectView += `</select>`
43
+ const tables = await connection.results({
44
+ select: `id, "table", "name", "route",tabs,labels, details, "left","right",one_column, sorting, properties,others,json`,
45
+ table: 'zfields',
46
+ orderBy: ['table', 'asc'],
47
+ })
48
+ let selectTable = `<select class="form-control form-select" id="select_module_joins">
49
+ <option value="">Please Select</option>`
50
+ tables.map((item) => {
51
+ selectTable += `<option value="${item.table}">${item.table}</option>`
52
+ })
53
+ selectTable += `</select>`
54
+ //console.log(datas)
55
+ let layout = 'view_generator'
56
+ const renderData = {
57
+ datas,
58
+ table,
59
+ view,
60
+ rows,
61
+ selectView,
62
+ tables,
63
+ selectTable,
64
+ csrfToken: req.csrfToken(),
65
+ route: view,
66
+ selects: jsonData.selects,
67
+ zForms: zForms,
68
+ relations: relations,
69
+ routeName: res.locals.routeName
70
+ }
71
+ const bodyView = Util.readFile(require.resolve(__dirname + '/views/zview.ejs'))
72
+ const bodyHTML = ejs.render(bodyView, renderData)
73
+ const endHTML = ejs.render(Util.readFile(require.resolve(__dirname + '/views/zviewjs.ejs')), renderData)
74
+ let dataRender = renderData
75
+ dataRender.bodyHTML = bodyHTML
76
+ dataRender.endHTML = endHTML
77
+ res.render(require.resolve(__dirname + '/views/view_layout.ejs'), dataRender)
78
+ })
79
+
80
+ router.post('/addview', async (req, res) => {
81
+ try {
82
+ console.log(req.body)
83
+ let body = req.body;
84
+ let route = Util.toName(body.route);
85
+ let name = body.name;
86
+ name = name.trim();
87
+ let json = Util.jsonSuccess("Success")
88
+ let forbidden = ['group', 'copy', 'command', 'from', 'select', 'distinct', 'where', 'year', 'month', 'day', 'ignore', 'previous', 'next',
89
+ 'start', 'end', 'set', 'setof', 'show', 'size', 'row', 'rows', 'return', 'order'];
90
+ if (forbidden.includes(name)) {
91
+ json = Util.flashError("View Name is Forbidden, try using other module name..", "route");
92
+ return json;
93
+ }
94
+ if (!name.length) {
95
+ json = Util.flashError("View Name Empty", "route");
96
+ return json;
97
+ }
98
+ let datas = {
99
+ name: name,
100
+ route: route,
101
+ table: route,
102
+ company_id: 1,
103
+ sorting: JSON.stringify([2, 1]),
104
+ created_at: Util.now(),
105
+ updated_at: Util.now(),
106
+ created_by: res.locals.userId || 1,
107
+ updated_by: res.locals.userId || 1,
108
+ }
109
+ await connection.insert({
110
+ table: 'zviews',
111
+ data: datas,
112
+ })
113
+ res.json(json)
114
+ } catch (err) {
115
+ res.json(Util.flashError(err.toString()))
116
+ }
117
+ })
118
+
119
+ router.post('/fields', async (req, res) => {
120
+ try {
121
+ let body = req.body
122
+ let table = body.table || ''
123
+ let result = {},
124
+ fields = {},
125
+ rowsFields = []
126
+ if (table) {
127
+ result = await connection.result({table: 'zviews', where: {table: table}})
128
+ }
129
+ let datas = await fieldsBox(result);
130
+ res.json(datas)
131
+ } catch (e) {
132
+ console.log(e)
133
+ res.json(e.toString())
134
+ }
135
+ })
136
+
137
+ router.post('/load-form', async (req, res) => {
138
+ const table = req.body.table
139
+ console.log(table)
140
+ let json = Util.flashError('error')
141
+ const result = await connection.result({
142
+ table: 'zviews',
143
+ where: {
144
+ table: table,
145
+ },
146
+ })
147
+ if (result.id) {
148
+ json = Util.jsonSuccess('success')
149
+ if (!result.router) {
150
+ result.router = Util.readFile(require.resolve(__dirname + '/views/router.txt'))
151
+ }
152
+ if (!result.index_ejs) {
153
+ result.index_ejs = Util.readFile(require.resolve(__dirname + '/views/index_ejs.txt'))
154
+ }
155
+ if (!result.indexcss_ejs) {
156
+ result.indexcss_ejs = Util.readFile(require.resolve(__dirname + '/views/indexcss_ejs.txt'))
157
+ }
158
+ if (!result.indexjs_ejs) {
159
+ result.indexjs_ejs = Util.readFile(require.resolve(__dirname + '/views/indexjs_ejs.txt'))
160
+ }
161
+ if (!result.view_ejs) {
162
+ result.view_ejs = Util.readFile(require.resolve(__dirname + '/views/view_ejs.txt'))
163
+ }
164
+ if (!result.queries) {
165
+ result.queries = {
166
+ sql: '',
167
+ fields: [],
168
+ tables: []
169
+ }
170
+ }
171
+ json.data = result
172
+ }
173
+ res.json(json)
174
+ })
175
+
176
+ router.post('/load-joins', async (req, res) => {
177
+ let jsonNotif = Util.jsonSuccess('Success')
178
+ let html = ''
179
+ try {
180
+ let body = req.body
181
+ console.log(body)
182
+ let table = body.table
183
+ html = await loadJoins(table)
184
+ jsonNotif.html = html
185
+ } catch (e) {
186
+ console.log(e)
187
+ }
188
+ res.json(jsonNotif)
189
+ })
190
+
191
+ router.post('/remove-joins', async (req, res) => {
192
+ let jsonNotif = Util.jsonSuccess('Success')
193
+ let html = ''
194
+ try {
195
+ let body = req.body
196
+ console.log(body)
197
+ let table = body.table
198
+ let table_join = body.table_join
199
+ let result = await connection.result({
200
+ table: 'zviews',
201
+ where: {
202
+ table: table,
203
+ },
204
+ })
205
+ let resultJoins = result.joins || {}
206
+ delete resultJoins[table_join]
207
+
208
+ await connection.update({
209
+ table: 'zviews',
210
+ data: {
211
+ joins: JSON.stringify(resultJoins),
212
+ },
213
+ where: {
214
+ table: table,
215
+ },
216
+ })
217
+ } catch (e) {
218
+ console.log(e)
219
+ }
220
+ res.json(jsonNotif)
221
+ })
222
+
223
+ router.post('/joins', async (req, res) => {
224
+ let jsonNotif = Util.jsonSuccess('Success')
225
+ let html = ''
226
+ try {
227
+ let body = req.body
228
+ console.log(body)
229
+ let table = body.table
230
+ let table_join = body.table_join
231
+ let result = await connection.result({
232
+ table: 'zviews',
233
+ where: {
234
+ route: table,
235
+ },
236
+ })
237
+ let resultJoins = result.joins || {}
238
+ resultJoins[table_join] = []
239
+ let myzfield = await connection.update({
240
+ table: 'zviews',
241
+ data: {
242
+ joins: JSON.stringify(resultJoins),
243
+ },
244
+ where: {
245
+ table: table,
246
+ },
247
+ })
248
+ jsonNotif.json = resultJoins
249
+ html = await joinHTML(resultJoins, myzfield)
250
+ } catch (e) {
251
+ console.log(e)
252
+ jsonNotif = Util.flashError(e + '')
253
+ }
254
+ jsonNotif.html = html
255
+ res.json(jsonNotif)
256
+ })
257
+
258
+
259
+ router.delete('/delete-table', csrfProtection, async (req, res) => {
260
+ let table = req.body.table
261
+ let json = Util.jsonSuccess('Successfully delete view')
262
+ try {
263
+ await connection.delete({
264
+ table: 'zviews',
265
+ where: {
266
+ route: table,
267
+ },
268
+ })
269
+ //await connection.query("DELETE FROM zfields WHERE `table` = ?", [table]);
270
+ await connection.query(`DROP VIEW "${table}";`)
271
+ //delete file
272
+ let modelFile = dirRoot + '/models/' + table + '.js'
273
+ fs.stat(modelFile, function (err, stats) {
274
+ console.log(stats) //here we got all information of file in stats variable
275
+ if (err) {
276
+ return console.error(err)
277
+ } else {
278
+ fs.unlink(modelFile, function (err) {
279
+ if (err) return console.log(err)
280
+ console.log('file deleted successfully')
281
+ })
282
+ }
283
+ })
284
+
285
+ let routesFile = dirRoot + '/routes/' + table + '.js'
286
+ fs.stat(routesFile, function (err, stats) {
287
+ console.log(stats) //here we got all information of file in stats variable
288
+ if (err) {
289
+ return console.error(err)
290
+ } else {
291
+ fs.unlink(routesFile, function (err) {
292
+ if (err) return console.log(err)
293
+ console.log('file deleted successfully')
294
+ })
295
+ }
296
+ })
297
+
298
+ let runtimeFile = dirRoot + '/public/runtime/script/' + table
299
+ fs.rm(
300
+ runtimeFile,
301
+ {
302
+ recursive: true,
303
+ },
304
+ (error) => {
305
+ if (error) {
306
+ console.log(error)
307
+ } else {
308
+ console.log('Recursive: Directories Deleted!')
309
+ }
310
+ }
311
+ )
312
+ let runtimeFileHead = dirRoot + '/public/runtime/head/' + table
313
+ fs.rm(
314
+ runtimeFileHead,
315
+ {
316
+ recursive: true,
317
+ },
318
+ (error) => {
319
+ if (error) {
320
+ console.log(error)
321
+ } else {
322
+ console.log('Recursive: Directories Deleted!')
323
+ }
324
+ }
325
+ )
326
+ let runtimeFileEnd = dirRoot + '/public/runtime/end/' + table
327
+ fs.rm(
328
+ runtimeFileEnd,
329
+ {
330
+ recursive: true,
331
+ },
332
+ (error) => {
333
+ if (error) {
334
+ console.log(error)
335
+ } else {
336
+ console.log('Recursive: Directories Deleted!')
337
+ }
338
+ }
339
+ )
340
+
341
+ await connection.delete({
342
+ table: 'zgrid',
343
+ where: {route_name: table},
344
+ })
345
+ if (table) {
346
+ const viewsFile = dirRoot + '/views/' + table
347
+ fs.rm(
348
+ viewsFile,
349
+ {
350
+ recursive: true,
351
+ },
352
+ (error) => {
353
+ if (error) {
354
+ console.log(error)
355
+ } else {
356
+ console.log('Recursive: Directories Deleted!')
357
+ }
358
+ }
359
+ )
360
+ }
361
+ await connection.delete({
362
+ table: 'zgrid_default',
363
+ where: {table: table},
364
+ })
365
+ } catch (e) {
366
+ json = Util.flashError(e.toString(), '')
367
+ }
368
+
369
+ res.json(json)
370
+ })
371
+
372
+ router.post('/save_and_generate', csrfProtection, async (req, res) => {
373
+ try {
374
+ const json = await generate(req, res)
375
+ res.json(json)
376
+ } catch (e) {
377
+ console.log(e)
378
+ res.status(200).json({message: e + ''})
379
+ }
380
+ })
381
+
382
+ //save to table zviews
383
+
384
+ const generate = async (req, res) => {
385
+ const body = req.body
386
+ console.log(body)
387
+ const table = body.table
388
+ const MYMODELS = myCache.get('MYMODELS')
389
+ let MYMODEL = {}
390
+ let chains = []
391
+ let datas = {}
392
+ let results
393
+ let dummy = false
394
+ const details = body.details || [];
395
+ let left = [], right = [], lefts = [], rights = [], oneColumn = [], oneColumns = [], tabLeft = {}, tabRight = {};
396
+ const obj = {}
397
+ obj.notabs = []
398
+ let labels = {};
399
+ let hasTab = false;
400
+ let tabs = {};
401
+ let joins = {}
402
+ let rows = await connection.results({table: 'zviews', where: {table: table}})
403
+ labels = rows[0].labels || {};
404
+ tabs = !rows[0].tabs ? [] : rows[0].tabs;
405
+ if (tabs.length) {
406
+ hasTab = true;
407
+ tabs.forEach(function (item, i) {
408
+ obj['arr' + i] = [];
409
+ tabLeft['arr' + i] = [];
410
+ tabRight['arr' + i] = [];
411
+ });
412
+ }
413
+ details.forEach(function (item, index) {
414
+ let name = item.name, value = item.value;
415
+ if (name.includes("_wtf_")) {
416
+ let split = name.split("_wtf_")
417
+ if (!joins[split[0]]) {
418
+ joins[split[0]] = []
419
+ }
420
+ joins[split[0]].push(split[1])
421
+ }
422
+ if (name.includes("___")) {
423
+ const explode = name.split("___");
424
+ //console.log(explode[1], explode[0])
425
+ obj[explode[1]].push(explode[0])
426
+ labels[explode[0]] = value;
427
+ } else {
428
+ if (name == 'LEFT') {
429
+ left.push(value);
430
+ } else if (name == 'RIGHT') {
431
+ right.push(value);
432
+ } else if (name == 'ONE_COLUMN') {
433
+ oneColumn.push(value);
434
+ } else {
435
+ obj['notabs'].push(name);
436
+ labels[name] = value;
437
+ }
438
+ }
439
+ });
440
+
441
+ const sorting = details[1].name == "ONE_COLUMN" ? [1, 2] : [2, 1];
442
+ for (let key in obj) {
443
+ if (key == "notabs") {
444
+ lefts = obj[key].filter((item) => left.includes(item));
445
+ rights = obj[key].filter((item) => right.includes(item));
446
+ oneColumns = obj[key].filter((item) => oneColumn.includes(item));
447
+ } else {
448
+ let myobj = {}
449
+ myobj[key] = obj[key].filter((item) => left.includes(item));
450
+ lefts.push(myobj);
451
+ myobj = {}
452
+ myobj[key] = obj[key].filter((item) => right.includes(item));
453
+ rights.push(myobj);
454
+ myobj = {}
455
+ myobj[key] = obj[key].filter((item) => oneColumn.includes(item));
456
+ oneColumns.push(myobj);
457
+ }
458
+ }
459
+
460
+ //set properties
461
+ let properties = {}
462
+ let propertiesKey = {}
463
+ for (let key in joins) {
464
+ let zfieldData = await connection.result({
465
+ table: "zfields",
466
+ where: {
467
+ table: key
468
+ }
469
+ })
470
+ if (!propertiesKey[key]) {
471
+ propertiesKey[key] = {}
472
+ }
473
+ propertiesKey[key] = zfieldData.properties
474
+ let arr = joins[key] || [];
475
+ arr.map((item) => {
476
+ properties[`${key}_wtf_${item}`] = propertiesKey[key][item]
477
+ })
478
+ }
479
+
480
+ datas.labels = JSON.stringify(labels);
481
+ datas.details = JSON.stringify(obj);
482
+ datas.left = JSON.stringify(lefts);
483
+ datas.right = JSON.stringify(rights);
484
+ datas.one_column = JSON.stringify(oneColumns);
485
+ datas.sorting = JSON.stringify(sorting);
486
+ datas.joins = JSON.stringify(joins);
487
+ datas.queries = JSON.stringify(body.queries);
488
+ datas.router = body.router;
489
+ datas.index_ejs = body.index_ejs;
490
+ datas.indexcss_ejs = body.indexcss_ejs;
491
+ datas.indexjs_ejs = body.indexjs_ejs;
492
+ datas.view_ejs = body.view_ejs;
493
+ datas.properties = JSON.stringify(properties);
494
+ await connection.update({
495
+ table: "zviews",
496
+ data: datas,
497
+ where: {
498
+ table: table
499
+ }
500
+ })
501
+ try {
502
+ await connection.query(`DROP VIEW ${table}`)
503
+ } catch (e) {
504
+ console.log(e)
505
+ }
506
+ let sql = ` CREATE OR REPLACE VIEW ${table} AS ${body.queries.sql};`
507
+ await connection.query(sql)
508
+ //create model route views file
509
+ await createAllFiles(table)
510
+ //restart pm2 module in production
511
+ if (process.env.NODE_ENV == 'production') {
512
+ pm2.connect(function (err) {
513
+ if (err) {
514
+ console.log(err.toString())
515
+ }
516
+ pm2.restart(process.env.PM2_NAME, (err, proc) => {
517
+ //io.to(room).emit("message","Restart done")
518
+ })
519
+ })
520
+ }
521
+
522
+ return Util.jsonSuccess('Success')
523
+ }
524
+
525
+ router.post('/set-query', async (req, res) => {
526
+ try {
527
+ //joins_checks___item_delivery_order___no_barang
528
+ let body = req.body;
529
+ let queries = body.queries;
530
+ let type = body.type;
531
+ //type = 1 add -1 delete
532
+ let field = body.name.replace("joins_checks___", "")
533
+ let table = field.split(".")[0];
534
+ let tables = queries.tables || []
535
+ let fields = queries.fields || []
536
+ if (type == 1) {
537
+ if (!fields.includes(field)) {
538
+ fields.push(field)
539
+ }
540
+ } else {
541
+ if (fields.length > 0) {
542
+ Util.arrayDelete(fields, field)
543
+ }
544
+ }
545
+ let sql = ``
546
+ let selects = []
547
+ if (fields.length > 0) {
548
+ fields.forEach(function (item) {
549
+ let split = item.split(".");
550
+ selects.push(`${split[0]}.${split[1]} as ${split[0]}_wtf_${split[1]}`)
551
+ if (!tables.includes(split[0])) {
552
+ tables.push(split[0])
553
+ }
554
+ })
555
+ sql = `SELECT ${selects.join(", ")}, ${tables[0]}.company_id as company_id, ${tables[0]}.id as id ${Util.newLine}`;
556
+ sql += `FROM ${tables[0]} ${Util.newLine}`
557
+ }
558
+ if (tables.length > 1) {
559
+ let tempfks = {}
560
+ for (let i = 0; i <= tables.length; i++) {
561
+ //check foreign key
562
+ let fks = await connection.query(connection.showFields(tables[i]));
563
+ fks.map((item) => {
564
+ tempfks[item.REFERENCED_TABLE_NAME] = `LEFT JOIN ${item.REFERENCED_TABLE_NAME} ON ${item.TABLE_NAME}.${item.COLUMN_NAME} = ${item.REFERENCED_TABLE_NAME}.${item.REFERENCED_COLUMN_NAME} `
565
+ })
566
+ if (i > 0) {
567
+ if (tempfks[tables[i]]) {
568
+ sql += tempfks[tables[i]];
569
+ }
570
+ }
571
+ }
572
+ }
573
+ res.json({
574
+ tables: tables,
575
+ fields: fields,
576
+ sql: sql
577
+ })
578
+ } catch (e) {
579
+ console.log(e)
580
+ }
581
+ })
582
+
583
+ router.post('/setting_field', csrfProtection, async (req, res) => {
584
+ let json = Util.jsonSuccess("Success")
585
+ let html = '';
586
+ try {
587
+ const body = req.body
588
+ const table = body.table
589
+ const name = body.name
590
+ const result = await connection.result({ table: 'zviews', where: { table: table } })
591
+ let properties = result.properties ? result.properties : {};
592
+ let property = !properties[name] ? {} : properties[name];
593
+ let type = property.type;
594
+ html = Model.buildWidget(name, type, property.values || {});
595
+ } catch (e) {
596
+ console.log(e)
597
+ html = Util.flashError(e.toString())
598
+ }
599
+ res.json(html)
600
+ })
601
+
602
+ async function fieldsBox(result) {
603
+ try {
604
+ const table = result.route || "";
605
+ let html = '';
606
+ var datas = {table: '', tabs: [], labels: {}, details: {}, left: [], right: []};
607
+ let count = 1;
608
+ let tabView = '';
609
+ let tabUl = '';
610
+ let tabContent = '';
611
+ let left = '', right = '', oneColumn = '';
612
+ let hasTab = false;
613
+ let properties = {}
614
+ let rowsFields;
615
+ if (table) {
616
+ if (result.id) {
617
+ datas = {
618
+ details: result.details || {},
619
+ labels: result.labels || {},
620
+ tabs: result.tabs || [],
621
+ left: result.left || [],
622
+ right: result.right || [],
623
+ oneColumn: result.one_column || [],
624
+ sorting: result.sorting || [],
625
+ property: result.properties || {},
626
+ joins: result.joins
627
+ };
628
+ let details = datas.details;
629
+ properties = datas.property;
630
+ let tabs = datas.tabs;
631
+ if (tabs.length) {
632
+ hasTab = true;
633
+ }
634
+ if (hasTab) {
635
+ tabUl += '<ul class="nav nav-tabs" id="myTab" role="tablist">';
636
+ tabContent += '<div class="tab-content" id="myTabContent">';
637
+ tabs.forEach(function (item, i) {
638
+ const navlink = i == 0 ? ' active' : '';
639
+ const ariaselected = i == 0 ? "true" : "false";
640
+ const showActive = i == 0 ? ' show active ' : '';
641
+ const n = i + 1;
642
+ const arrName = 'arr' + i;
643
+ let dynamicsLeft = '', dynamicsRight = '', dynamicsOneColumn = '';
644
+ let tabLeft = [], tabRight = [], tabOneColum = [];
645
+ if (datas.left.length) {
646
+ datas.left.forEach(function (o) {
647
+ if (typeof o == "object") {
648
+ for (var key in o) {
649
+ if (key == arrName) {
650
+ tabLeft = o[key];
651
+ }
652
+ }
653
+ }
654
+ });
655
+ }
656
+ if (datas.right.length) {
657
+ datas.right.forEach(function (o) {
658
+ if (typeof o == "object") {
659
+ for (var key in o) {
660
+ if (key == arrName) {
661
+ tabRight = o[key];
662
+ }
663
+ }
664
+ }
665
+ });
666
+ }
667
+ if (datas.oneColumn.length) {
668
+ datas.oneColumn.forEach(function (o) {
669
+ if (typeof o == "object") {
670
+ for (var key in o) {
671
+ if (key == arrName) {
672
+ tabOneColum = o[key];
673
+ }
674
+ }
675
+ }
676
+ });
677
+ }
678
+
679
+ if (tabLeft.length) {
680
+ tabLeft.map((o) => {
681
+ if (datas.property[o] && datas.property[o].hasOwnProperty("type")) {
682
+ dynamicsLeft += dragable_with_icon(o, datas.labels[o], i, "LEFT", datas.property[o].type);
683
+ }
684
+ });
685
+ }
686
+ if (tabRight.length) {
687
+ tabRight.map((o) => {
688
+ if (datas.property[o] && datas.property[o].hasOwnProperty("type")) {
689
+ dynamicsRight += dragable_with_icon(o, datas.labels[o], i, "RIGHT", datas.property[o].type);
690
+ }
691
+ });
692
+ }
693
+
694
+ if (tabOneColum.length) {
695
+ tabOneColum.map((o) => {
696
+ if (datas.property[o] && datas.property[o].hasOwnProperty("type")) {
697
+ dynamicsOneColumn += dragable_with_icon(o, datas.labels[o], i, "ONE_COLUMN", datas.property[o].type);
698
+ }
699
+ });
700
+ }
701
+
702
+ tabView += `<li class="item" draggable="true"><div class='divtabs'>${n}. <span class="tabname"> ${item}</span><input type='hidden' name='tabs[]' value='${item}' /> <button type='button' class='btn btn-sm btn-info edittab' data-toggle="modal" data-target="#modal_tab" data-name="${item}" data-id="${i}" > <i class='fas fa-edit'></i> </button> <button type='button' onclick='$(this).parent().remove();' class='btn btn-sm btn-danger trashtab'><i class='fas fa-trash'></i> </button></div></li>`;
703
+ tabUl += `<li class="nav-item">
704
+ <a class="nav-link ${navlink}" id="tabid${i}" data-toggle="tab" href="#tabgo${i}" role="tab" aria-controls="tabgo${i}" aria-selected="${ariaselected}">${item}</a>
705
+ </li>`;
706
+
707
+ tabContent += `<div class="tab-pane fade ${showActive}" id="tabgo${i}" role="tabpanel" aria-labelledby="tabtabgo${i}">
708
+ <div class="container">
709
+ <div class="row">
710
+ <div class="col-md-6"><ol class="mydragable divbox" data-name="LEFT" id="arr${i}">${dynamicsLeft}</ol></div>
711
+ <div class="col-md-6"><ol class="mydragable divbox" data-name="RIGHT" id="arr${i}">${dynamicsRight}</ol></div>
712
+ </div>
713
+ <div class="row">
714
+ <div class="col-md-12"><ol class="mydragable divbox" data-name="ONE_COLUMN" id="arr${i}">${dynamicsOneColumn}</ol></div>
715
+ </div>
716
+ </div>
717
+ </div>`;
718
+ });
719
+ //end tabs
720
+ tabUl += '</ul>';
721
+ tabContent += '</div>';
722
+ count = tabs.length + 1;
723
+ }
724
+ }
725
+ }
726
+ //caption left or right
727
+ if (datas.left.length) {
728
+ datas.left.forEach(function (item) {
729
+ if (properties.hasOwnProperty(item)) {
730
+ left += dragable_with_icon(item, datas.labels[item], "", "LEFT", datas.property[item].type);
731
+ }
732
+ });
733
+ }
734
+ if (datas.right.length) {
735
+ datas.right.forEach(function (item) {
736
+ if (properties.hasOwnProperty(item)) {
737
+ right += dragable_with_icon(item, datas.labels[item], "", "RIGHT", datas.property[item].type);
738
+ }
739
+ });
740
+ }
741
+ if (datas.oneColumn.length) {
742
+ datas.oneColumn.forEach(function (item) {
743
+ if (properties.hasOwnProperty(item)) {
744
+ oneColumn += dragable_with_icon(item, datas.labels[item], "", "ONE_COLUMN", datas.property[item].type);
745
+ }
746
+ });
747
+ }
748
+ datas.sorting.forEach(function (item, index) {
749
+ if (item == 1) {
750
+ html += columnOne(oneColumn);
751
+ } else {
752
+ html += `<div class="row sortable"><i class="fa fa-arrows icon-floats"></i>${columnLR(left, "LEFT")} ${columnLR(right, "RIGHT")}</div>`;
753
+ }
754
+ });
755
+ let json = {}
756
+ json.html = html;
757
+ json.datas = datas;
758
+ json.tabview = tabView;
759
+ json.count = count;
760
+ json.tabBox = tabUl + tabContent;
761
+
762
+ return json;
763
+ //res.json(json);
764
+ } catch (e) {
765
+ console.log(e)
766
+ //res.status(400).json({message: e.toString()})
767
+ //json = {}
768
+ return {}
769
+ }
770
+ }
771
+
772
+ const zFieldsProperty = async (table, fields) => {
773
+ let data = {}
774
+ data.table = table;
775
+ data.name = Util.fieldToName(table);
776
+ data.route = table;
777
+ let label = {}
778
+ let details = [], lefts = [], rights = [];
779
+ let nots = Util.nots;
780
+ //let fields = await connection.query(connection.showFullFields(table));
781
+ fields.forEach(function (item) {
782
+ label[item.Field] = Util.fieldToName(item.Field);
783
+ });
784
+ data.labels = JSON.stringify(label);
785
+ let num = 1;
786
+ fields.forEach(function (item) {
787
+ if (!Util.in_array(item.Field, nots)) {
788
+ details.push(item.Field);
789
+ if (num % 2 == 0) {
790
+ rights.push(item.Field)
791
+ } else {
792
+ lefts.push(item.Field)
793
+ }
794
+ num++;
795
+ }
796
+ });
797
+ let notabs = {
798
+ notabs: details
799
+ }
800
+
801
+ data.details = JSON.stringify(notabs);
802
+ data.left = JSON.stringify(lefts);
803
+ data.right = JSON.stringify(rights);
804
+ return data;
805
+ };
806
+
807
+ const dragable_with_icon = (name, label, tab, leftright, type = "") => {
808
+ let myname = tab === "" ? name : name + "___arr" + tab;
809
+ leftright = leftright || "LEFT";
810
+ var typeName = type ? Model.keys[type] : "";
811
+ return `<li id="li${name}">
812
+ <div class="input-group">
813
+ <div class="input-group-prepend">
814
+ <span class="input-group-text modal_setting" data-type="${typeName}" data-name="${name}" data-label="${label}" ><i class="fa fa-cog text-info modal_setting" data-type="${typeName}" data-name="${name}" data-label="${label}"></i> </span>
815
+ <span class="input-group-text can-copy" data-name="${name}" title="click to copy"><i class="fa fa-copy"></i></span>
816
+ <span class="input-group-text" >${name}</span>
817
+ <input type="text" class="form-control" data-name="${name}" name="${myname}" value="${label}">
818
+ <input type="hidden" name="${leftright}" value="${name}">
819
+ </div>
820
+ </div><br></li>`;
821
+ };
822
+
823
+ const columnLR = (items, dataName) => {
824
+ return `<div class="col-md-6"><ol class="mydragable divboxlittle" data-name="${dataName}">${items}</ol></div>`;
825
+ }
826
+
827
+ const columnOne = (items) => {
828
+ 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>`;
829
+ }
830
+
831
+
832
+ async function loadJoins(table) {
833
+ let html = ''
834
+ try {
835
+ /* let sql = `select ${table}.* from ${table} `;
836
+ console.log(sql)*/
837
+ let result = await connection.result({
838
+ table: 'zviews',
839
+ where: {
840
+ table: table,
841
+ },
842
+ })
843
+ let joinsObj = result.joins || {}
844
+ html = await joinHTML(joinsObj, result)
845
+ } catch (e) {
846
+ console.log(e)
847
+ html = e + ''
848
+ }
849
+ return html
850
+ }
851
+
852
+ async function joinHTML(json, myzfield) {
853
+ let html = ``
854
+ try {
855
+ let zfields = await connection.results({
856
+ table: 'zfields',
857
+ })
858
+ let zfieldsObj = Util.arrayToObject(zfields, 'table')
859
+ for (let key in json) {
860
+ html += `<div class="joinContainer col-md-4">`
861
+ html += `<h5>${zfieldsObj[key].name} <button type="button" class="btn btn-danger" onclick="removeJoins('${key}')"><i class="fa fa-trash "></i> </button></h5>`
862
+ html += fieldHTML(zfieldsObj[key], myzfield)
863
+ html += `</div>`
864
+ }
865
+ } catch (e) {
866
+ html = e + ''
867
+ }
868
+ return html
869
+ }
870
+
871
+ function fieldHTML(obj, myzfield) {
872
+ let html = ``
873
+ try {
874
+ let labels = obj.labels
875
+ let table = obj.table
876
+ let myzfieldJoins = myzfield.joins || {}
877
+ for (let key in labels) {
878
+ let mylabel = labels[key]
879
+ let selected = ''
880
+ if (myzfieldJoins[table]) {
881
+ let arr = myzfieldJoins[table] || []
882
+ arr.map((item) => {
883
+ if (item.key == `${table}.${key}`) {
884
+ selected = ` checked `
885
+ mylabel = item.value
886
+ }
887
+ })
888
+ }
889
+ html += `<div class="input-group">
890
+ <div class="input-group-prepend">
891
+ <span class="input-group-text"><input type="checkbox" ${selected} onclick="checked_join(this)" name="joins_checks___${table}.${key}"></span>
892
+ <span class="input-group-text">${key}</span>
893
+ <input type="text" class="form-control" name="joins_labels___${table}.${key}" id="joins___${table}___${key}" value="${mylabel}">
894
+ </div>
895
+ </div>`
896
+ }
897
+ } catch (e) {
898
+ html = e + ''
899
+ }
900
+ return html
901
+ }
902
+
903
+ const viewAttributes = async (tableView = '') => {
904
+ let result = {}
905
+ let datas = {}
906
+ let select = {
907
+ text: 'Text',
908
+ textarea: 'Textarea',
909
+ checkbox: 'Checkbox',
910
+ number: 'Amount',
911
+ integer: 'Integer',
912
+ select: 'Select (static) ',
913
+ relation: 'Select (relation to other module)',
914
+ image: 'Image Upload',
915
+ file: 'File Upload',
916
+ dropzone: 'Drop Files',
917
+ email: 'Email',
918
+ password: 'Password',
919
+ datepicker: 'Date Picker',
920
+ datetime: 'Date Time',
921
+ clockpicker: 'Clock Picker',
922
+ range: 'Range',
923
+ color: 'Color Picker',
924
+ switch: 'Switch',
925
+ tags: 'Tags',
926
+ editor: 'Editor',
927
+ tinymce: 'Editor Tiny MCE',
928
+ ide_editor: 'IDE Editor (code)',
929
+ multi_line_editor: 'Multi Line Editor',
930
+ radio: 'Radio ',
931
+ typeahead: 'Auto Complete',
932
+ dropdown_multi: 'Dropdown Multi',
933
+ lexical: 'Lexical Editor (Experimental)',
934
+ dropdown_checkbox: 'Dropdown Checkbox',
935
+ table: 'Table',
936
+ json: 'JSON',
937
+ location: 'Location (Google Map)',
938
+ numeric: 'Numeric/Double',
939
+ dragdrop: 'Drag Drop',
940
+ ltree: 'LTree',
941
+ virtual: 'Virtual Field (readonly)',
942
+ custom: 'Custom'
943
+ }
944
+ if (tableView) {
945
+ datas = await connection.result({
946
+ table: "zviews",
947
+ where: {
948
+ route: tableView
949
+ }
950
+ })
951
+ } else {
952
+ datas = {table: '', tabs: [], labels: {}, details: {}, queries: []}
953
+ }
954
+
955
+ return {
956
+ datas: datas,
957
+ table: tableView,
958
+ route: datas.route,
959
+ name: datas.name
960
+ }
961
+ }
962
+
963
+ //create model routes views
964
+ const createAllFiles = async (table) => {
965
+ let result = await connection.result({
966
+ table: "zviews",
967
+ where: {
968
+ table: table
969
+ }
970
+ })
971
+ let json = {
972
+ table: result.table,
973
+ routeName: result.route,
974
+ title: result.name,
975
+ hasTabs: false,
976
+ tabs: [],
977
+ tabsDetail: {
978
+ notabs: [],
979
+ },
980
+ keys: Object.keys(result.labels),
981
+ keysExcel: Object.keys(result.labels),
982
+ labels:result.labels
983
+ }
984
+ let fields = {}
985
+ let options = {}
986
+ let datas = {}
987
+ let widgets = {}
988
+ let grids = {
989
+ visibles:[],
990
+ invisibles:[]
991
+ }
992
+ let joins = result.joins || {}
993
+ const MYMODELS = myCache.get('MYMODELS')
994
+ for (let key in joins) {
995
+ let MYMODEL = MYMODELS[key]
996
+ let items = joins[key] || []
997
+ items.map((item) => {
998
+ fields[`${key}_wtf_${item}`] = MYMODEL.fields[item]
999
+ options[`${key}_wtf_${item}`] = MYMODEL.options[item]
1000
+ datas[`${key}_wtf_${item}`] = ""
1001
+ widgets[`${key}_wtf_${item}`] = MYMODEL.widgets[item]
1002
+ })
1003
+ }
1004
+ json.fields = fields
1005
+ json.options = options
1006
+ json.hasApproval = false
1007
+ grids.visibles = json.keys
1008
+ json.grids=grids
1009
+ json.datas=datas
1010
+ json.widgets=widgets
1011
+ json.queries=result.queries
1012
+ json.dataJoins=result.joins
1013
+
1014
+ await connection.delete({
1015
+ table: 'zgrid',
1016
+ where: {
1017
+ route_name: table,
1018
+ },
1019
+ })
1020
+ await connection.delete({
1021
+ table: 'zgrid_default',
1022
+ where: {
1023
+ table: table,
1024
+ },
1025
+ })
1026
+ //insert into zgrid default
1027
+ let datagrid = {
1028
+ company_id: 1,
1029
+ updated_by: 1,
1030
+ created_by: 1,
1031
+ created_at: Util.now(),
1032
+ updated_at: Util.now(),
1033
+ }
1034
+ datagrid.table = table
1035
+ datagrid.visibles = JSON.stringify(json.grids.visibles)
1036
+ datagrid.invisibles = JSON.stringify(json.grids.invisibles)
1037
+ datagrid.fields = JSON.stringify([...json.grids.visibles, ...json.grids.invisibles])
1038
+ await connection.insert({
1039
+ table: 'zgrid_default',
1040
+ data: datagrid,
1041
+ })
1042
+ //create model file
1043
+ let modelContent = `let MYMODEL = ${Util.newLine} ${JSON.stringify(json,null,2)} ${Util.newLine}module.exports=MYMODEL`
1044
+ fs.writeFileSync(`${dirRoot}/models/${table}.js`, modelContent)
1045
+ console.log(`The file model of ${table}.js is saved!`)
1046
+ //create route file
1047
+ fs.writeFileSync(`${dirRoot}/routes/${table}.js`, result.router.replace('[[[TABLE_NAME]]]', table))
1048
+ console.log(`The file model of ${table}.js is saved!`)
1049
+ //create views file
1050
+ let DIR_VIEW = `${dirRoot}/views/${table}`
1051
+ if (!fs.existsSync(DIR_VIEW)) {
1052
+ fs.mkdirSync(DIR_VIEW)
1053
+ }
1054
+ fs.writeFileSync(`${DIR_VIEW}/index.ejs`, result.index_ejs)
1055
+ console.log(`The file model of index.ejs is saved!`)
1056
+ fs.writeFileSync(`${DIR_VIEW}/indexcss.ejs`, result.indexcss_ejs)
1057
+ console.log(`The file model of indexcss.ejs is saved!`)
1058
+ fs.writeFileSync(`${DIR_VIEW}/indexjs.ejs`, result.indexjs_ejs)
1059
+ console.log(`The file model of indexjs.ejs is saved!`)
1060
+ fs.writeFileSync(`${DIR_VIEW}/view.ejs`, result.view_ejs)
1061
+ console.log(`The file model of view.ejs is saved!`)
1062
+ }
1063
+
1064
+ module.exports = router