zet-lib 1.0.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.
- package/LICENSE +21 -0
- package/README.md +4 -0
- package/lib/Form.js +717 -0
- package/lib/Mail.js +70 -0
- package/lib/Modal.js +95 -0
- package/lib/UI.js +15 -0
- package/lib/Util.js +1242 -0
- package/lib/access.js +6 -0
- package/lib/cache.js +4 -0
- package/lib/connection.js +304 -0
- package/lib/debug.js +22 -0
- package/lib/index.js +29 -0
- package/lib/io.js +45 -0
- package/lib/languages/lang_en.js +115 -0
- package/lib/languages/lang_fr.js +114 -0
- package/lib/languages/lang_id.js +116 -0
- package/lib/languages/lang_jp.js +114 -0
- package/lib/menuGenerator.js +236 -0
- package/lib/moduleLib.js +427 -0
- package/lib/tableForm.js +10 -0
- package/lib/zCache.js +326 -0
- package/lib/zComponent.js +27 -0
- package/lib/zFn.js +59 -0
- package/lib/zFunction.js +20 -0
- package/lib/zMenuCollections.js +62 -0
- package/lib/zReport.js +930 -0
- package/lib/zRole.js +140 -0
- package/lib/zRoute.js +3226 -0
- package/lib/zTester.js +93 -0
- package/lib/zapp.js +79 -0
- package/lib/zdataTable.js +130 -0
- package/package.json +50 -0
package/lib/zRoute.js
ADDED
|
@@ -0,0 +1,3226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* For default route controller
|
|
3
|
+
* service for routes
|
|
4
|
+
*/
|
|
5
|
+
const excelToJson = require('convert-excel-to-json');
|
|
6
|
+
const qs = require('qs');
|
|
7
|
+
//for generate PDF
|
|
8
|
+
const puppeteer = require('puppeteer');
|
|
9
|
+
const ejs = require('ejs');
|
|
10
|
+
const Util = require('./Util');
|
|
11
|
+
const connection = require('./connection');
|
|
12
|
+
const gridTable = 'zgrid';
|
|
13
|
+
const fs = require('fs-extra');
|
|
14
|
+
const io = require('./io');
|
|
15
|
+
const myCache = require('./cache');
|
|
16
|
+
const moment = require('moment');
|
|
17
|
+
const debug = require("./debug");
|
|
18
|
+
const moduleLib = require("./moduleLib");
|
|
19
|
+
const cForm = require("./Form");
|
|
20
|
+
const config = require('dotenv').config();
|
|
21
|
+
//const dirRoot = process.env.dirRoot;
|
|
22
|
+
|
|
23
|
+
const zRoute = {};
|
|
24
|
+
|
|
25
|
+
zRoute.tableHasNoCompanyId = ['zcompany', 'zrole', 'zgrid'];
|
|
26
|
+
|
|
27
|
+
//get all models
|
|
28
|
+
zRoute.MYMODELS = () => {
|
|
29
|
+
let obj = {};
|
|
30
|
+
const dir = `${dirRoot}/models`;
|
|
31
|
+
let models = Util.getAllFiles(dir);
|
|
32
|
+
for (const item of models) {
|
|
33
|
+
let name = item.replace('.js', '');
|
|
34
|
+
obj[name] = require(`${dir}/${name}`)
|
|
35
|
+
}
|
|
36
|
+
return obj;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
//get all routes
|
|
40
|
+
zRoute.ROUTES = () => {
|
|
41
|
+
let arr = [];
|
|
42
|
+
const dir = `${dirRoot}/routes`;
|
|
43
|
+
let routes = Util.getAllFiles(dir);
|
|
44
|
+
for (const item of routes) {
|
|
45
|
+
let name = item.replace('.js', '');
|
|
46
|
+
if (name != "index"){
|
|
47
|
+
arr.push(name)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return arr;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/*
|
|
54
|
+
Auto updated_at,created_at,company_id,created_by,updated_by
|
|
55
|
+
*/
|
|
56
|
+
zRoute.commons = (req, res, type = "create") => {
|
|
57
|
+
let data = {
|
|
58
|
+
company_id: res.locals.companyId,
|
|
59
|
+
created_at: Util.now(),
|
|
60
|
+
updated_at: Util.now(),
|
|
61
|
+
created_by: res.locals.userId,
|
|
62
|
+
updated_by: res.locals.userId
|
|
63
|
+
};
|
|
64
|
+
if (type != "create") {
|
|
65
|
+
delete data.created_at;
|
|
66
|
+
delete data.created_by;
|
|
67
|
+
return data;
|
|
68
|
+
} else {
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
post data handling
|
|
75
|
+
*/
|
|
76
|
+
zRoute.postData = (obj) => {
|
|
77
|
+
return qs.parse(obj);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
zRoute.post = (req, res, MYMODEL, routeName, body) => {
|
|
81
|
+
routeName = routeName || MYMODEL.routeName;
|
|
82
|
+
body = body || req.body;
|
|
83
|
+
let post = qs.parse(body);
|
|
84
|
+
let isEmptyFiles = Util.isEmptyObject(req.files);
|
|
85
|
+
let time = new Date().getTime();
|
|
86
|
+
let path_tmp = dirRoot + "/public/uploads/" + routeName + "/";
|
|
87
|
+
let hasFile = false;
|
|
88
|
+
let files;
|
|
89
|
+
let checkboxes = [];
|
|
90
|
+
let multies = [];
|
|
91
|
+
fs.ensureDir(path_tmp, err => {
|
|
92
|
+
console.log('ensureDir',err); // => null
|
|
93
|
+
});
|
|
94
|
+
if (!isEmptyFiles) {
|
|
95
|
+
files = qs.parse(req.files);
|
|
96
|
+
let fileRoute = files[routeName];
|
|
97
|
+
for (let key in fileRoute) {
|
|
98
|
+
let filename = time + fileRoute[key].name;
|
|
99
|
+
if (Array.isArray(fileRoute[key])) {
|
|
100
|
+
hasFile = true;
|
|
101
|
+
//add folder again
|
|
102
|
+
fs.ensureDir(path_tmp + key, err => {
|
|
103
|
+
console.log('ensureDir',err); // => null
|
|
104
|
+
});
|
|
105
|
+
} else {
|
|
106
|
+
fileRoute[key].mv(path_tmp + filename, function (err) {
|
|
107
|
+
if (err) {
|
|
108
|
+
console.log('fileempty move',err); // => null
|
|
109
|
+
return res.status(500).send(err);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
post[routeName][key] = filename;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
let widgets = MYMODEL.widgets;
|
|
117
|
+
let tags = [];
|
|
118
|
+
let val;
|
|
119
|
+
for (let key in post[routeName]) {
|
|
120
|
+
let widgetName = widgets[key].name;
|
|
121
|
+
val = post[routeName][key];
|
|
122
|
+
switch (widgetName) {
|
|
123
|
+
case "dropdown_checkbox" :
|
|
124
|
+
let checkboxArr = [];
|
|
125
|
+
for (let k in post[routeName][key]) {
|
|
126
|
+
if (post[routeName][key][k] == 1) {
|
|
127
|
+
checkboxArr.push(k)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
post[routeName][key] = JSON.stringify(checkboxArr);
|
|
131
|
+
break;
|
|
132
|
+
|
|
133
|
+
case "tags" :
|
|
134
|
+
tags.push(key);
|
|
135
|
+
let value = post[routeName][key] || "";
|
|
136
|
+
let dataValue;
|
|
137
|
+
if (value) {
|
|
138
|
+
if (typeof value == "object") {
|
|
139
|
+
dataValue = value;
|
|
140
|
+
dataValue = JSON.stringify(dataValue);
|
|
141
|
+
} else {
|
|
142
|
+
if (value.substring(0, 1) == "{") {
|
|
143
|
+
dataValue = `[${value.substring(1, (value.length - 1))}]`;
|
|
144
|
+
} else if (value.substring(0, 1) == "[") {
|
|
145
|
+
dataValue = value;
|
|
146
|
+
} else {
|
|
147
|
+
var arr = [];
|
|
148
|
+
arr.push(value);
|
|
149
|
+
dataValue = JSON.stringify(arr);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
post[routeName][key] = dataValue;
|
|
154
|
+
break;
|
|
155
|
+
|
|
156
|
+
case "dropdown_multi" :
|
|
157
|
+
post[routeName][key] = JSON.stringify(post[routeName][key]);
|
|
158
|
+
break;
|
|
159
|
+
|
|
160
|
+
case "lexical" :
|
|
161
|
+
post[routeName][key] = JSON.stringify(post[routeName][key]);
|
|
162
|
+
//console.log(post[routeName][key]);
|
|
163
|
+
break;
|
|
164
|
+
|
|
165
|
+
case "table" :
|
|
166
|
+
const MODEL_TABLE = require('./../models/' + widgets[key].table);
|
|
167
|
+
const postTableData = post[routeName][key];
|
|
168
|
+
const widgetTables = MODEL_TABLE.widgets;
|
|
169
|
+
const dataTable = []
|
|
170
|
+
const nots = Util.nots;
|
|
171
|
+
const reqfiles = req.files;
|
|
172
|
+
if (postTableData.length) {
|
|
173
|
+
for (let i = 0; i < postTableData.length; i++) {
|
|
174
|
+
let item = postTableData[i];
|
|
175
|
+
for (const k in widgetTables) {
|
|
176
|
+
if (!Util.in_array(k, nots)) {
|
|
177
|
+
if (widgetTables[k].name == "number") {
|
|
178
|
+
item[k] = Util.toNumber(item[k]);
|
|
179
|
+
}
|
|
180
|
+
if (widgetTables[k].name == "file" || widgetTables[k].name == "image") {
|
|
181
|
+
var fileImageName = `${MYMODEL.table}[${key}][${i}][${k}]`;
|
|
182
|
+
if (reqfiles && Object.hasOwn(reqfiles, fileImageName)) {
|
|
183
|
+
var kname = Util.generateUnique(5) + "_" + req.files[fileImageName].name;
|
|
184
|
+
item[k] = kname;
|
|
185
|
+
req.files[fileImageName].mv(path_tmp + key + "/" + kname, function (err) {
|
|
186
|
+
if (err) {
|
|
187
|
+
return res.status(500).send(err);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
post[routeName][key] = JSON.stringify(postTableData);
|
|
197
|
+
break;
|
|
198
|
+
|
|
199
|
+
case "multi_line_editor" :
|
|
200
|
+
post[routeName][key] = JSON.stringify(post[routeName][key]);
|
|
201
|
+
break;
|
|
202
|
+
|
|
203
|
+
case "relation" :
|
|
204
|
+
post[routeName][key] = val ? val : null;
|
|
205
|
+
break;
|
|
206
|
+
|
|
207
|
+
case "typeahead" :
|
|
208
|
+
post[routeName][key] = val ? val : null;
|
|
209
|
+
break;
|
|
210
|
+
|
|
211
|
+
case "datepicker" :
|
|
212
|
+
post[routeName][key] = val ? val : null;
|
|
213
|
+
break;
|
|
214
|
+
|
|
215
|
+
case "datetime" :
|
|
216
|
+
val = post[routeName][key];
|
|
217
|
+
post[routeName][key] = val ? val : null;
|
|
218
|
+
break;
|
|
219
|
+
|
|
220
|
+
case "integer" :
|
|
221
|
+
if (typeof val == "string") {
|
|
222
|
+
const onlyNumbers = val.replace(/\D/g, '');
|
|
223
|
+
val = parseInt(onlyNumbers);
|
|
224
|
+
}
|
|
225
|
+
post[routeName][key] = val ? val : null;
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
//check if widget have a tag default null
|
|
230
|
+
for (let key in widgets) {
|
|
231
|
+
if (widgets[key].name == "tags") {
|
|
232
|
+
if (!tags.includes(key)) {
|
|
233
|
+
post[routeName][key] = null;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
if (widgets[key].name == "table") {
|
|
237
|
+
if (!post[routeName][key]) {
|
|
238
|
+
post[routeName][key] = null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
return post;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
zRoute.attributeData = async (res, MYMODEL, obj) => {
|
|
246
|
+
obj = obj || null;
|
|
247
|
+
const userId = res.locals.userId || 0;
|
|
248
|
+
const routeName = MYMODEL.routeName;
|
|
249
|
+
let attributeData, labels, visibles, invisibles, filter;
|
|
250
|
+
attributeData = MYMODEL;
|
|
251
|
+
const zgrid = await connection.results({
|
|
252
|
+
table: 'zgrid',
|
|
253
|
+
where: {user_id: userId, route_name: routeName}
|
|
254
|
+
});
|
|
255
|
+
if (zgrid.length) {
|
|
256
|
+
visibles = zgrid[0].visibles ? zgrid[0].visibles : MYMODEL.grids.visibles;
|
|
257
|
+
invisibles = zgrid[0].invisibles ? zgrid[0].invisibles : MYMODEL.grids.invisibles;
|
|
258
|
+
filter = zgrid[0].filter ? zgrid[0].filter : null;
|
|
259
|
+
} else {
|
|
260
|
+
visibles = MYMODEL.grids.visibles;
|
|
261
|
+
invisibles = MYMODEL.grids.invisibles;
|
|
262
|
+
filter = null;
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
attributeData.labels = MYMODEL.labels;
|
|
266
|
+
|
|
267
|
+
res.locals.routeName = routeName;
|
|
268
|
+
res.locals.attributeData = attributeData;
|
|
269
|
+
res.locals.visibles = visibles;
|
|
270
|
+
res.locals.invisibles = invisibles;
|
|
271
|
+
res.locals.gridFilter = filter;
|
|
272
|
+
res.locals.visiblesObj = visibles.reduce((result, item) => {
|
|
273
|
+
return {...result, [item]: MYMODEL.labels[item]}
|
|
274
|
+
}, {});
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
/*
|
|
279
|
+
For ajax purpose
|
|
280
|
+
*/
|
|
281
|
+
zRoute.ajax = async (req, res) => {
|
|
282
|
+
let body = req.body;
|
|
283
|
+
let table = body.table;
|
|
284
|
+
let type = body.type;
|
|
285
|
+
let results;
|
|
286
|
+
let obj = {
|
|
287
|
+
table: table
|
|
288
|
+
};
|
|
289
|
+
if (body.where) {
|
|
290
|
+
obj.where = body.where;
|
|
291
|
+
}
|
|
292
|
+
if (body.data) {
|
|
293
|
+
obj.data = body.data;
|
|
294
|
+
}
|
|
295
|
+
if (!table) {
|
|
296
|
+
io.to(res.locals.token).emit("error", "table must be set");
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
if (!type) {
|
|
300
|
+
io.to(res.locals.token).emit("error", "type must be set, select insert update or delete");
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
let params = roles[res.locals.roleId].params;
|
|
304
|
+
if (!params.hasOwnProperty(table)) {
|
|
305
|
+
io.to(res.locals.token).emit("error", "You have no access to this page");
|
|
306
|
+
}
|
|
307
|
+
let MYMODEL = require(`./../models/${table}`);
|
|
308
|
+
if (type == "select") {
|
|
309
|
+
if (params[table].includes("index")) {
|
|
310
|
+
results = await connection.results(obj)
|
|
311
|
+
} else {
|
|
312
|
+
io.to(res.locals.token).emit("error", "You have no access to this page");
|
|
313
|
+
}
|
|
314
|
+
} else if (type == "update") {
|
|
315
|
+
if (params[table].includes("update")) {
|
|
316
|
+
results = await connection.update(obj)
|
|
317
|
+
} else {
|
|
318
|
+
io.to(res.locals.token).emit("error", "You have no access to this page");
|
|
319
|
+
}
|
|
320
|
+
} else if (type == "insert") {
|
|
321
|
+
if (params[table].includes("create")) {
|
|
322
|
+
results = await connection.insert(obj);
|
|
323
|
+
} else {
|
|
324
|
+
io.to(res.locals.token).emit("error", "You have no access to this page");
|
|
325
|
+
}
|
|
326
|
+
} else if (type == "delete") {
|
|
327
|
+
if (params[table].includes("delete")) {
|
|
328
|
+
results = await connection.delete(obj)
|
|
329
|
+
} else {
|
|
330
|
+
io.to(res.locals.token).emit("error", "You have no access to this page");
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
res.json({
|
|
334
|
+
results: results,
|
|
335
|
+
MYMODEL: MYMODEL
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
zRoute.validator = function (datas, MYMODEL) {
|
|
340
|
+
let obj = MYMODEL.fields;
|
|
341
|
+
let labels = MYMODEL.labels;
|
|
342
|
+
let fields = Util.requiredFields(obj);
|
|
343
|
+
let message = "";
|
|
344
|
+
let status = 1;
|
|
345
|
+
let field = "";
|
|
346
|
+
fields.map((item) => {
|
|
347
|
+
if (datas.hasOwnProperty(item)) {
|
|
348
|
+
if (!datas[item] || datas[item] == "") {
|
|
349
|
+
status = 0;
|
|
350
|
+
field = item;
|
|
351
|
+
message = Util.jsonError(item, labels[item] + " " + LANGUAGE.form_not_empty);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
});
|
|
355
|
+
let widgets = MYMODEL.widgets;
|
|
356
|
+
let numbers = [];
|
|
357
|
+
for (let key in widgets) {
|
|
358
|
+
if (widgets[key].name == "number") {
|
|
359
|
+
numbers.push(key);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (numbers.length) {
|
|
363
|
+
for (let key in datas) {
|
|
364
|
+
if (Util.in_array(key, numbers)) {
|
|
365
|
+
datas[key] = Util.replaceAll("" + datas[key], ".", "");
|
|
366
|
+
datas[key] = parseFloat(datas[key]) || 0;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return {
|
|
371
|
+
status: status,
|
|
372
|
+
message: message,
|
|
373
|
+
field: field
|
|
374
|
+
};
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
zRoute.selectData = (MYMODEL) => {
|
|
378
|
+
let widgets = MYMODEL.widgets;
|
|
379
|
+
let arr = [];
|
|
380
|
+
let data = '*';
|
|
381
|
+
for (let key in widgets) {
|
|
382
|
+
if (widgets[key].name == 'virtual') {
|
|
383
|
+
arr.push(widgets[key].fields);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (arr.length) {
|
|
387
|
+
data += ',';
|
|
388
|
+
data += arr.join(',');
|
|
389
|
+
}
|
|
390
|
+
return data;
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
zRoute.relations = async (req, res, table) => {
|
|
394
|
+
try {
|
|
395
|
+
const MYMODEL = require("./../models/" + table);
|
|
396
|
+
let relations = {}
|
|
397
|
+
relations["zattributes"] = {}
|
|
398
|
+
relations["zvirtuals"] = {}
|
|
399
|
+
let typeahead = {}
|
|
400
|
+
let hasAttributes = false;
|
|
401
|
+
let zattributes = {};
|
|
402
|
+
let company_id = res.locals.companyId;
|
|
403
|
+
//f0r widgets
|
|
404
|
+
for (let key in MYMODEL.widgets) {
|
|
405
|
+
const keyRow = key + "Row";
|
|
406
|
+
const keyFields = key + "Fields";
|
|
407
|
+
const keyObject = key + "Object";
|
|
408
|
+
const widget = MYMODEL.widgets[key];
|
|
409
|
+
const widgetName = MYMODEL.widgets[key].name;
|
|
410
|
+
let emptyArray = Util.arrayUnShift(['id', 'zname']);
|
|
411
|
+
|
|
412
|
+
if (widgetName == "dropdown_multi") {
|
|
413
|
+
let obj = {
|
|
414
|
+
select: widget.fields.join(",") + " as zname ",
|
|
415
|
+
table: widget.table,
|
|
416
|
+
where: {company_id: company_id},
|
|
417
|
+
orderBy: ['zname', 'asc']
|
|
418
|
+
};
|
|
419
|
+
if (Util.in_array(widget.table, zRoute.tableHasNoCompanyId)) {
|
|
420
|
+
delete obj.where;
|
|
421
|
+
}
|
|
422
|
+
const cacheKey = `${obj.table}_${widget.table}___${key}_${company_id}`;
|
|
423
|
+
let results = {};
|
|
424
|
+
if (myCache.has(cacheKey)) {
|
|
425
|
+
results = myCache.get(cacheKey);
|
|
426
|
+
} else {
|
|
427
|
+
results = await connection.results(obj);
|
|
428
|
+
}
|
|
429
|
+
relations[key] = [Util.arrayUnShift(['id', 'zname']), ...results];
|
|
430
|
+
relations[keyObject] = Util.arrayWithObject(relations[key], 'id', 'zname');
|
|
431
|
+
} else if (widgetName == "table") {
|
|
432
|
+
let MODEL_TABLE = require(`./../models/${widget.table}`);
|
|
433
|
+
let nots = [...CONFIG.generator.notRenderField, ...['no', 'actionColumn']];
|
|
434
|
+
let obj = {}
|
|
435
|
+
let visibles = MODEL_TABLE.grids.visibles;
|
|
436
|
+
let invisibles = MODEL_TABLE.grids.invisibles;
|
|
437
|
+
let properties = {}
|
|
438
|
+
visibles.forEach(function (item) {
|
|
439
|
+
if (!Util.in_array(item, nots)) {
|
|
440
|
+
obj[item] = MODEL_TABLE.labels[item];
|
|
441
|
+
properties[item] = MODEL_TABLE.widgets[item]
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
invisibles.forEach(function (item) {
|
|
445
|
+
if (!Util.in_array(item, nots)) {
|
|
446
|
+
obj[item] = MODEL_TABLE.labels[item];
|
|
447
|
+
properties[item] = MODEL_TABLE.widgets[item]
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
relations[key] = obj;
|
|
451
|
+
relations[`properties_${key}`] = properties;
|
|
452
|
+
relations[keyRow] = await zRoute.relations(req, res, widget.table);
|
|
453
|
+
relations[key + "Table"] = widget.table;
|
|
454
|
+
//let MODEL_TABLE = require("./../models/" + MYMODEL.widgets[key].table);
|
|
455
|
+
relations[key + "TABLE"] = await zRoute.relations(req, res, MODEL_TABLE.table);
|
|
456
|
+
|
|
457
|
+
} else if (widgetName == "multi_line_editor") {
|
|
458
|
+
let MODEL_TABLE = require(`./../models/${widget.table}`);
|
|
459
|
+
relations[keyFields] = MYMODEL.widgets[key].fields;
|
|
460
|
+
relations[key] = await zRoute.relations(req, res, widget.table);
|
|
461
|
+
|
|
462
|
+
} else if (widgetName == "select") {
|
|
463
|
+
relations[key] = widget.fields;
|
|
464
|
+
relations[key + "Array"] = widget.array;
|
|
465
|
+
relations[keyFields] = widget.fields;
|
|
466
|
+
relations[keyObject] = Util.objectToGridFormat(relations[key], true);
|
|
467
|
+
|
|
468
|
+
} else if (widgetName == "radio") {
|
|
469
|
+
relations[key] = widget.fields;
|
|
470
|
+
relations[key + "Array"] = widget.array;
|
|
471
|
+
relations[keyFields] = widget.fields;
|
|
472
|
+
relations[keyObject] = Util.objectToGridFormat(relations[key], true);
|
|
473
|
+
|
|
474
|
+
} else if (widgetName == "relation") {
|
|
475
|
+
let select = widget.fields.join(",") + " as zname ";
|
|
476
|
+
let obj = {
|
|
477
|
+
select: select,
|
|
478
|
+
table: widget.table,
|
|
479
|
+
where: {company_id: company_id},
|
|
480
|
+
orderBy : ['zname', 'asc']
|
|
481
|
+
};
|
|
482
|
+
if (Util.in_array(widget.table, zRoute.tableHasNoCompanyId)) {
|
|
483
|
+
delete obj.where;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (widget.hasOwnProperty("please_select")) {
|
|
487
|
+
if (widget.please_select != undefined) {
|
|
488
|
+
if (widget.please_select != "") {
|
|
489
|
+
emptyArray = {
|
|
490
|
+
'id': '',
|
|
491
|
+
'zname': widget.please_select
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
let cacheKey = `${widget.table}_${MYMODEL.table}___${key}_${company_id}`;
|
|
497
|
+
if(key == 'created_by' || key == 'updated_by') {
|
|
498
|
+
cacheKey = `zuser_${key}_${company_id}`;
|
|
499
|
+
}
|
|
500
|
+
let results;
|
|
501
|
+
if (myCache.has(cacheKey)) {
|
|
502
|
+
results = myCache.get(cacheKey);
|
|
503
|
+
} else {
|
|
504
|
+
results = await connection.results(obj);
|
|
505
|
+
}
|
|
506
|
+
relations[key] = [emptyArray, ...results];
|
|
507
|
+
relations[keyFields] = widget.fields;
|
|
508
|
+
relations[keyObject] = Util.arrayWithObject(relations[key], 'id', 'zname');
|
|
509
|
+
if (widget.isAttributes) {
|
|
510
|
+
zattributes[key] = Util.arrayToObject(results, "id");
|
|
511
|
+
hasAttributes = true;
|
|
512
|
+
}
|
|
513
|
+
} else if (widgetName == "dropdown_chain") {
|
|
514
|
+
const obj = {
|
|
515
|
+
select: widget.fields.join(",") + " as zname ",
|
|
516
|
+
table: widget.table,
|
|
517
|
+
where: {company_id: company_id},
|
|
518
|
+
orderBy: ['id', 'asc']
|
|
519
|
+
};
|
|
520
|
+
if (Util.in_array(widget.table, zRoute.tableHasNoCompanyId)) {
|
|
521
|
+
delete obj.where;
|
|
522
|
+
}
|
|
523
|
+
const cacheKey = `${widget.table}_${MYMODEL.table}___${key}_${company_id}`;
|
|
524
|
+
let results;
|
|
525
|
+
if (myCache.has(cacheKey)) {
|
|
526
|
+
results = myCache.get(cacheKey);
|
|
527
|
+
} else {
|
|
528
|
+
results = await connection.results(obj);
|
|
529
|
+
}
|
|
530
|
+
relations[key] = [Util.arrayUnShift(['id', 'zname']), ...results];
|
|
531
|
+
relations[keyFields] = widget.fields;
|
|
532
|
+
relations[keyObject] = Util.arrayWithObject(relations[key], 'id', 'zname');
|
|
533
|
+
} else if (widgetName == "typeahead") {
|
|
534
|
+
let select = widget.fields.join(",") + " as zname ";
|
|
535
|
+
let obj = {
|
|
536
|
+
select: select,
|
|
537
|
+
table: widget.table,
|
|
538
|
+
where: {company_id: company_id},
|
|
539
|
+
orderBy: ['zname', 'asc']
|
|
540
|
+
};
|
|
541
|
+
if (Util.in_array(widget.table, zRoute.tableHasNoCompanyId)) {
|
|
542
|
+
delete obj.where;
|
|
543
|
+
}
|
|
544
|
+
const cacheKey = `${widget.table}_${MYMODEL.table}___${key}_${company_id}`;
|
|
545
|
+
let results;
|
|
546
|
+
if (myCache.has(cacheKey)) {
|
|
547
|
+
results = myCache.get(cacheKey);
|
|
548
|
+
} else {
|
|
549
|
+
results = await connection.results(obj);
|
|
550
|
+
}
|
|
551
|
+
relations[key] = [Util.arrayUnShift(['id', 'zname']), ...results];
|
|
552
|
+
relations[keyObject] = Util.arrayWithObject(relations[key], 'id', 'zname');
|
|
553
|
+
relations[keyFields] = widget.fields;
|
|
554
|
+
|
|
555
|
+
} else if (widgetName == "switch") {
|
|
556
|
+
relations[key] = Util.modulesSwitch(widget.fields);
|
|
557
|
+
relations[keyFields] = widget.fields;
|
|
558
|
+
|
|
559
|
+
} else if (widgetName == "virtual") {
|
|
560
|
+
relations["zvirtuals"][key] = widget.fields;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
let selectZvirtuals = "";
|
|
565
|
+
for (let key in relations["zvirtuals"]) {
|
|
566
|
+
selectZvirtuals += `${relations['zvirtuals'][key]} , `
|
|
567
|
+
}
|
|
568
|
+
if (selectZvirtuals) {
|
|
569
|
+
relations.selectZvirtuals = selectZvirtuals;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
return relations;
|
|
573
|
+
} catch (err) {
|
|
574
|
+
debug(req, res, err);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
/*
|
|
579
|
+
Function to create filter elements on data table grid
|
|
580
|
+
*/
|
|
581
|
+
|
|
582
|
+
zRoute.dataTableFilterSync = async (req, res, MYMODEL, filter) => {
|
|
583
|
+
const relations = await zRoute.relations(req, res, MYMODEL.table);
|
|
584
|
+
const dataTable = zRoute.dataTableFilter(MYMODEL, relations, filter);
|
|
585
|
+
return dataTable;
|
|
586
|
+
};
|
|
587
|
+
|
|
588
|
+
zRoute.dataTableFilter = (MYMODEL, relations, filter) => {
|
|
589
|
+
filter = filter || {}
|
|
590
|
+
let filterColumns = filter.hasOwnProperty("columns") ? filter.columns : [];
|
|
591
|
+
let filterObject = {}
|
|
592
|
+
let filterKey = '';
|
|
593
|
+
let isFilter = false;
|
|
594
|
+
filterColumns.forEach(function (item) {
|
|
595
|
+
var value = item.search.value
|
|
596
|
+
if (value) {
|
|
597
|
+
filterKey += ` $("#data_table_${filter.fields[item.data]}").change(); `
|
|
598
|
+
filterObject[filter.fields[item.data]] = Util.replaceAll(value, "%", "");
|
|
599
|
+
isFilter = true;
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
if (isFilter) {
|
|
603
|
+
filterKey += ` $("select[name='dataTable_length']").val(${filter.length}); $("select[name='dataTable_length']").change(); `
|
|
604
|
+
}
|
|
605
|
+
let fields = MYMODEL.fields;
|
|
606
|
+
let widgets = MYMODEL.widgets;
|
|
607
|
+
let types = {}
|
|
608
|
+
let dataTable = {};
|
|
609
|
+
let options;
|
|
610
|
+
for (let key in fields) {
|
|
611
|
+
let html = '';
|
|
612
|
+
const value = filterObject.hasOwnProperty(key) ? filterObject[key] : "";
|
|
613
|
+
if (key == "id") {
|
|
614
|
+
types[key] = 'input';
|
|
615
|
+
dataTable[key] = `<input type="number" placeholder="${fields[key].title}" value="${value}" id="data_table_${key}" >`;
|
|
616
|
+
} else {
|
|
617
|
+
if (widgets.hasOwnProperty(key)) {
|
|
618
|
+
const widgetName = widgets[key].name;
|
|
619
|
+
switch (widgetName) {
|
|
620
|
+
case "switch" :
|
|
621
|
+
options = relations[key].reduce((result, item) => {
|
|
622
|
+
var selected = value === item.id ? " selected " : "";
|
|
623
|
+
return result + `<option value="${item.id}" ${selected}>${item.name}</option>`
|
|
624
|
+
}, "");
|
|
625
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select" >${options}</select>`;
|
|
626
|
+
types[key] = 'select';
|
|
627
|
+
break;
|
|
628
|
+
|
|
629
|
+
case "color" :
|
|
630
|
+
dataTable[key] = `<input type="color" class="form-control form-control-color" value="${value}" id="data_table_${key}" >`;
|
|
631
|
+
types[key] = 'input';
|
|
632
|
+
break;
|
|
633
|
+
|
|
634
|
+
case "relation" :
|
|
635
|
+
options = relations[key].reduce((result, item) => {
|
|
636
|
+
var selected = value === item.id ? " selected " : "";
|
|
637
|
+
return result + `<option value="${item.id}" ${selected}>${item.zname}</option>`
|
|
638
|
+
}, "");
|
|
639
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select " >${options}</select>`;
|
|
640
|
+
types[key] = 'select';
|
|
641
|
+
break;
|
|
642
|
+
|
|
643
|
+
case "dropdown_multi" :
|
|
644
|
+
options = relations[key].reduce((result, item) => {
|
|
645
|
+
var selected = value == item.id ? " selected " : "";
|
|
646
|
+
return result + `<option value="${item.id}" ${selected} >${item.zname}</option>`
|
|
647
|
+
}, "");
|
|
648
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select " >${options}</select>`;
|
|
649
|
+
types[key] = 'select';
|
|
650
|
+
break;
|
|
651
|
+
|
|
652
|
+
case "dropdown_chain" :
|
|
653
|
+
options = relations[key].reduce((result, item) => {
|
|
654
|
+
var selected = value == item.id ? " selected " : "";
|
|
655
|
+
return result + `<option value="${item.id}" ${selected}>${item.zname}</option>`
|
|
656
|
+
}, "");
|
|
657
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select " >${options}</select>`;
|
|
658
|
+
types[key] = 'select';
|
|
659
|
+
break;
|
|
660
|
+
|
|
661
|
+
case "select" :
|
|
662
|
+
let please_select = widgets[key].please_select;
|
|
663
|
+
options = `<option value=""> </option>`;
|
|
664
|
+
if (please_select != undefined) {
|
|
665
|
+
if (please_select != "") {
|
|
666
|
+
options = `<option value="">${please_select}</option>`;
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
for (var k in relations[key]) {
|
|
670
|
+
const selected = value === k ? " selected " : "";
|
|
671
|
+
options += `<option value="${k}" ${selected}>${relations[key][k]}</option>`;
|
|
672
|
+
}
|
|
673
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select " >${options}</select>`;
|
|
674
|
+
types[key] = 'select';
|
|
675
|
+
break;
|
|
676
|
+
|
|
677
|
+
case "radio" :
|
|
678
|
+
options = `<option value=""> </option>`;
|
|
679
|
+
var items = relations[key + "Array"] || [];
|
|
680
|
+
if (items) {
|
|
681
|
+
items.forEach(function (item) {
|
|
682
|
+
let selected = item.value == value ? ' selected ' : '';
|
|
683
|
+
options += `<option value="${item.value}" ${selected}>${item.label}</option>`;
|
|
684
|
+
});
|
|
685
|
+
} else {
|
|
686
|
+
for (var k in relations[key]) {
|
|
687
|
+
let selected = value === k ? " selected " : "";
|
|
688
|
+
options += `<option value="${k}" ${selected}>${relations[key][k]}</option>`;
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select " >${options}</select>`;
|
|
692
|
+
types[key] = 'select';
|
|
693
|
+
break;
|
|
694
|
+
|
|
695
|
+
case "typeahead" :
|
|
696
|
+
options = relations[key].reduce((result, item) => {
|
|
697
|
+
var selected = value === item.id ? " selected " : "";
|
|
698
|
+
return result + `<option value="${item.id}" ${selected}>${item.zname}</option>`
|
|
699
|
+
}, "");
|
|
700
|
+
dataTable[key] = `<select id="data_table_${key}" class="form-control form-select " >${options}</select>`;
|
|
701
|
+
types[key] = 'select';
|
|
702
|
+
break;
|
|
703
|
+
|
|
704
|
+
case "number" :
|
|
705
|
+
dataTable[key] = `<input type="text" class="form-control " value="${value}" id="data_table_${key}" >`;
|
|
706
|
+
types[key] = 'input';
|
|
707
|
+
break;
|
|
708
|
+
|
|
709
|
+
case "integer" :
|
|
710
|
+
dataTable[key] = `<input type="number" class="form-control " value="${value}" id="data_table_${key}" >`;
|
|
711
|
+
types[key] = 'input';
|
|
712
|
+
break;
|
|
713
|
+
|
|
714
|
+
/*case "json" :
|
|
715
|
+
dataTable[key] = `<input type="number" class="form-control form-control-sm" value="${value}" id="data_table_${key}" >`;
|
|
716
|
+
types[key] = 'input';
|
|
717
|
+
break;*/
|
|
718
|
+
|
|
719
|
+
case "virtual" :
|
|
720
|
+
dataTable[key] = ``;
|
|
721
|
+
break;
|
|
722
|
+
|
|
723
|
+
default :
|
|
724
|
+
dataTable[key] = `<input type="text" class="form-control " value="${value}" id="data_table_${key}" >`;
|
|
725
|
+
types[key] = 'input';
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
} else {
|
|
729
|
+
dataTable[key] = ``;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
dataTable.MYMODEL = MYMODEL;
|
|
735
|
+
dataTable.RELATIONS = relations;
|
|
736
|
+
dataTable.TYPES = types;
|
|
737
|
+
dataTable.FILTER = filter;
|
|
738
|
+
dataTable.FILTEROBJECT = filterObject;
|
|
739
|
+
dataTable.FILTERKEY = filterKey;
|
|
740
|
+
return dataTable;
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
zRoute.dataTableData = (key, value, MYMODEL, relations) => {
|
|
744
|
+
relations = relations || {}
|
|
745
|
+
var keyFields = key + "Fields";
|
|
746
|
+
var keyObject = key + "Object";
|
|
747
|
+
let myvalue = value;
|
|
748
|
+
var widgetName = MYMODEL.widgets[key] ? MYMODEL.widgets[key].name : "";
|
|
749
|
+
if (widgetName) {
|
|
750
|
+
switch (widgetName) {
|
|
751
|
+
case "switch" :
|
|
752
|
+
myvalue = relations[keyFields][value] || "";
|
|
753
|
+
break;
|
|
754
|
+
|
|
755
|
+
case "color" :
|
|
756
|
+
myvalue = `<input type="color" value="${value}">`;
|
|
757
|
+
break;
|
|
758
|
+
|
|
759
|
+
case "relation" :
|
|
760
|
+
myvalue = relations[keyObject][value] || "";
|
|
761
|
+
break;
|
|
762
|
+
|
|
763
|
+
case "dropdown_multi" :
|
|
764
|
+
let arr = value ? value : [];
|
|
765
|
+
if (arr.length) {
|
|
766
|
+
let myarr = [];
|
|
767
|
+
arr.forEach(function (item) {
|
|
768
|
+
myarr.push(relations[keyObject][item]);
|
|
769
|
+
});
|
|
770
|
+
myvalue = myarr.length ? myarr.join(", ") : "";
|
|
771
|
+
}
|
|
772
|
+
break;
|
|
773
|
+
|
|
774
|
+
case "dropdown_chain" :
|
|
775
|
+
myvalue = relations[key][value] || "";
|
|
776
|
+
break;
|
|
777
|
+
|
|
778
|
+
case "select" :
|
|
779
|
+
myvalue = relations[keyFields][value] || "";
|
|
780
|
+
break;
|
|
781
|
+
|
|
782
|
+
case "radio" :
|
|
783
|
+
myvalue = relations[keyFields][value] || "";
|
|
784
|
+
break;
|
|
785
|
+
|
|
786
|
+
case "typeahead" :
|
|
787
|
+
myvalue = relations[keyObject][value] || "";
|
|
788
|
+
break;
|
|
789
|
+
|
|
790
|
+
case "datetime" :
|
|
791
|
+
myvalue = Util.timeSql(value);
|
|
792
|
+
break;
|
|
793
|
+
|
|
794
|
+
case "datepicker" :
|
|
795
|
+
myvalue = Util.dateFormat(value, MYMODEL.widgets[key].format);
|
|
796
|
+
break;
|
|
797
|
+
|
|
798
|
+
case "number" :
|
|
799
|
+
myvalue = Util.formatNumber(value);
|
|
800
|
+
break;
|
|
801
|
+
|
|
802
|
+
case "integer" :
|
|
803
|
+
myvalue = parseInt(value);
|
|
804
|
+
break;
|
|
805
|
+
|
|
806
|
+
case "image" :
|
|
807
|
+
myvalue = Util.fileView("/uploads/" + MYMODEL.routeName + "/", value);
|
|
808
|
+
break;
|
|
809
|
+
|
|
810
|
+
case "file" :
|
|
811
|
+
myvalue = Util.fileView("/uploads/" + MYMODEL.routeName + "/", value);
|
|
812
|
+
break;
|
|
813
|
+
|
|
814
|
+
case "password" :
|
|
815
|
+
myvalue = "xxxxxx";
|
|
816
|
+
break;
|
|
817
|
+
|
|
818
|
+
case "json" :
|
|
819
|
+
myvalue = value ? JSON.stringify(value).replaceAll('","', '", "') : '';
|
|
820
|
+
break;
|
|
821
|
+
|
|
822
|
+
default :
|
|
823
|
+
value = value || "";
|
|
824
|
+
myvalue = value.length > 50 ? value.substring(0, 50) : value;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return myvalue;
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
zRoute.users = async (req) => {
|
|
831
|
+
if (!Object.prototype.hasOwnProperty.call(req.session, "user")) {
|
|
832
|
+
return [];
|
|
833
|
+
} else {
|
|
834
|
+
return await connection.query('SELECT zuser.id, zuser.fullname as zname FROM zuser LEFT JOIN zuser ON (zuser.id = zuser_company.user_id) WHERE zuser_company.company_id = ?', [req.session.user.company_id]);
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
zRoute.usersObj = {id: '', fullname: ''};
|
|
839
|
+
zRoute.usersArr = ['id', 'fullname'];
|
|
840
|
+
zRoute.usersDropdown = async (req) => {
|
|
841
|
+
return [zRoute.usersObj, ...await zRoute.users(req)];
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
zRoute.getUsers = async () => {
|
|
845
|
+
return Util.arrayToObject(await connection.results({table: "zuser"}), "id");
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
zRoute.changePassword = async (req, res) => {
|
|
849
|
+
let userId = req.session.user.id;
|
|
850
|
+
let query = req.body;
|
|
851
|
+
let passwordNow = query.passwordNow.trim();
|
|
852
|
+
let password = query.password.trim();
|
|
853
|
+
let passwordRepeat = query.passwordRepeat.trim();
|
|
854
|
+
let password_pattern = Util.regexPassword(6, 20)
|
|
855
|
+
if (!password.match(password_pattern)) {
|
|
856
|
+
return res.json(Util.jsonError('password', LANGUAGE.password_combine))
|
|
857
|
+
}
|
|
858
|
+
if (password != passwordRepeat) {
|
|
859
|
+
return res.json(Util.jsonError('password', LANGUAGE.password_equal))
|
|
860
|
+
}
|
|
861
|
+
let user = await connection.results({
|
|
862
|
+
table: "zuser",
|
|
863
|
+
where: {
|
|
864
|
+
id: userId,
|
|
865
|
+
password: Util.hash(passwordNow)
|
|
866
|
+
}
|
|
867
|
+
});
|
|
868
|
+
if (user.length == 0) {
|
|
869
|
+
return res.json(Util.jsonError('passwordNow', LANGUAGE.password_wrong))
|
|
870
|
+
}
|
|
871
|
+
let data = {
|
|
872
|
+
password: Util.hash(password)
|
|
873
|
+
};
|
|
874
|
+
await connection.update({
|
|
875
|
+
table: "zuser",
|
|
876
|
+
where: {
|
|
877
|
+
id: userId
|
|
878
|
+
},
|
|
879
|
+
data: data
|
|
880
|
+
});
|
|
881
|
+
res.json(Util.jsonSuccess(LANGUAGE.change_password_success))
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
zRoute.resetPassword = async (req, res) => {
|
|
885
|
+
let query = req.body;
|
|
886
|
+
let password = query.password;
|
|
887
|
+
let password_repeat = query.password_repeat.trim();
|
|
888
|
+
let password_pattern = Util.regexPassword(6, 20)
|
|
889
|
+
let forgot_password = req.params.forgot_password || "";
|
|
890
|
+
let json = Util.jsonError('password', LANGUAGE.link_expired);
|
|
891
|
+
if (forgot_password == "")
|
|
892
|
+
return res.json(Util.jsonError('password', LANGUAGE.link_expired))
|
|
893
|
+
if (!password.match(password_pattern))
|
|
894
|
+
return res.json(Util.jsonError('password', LANGUAGE.password_combine))
|
|
895
|
+
if (password != password_repeat)
|
|
896
|
+
return res.json(Util.jsonError('password', LANGUAGE.password_equal))
|
|
897
|
+
|
|
898
|
+
const results = await connection.results({
|
|
899
|
+
table: "zuser",
|
|
900
|
+
where: {
|
|
901
|
+
forgot_password: forgot_password
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
if (results.length > 0) {
|
|
905
|
+
await connection.update({
|
|
906
|
+
table: "zuser",
|
|
907
|
+
data: {
|
|
908
|
+
password: Util.hash(password),
|
|
909
|
+
forgot_password: ""
|
|
910
|
+
},
|
|
911
|
+
where: {
|
|
912
|
+
id: results[0].id
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
req.session.sessionFlash = Util.jsonSuccess(LANGUAGE.change_password_success);
|
|
916
|
+
json = Util.jsonSuccess(LANGUAGE.success)
|
|
917
|
+
} else {
|
|
918
|
+
json = Util.jsonError('password', LANGUAGE.link_expired)
|
|
919
|
+
}
|
|
920
|
+
res.json(json);
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
zRoute.loginAuth = async (username, fields) => {
|
|
924
|
+
let results = await connection.results({table: "zuser", where: {username: username}});
|
|
925
|
+
if (results.length) {
|
|
926
|
+
await connection.update({table: "zuser", data: fields, where: {id: results[0].id}});
|
|
927
|
+
//back to query to completed
|
|
928
|
+
results = await connection.results({table: "zuser", where: {id: results[0].id}})
|
|
929
|
+
}
|
|
930
|
+
return results;
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
zRoute.loginNormal = async (username, password) => {
|
|
934
|
+
let result = await connection.result({
|
|
935
|
+
table: "zuser",
|
|
936
|
+
where: {username: username}
|
|
937
|
+
});
|
|
938
|
+
if (!result) {
|
|
939
|
+
return [];
|
|
940
|
+
} else {
|
|
941
|
+
const match = Util.hashCompare(password, result.password);
|
|
942
|
+
if (match) {
|
|
943
|
+
return [result];
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
return [];
|
|
947
|
+
};
|
|
948
|
+
|
|
949
|
+
zRoute.loginAjax = async (username, password, req, res, isSocialLogin, url = "") => {
|
|
950
|
+
let redirect = '';
|
|
951
|
+
let data = {
|
|
952
|
+
status: 0,
|
|
953
|
+
url: redirect
|
|
954
|
+
};
|
|
955
|
+
try {
|
|
956
|
+
isSocialLogin = isSocialLogin || false;
|
|
957
|
+
const rows = isSocialLogin ? await zRoute.loginAuth(username, password) : await zRoute.loginNormal(username, password);
|
|
958
|
+
if (rows.length > 0) {
|
|
959
|
+
if (rows[0].active == 1) {
|
|
960
|
+
await zRoute.handleSession(req, rows[0]);
|
|
961
|
+
redirect = url == "" ? `${process.env.APP_AFTER_LOGIN}` : url;
|
|
962
|
+
data = {
|
|
963
|
+
status: 1,
|
|
964
|
+
url: redirect
|
|
965
|
+
}
|
|
966
|
+
} else {
|
|
967
|
+
data = {
|
|
968
|
+
status: 2,
|
|
969
|
+
url: redirect
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
} catch (err) {
|
|
974
|
+
debug(req, res, err);
|
|
975
|
+
res.json("Error : " + err.toString());
|
|
976
|
+
}
|
|
977
|
+
return data;
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
zRoute.login = async (username, password, req, res, isSocialLogin, url = "") => {
|
|
981
|
+
isSocialLogin = isSocialLogin || false;
|
|
982
|
+
let data = await zRoute.loginAjax(username, password, req, res, isSocialLogin, url);
|
|
983
|
+
let redirect = data.url;
|
|
984
|
+
if (data.status == 1) {
|
|
985
|
+
res.redirect(redirect);
|
|
986
|
+
} else {
|
|
987
|
+
req.session.sessionFlashc = 1;
|
|
988
|
+
res.locals.sessionFlash = 1;
|
|
989
|
+
res.redirect(url == "" ? process.env.APP_AFTER_LOGIN : "/" + url);
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
|
|
993
|
+
zRoute.logout = async (req, res) => {
|
|
994
|
+
req.session.destroy(function (err) {
|
|
995
|
+
if (err) console.log('/logout err', err);
|
|
996
|
+
res.redirect(process.env.APP_AFTER_LOGOUT);
|
|
997
|
+
});
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
zRoute.handleSession = async (req, user) => {
|
|
1001
|
+
const company = await connection.result({
|
|
1002
|
+
table: "zcompany",
|
|
1003
|
+
where: {
|
|
1004
|
+
id: user.company_id
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
const userCompany = await connection.results({
|
|
1008
|
+
table: "zuser_company",
|
|
1009
|
+
joins: [
|
|
1010
|
+
"LEFT JOIN zcompany ON (zcompany.id = zuser_company.company_id)"
|
|
1011
|
+
],
|
|
1012
|
+
where: {
|
|
1013
|
+
"zuser_company.user_id": user.id
|
|
1014
|
+
}
|
|
1015
|
+
});
|
|
1016
|
+
|
|
1017
|
+
if (!userCompany.length) {
|
|
1018
|
+
req.session.user = {}
|
|
1019
|
+
} else {
|
|
1020
|
+
const userCompanyObject = Util.arrayToObject(userCompany, "company_id");
|
|
1021
|
+
const role = await connection.result({
|
|
1022
|
+
table: "zrole",
|
|
1023
|
+
where: {
|
|
1024
|
+
id: userCompanyObject[user.company_id].role_id
|
|
1025
|
+
}
|
|
1026
|
+
});
|
|
1027
|
+
user.roleName = role.name;
|
|
1028
|
+
let roleKeys = role.params ? role.params : {};
|
|
1029
|
+
user.roleKeys = Object.keys(roleKeys);
|
|
1030
|
+
user.company = company;
|
|
1031
|
+
user.companies = userCompany;
|
|
1032
|
+
req.session.user = user;
|
|
1033
|
+
}
|
|
1034
|
+
};
|
|
1035
|
+
|
|
1036
|
+
zRoute.excelQuery = async (req, res, MYMODEL) => {
|
|
1037
|
+
//check directory for import not export
|
|
1038
|
+
const dir = `${dirRoot}/public/excel/tmp`;
|
|
1039
|
+
if (!fs.existsSync(dir)) {
|
|
1040
|
+
fs.mkdirSync(dir);
|
|
1041
|
+
}
|
|
1042
|
+
//end
|
|
1043
|
+
let reqQuery = req.query;
|
|
1044
|
+
let zSearch = reqQuery.zsearch == 1 ? true : false;
|
|
1045
|
+
let zall = reqQuery.all == 1 ? true : false;
|
|
1046
|
+
let zstandart = reqQuery.zstandart == 1 ? true : false;
|
|
1047
|
+
await zRoute.attributeData(res, MYMODEL);
|
|
1048
|
+
const results = await connection.results({
|
|
1049
|
+
table: "zgrid",
|
|
1050
|
+
where: {
|
|
1051
|
+
route_name: MYMODEL.routeName,
|
|
1052
|
+
user_id: res.locals.userId
|
|
1053
|
+
}
|
|
1054
|
+
});
|
|
1055
|
+
let rows = [];
|
|
1056
|
+
let fields = [];
|
|
1057
|
+
let body = {};
|
|
1058
|
+
let select = "";
|
|
1059
|
+
let allfields = Object.keys(MYMODEL.widgets);
|
|
1060
|
+
if (results.length) {
|
|
1061
|
+
let result = results[0];
|
|
1062
|
+
body = result.filter;
|
|
1063
|
+
fields = body.fields.filter(item => item != "no" && item != "actionColumn");
|
|
1064
|
+
select = Util.selectMysql(fields);
|
|
1065
|
+
if (zall) {
|
|
1066
|
+
let difference = allfields.filter(x => !fields.includes(x));
|
|
1067
|
+
let arr = [...fields, ...difference];
|
|
1068
|
+
select = arr.join(",");
|
|
1069
|
+
}
|
|
1070
|
+
let whereArray = [];
|
|
1071
|
+
let columns = body.columns;
|
|
1072
|
+
columns.forEach(function (item) {
|
|
1073
|
+
if (item.search.value) {
|
|
1074
|
+
whereArray.push({
|
|
1075
|
+
field: body.fields[item.data],
|
|
1076
|
+
option: MYMODEL.options[body.fields[item.data]],
|
|
1077
|
+
value: item.search.value,
|
|
1078
|
+
operator: "AND"
|
|
1079
|
+
});
|
|
1080
|
+
}
|
|
1081
|
+
});
|
|
1082
|
+
const orderColumn = body.fields[body.order[0].column] == "actionColumn" ? "id" : body.fields[body.order[0].column] == "no" ? "id" : body.fields[body.order[0].column] == "actionColum" ? "id" : body.fields[body.order[0].column];
|
|
1083
|
+
if (zstandart) {
|
|
1084
|
+
select = "*";
|
|
1085
|
+
}
|
|
1086
|
+
const obj = {
|
|
1087
|
+
select: select,
|
|
1088
|
+
table: MYMODEL.table,
|
|
1089
|
+
whereArray: whereArray,
|
|
1090
|
+
/* limit: body.length,
|
|
1091
|
+
offset : body.start,*/
|
|
1092
|
+
orderBy: [orderColumn, body.order[0].dir]
|
|
1093
|
+
};
|
|
1094
|
+
if (!zall) {
|
|
1095
|
+
obj.limit = body.length;
|
|
1096
|
+
obj.offset = body.start;
|
|
1097
|
+
}
|
|
1098
|
+
rows = await connection.results(obj);
|
|
1099
|
+
} else {
|
|
1100
|
+
rows = await connection.results({
|
|
1101
|
+
select: Util.selectMysql(fields),
|
|
1102
|
+
table: MYMODEL.table,
|
|
1103
|
+
limit: reqQuery.pageSize,
|
|
1104
|
+
offset: parseInt(reqQuery.pageSize) - 1,
|
|
1105
|
+
orderBy: ["id", "desc"]
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
if (zall) {
|
|
1109
|
+
fields = select.split(",");
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
const ztype = reqQuery.ztype == 1 ? true : false;
|
|
1113
|
+
if (ztype) {
|
|
1114
|
+
await zRoute.pdf(req, res, MYMODEL, fields, rows);
|
|
1115
|
+
} else {
|
|
1116
|
+
await zRoute.excel(req, res, MYMODEL, fields, rows);
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
1119
|
+
|
|
1120
|
+
// for excels
|
|
1121
|
+
zRoute.excel = async (req, res, MYMODEL, fields, rows, callback, fileName) => {
|
|
1122
|
+
//if any other custom value then callback needed
|
|
1123
|
+
callback = callback || function () {};
|
|
1124
|
+
const Excel = require('exceljs');
|
|
1125
|
+
const workbook = new Excel.Workbook();
|
|
1126
|
+
let worksheet = workbook.addWorksheet(res.locals.routeName, {pageSetup: {paperSize: 9, orientation: 'landscape'}})
|
|
1127
|
+
worksheet.properties.defaultColWidth = 13;
|
|
1128
|
+
const params = req.query;
|
|
1129
|
+
const isRaws = params.zraws == 1 ? true : false;
|
|
1130
|
+
const sequence = Util.excelSequence();
|
|
1131
|
+
const labels = MYMODEL.labels;
|
|
1132
|
+
let start = 4, num = 1, routeName = res.locals.routeName;
|
|
1133
|
+
// properties
|
|
1134
|
+
const yellow = {
|
|
1135
|
+
type: 'pattern',
|
|
1136
|
+
pattern: 'solid',
|
|
1137
|
+
fgColor: {argb: 'FFFFFF00'},
|
|
1138
|
+
bgColor: {argb: 'FF0000FF'}
|
|
1139
|
+
};
|
|
1140
|
+
const blue = {
|
|
1141
|
+
type: 'pattern',
|
|
1142
|
+
pattern: 'solid',
|
|
1143
|
+
fgColor: {argb: '96C8FB'},
|
|
1144
|
+
bgColor: {argb: '96C8FB'}
|
|
1145
|
+
};
|
|
1146
|
+
const center = {vertical: 'middle', horizontal: 'center', wrapText: true};
|
|
1147
|
+
const bold = {bold: true};
|
|
1148
|
+
//end properties
|
|
1149
|
+
for (let i = 0; i < fields.length; i++) {
|
|
1150
|
+
worksheet.getCell(sequence[i] + '1').value = labels[fields[i]];
|
|
1151
|
+
worksheet.getCell(sequence[i] + '1').fill = blue;
|
|
1152
|
+
worksheet.getCell(sequence[i] + '1').font = bold;
|
|
1153
|
+
worksheet.getCell(sequence[i] + '1').alignment = center;
|
|
1154
|
+
}
|
|
1155
|
+
for (let i = 0; i < fields.length; i++) {
|
|
1156
|
+
worksheet.getCell(sequence[i] + '2').value = fields[i];
|
|
1157
|
+
worksheet.getCell(sequence[i] + '2').fill = yellow;
|
|
1158
|
+
worksheet.getCell(sequence[i] + '2').alignment = center;
|
|
1159
|
+
}
|
|
1160
|
+
worksheet.mergeCells('A3:' + sequence[(fields.length - 1)] + '3');
|
|
1161
|
+
worksheet.getCell('A3').value = 'DATA';
|
|
1162
|
+
worksheet.getCell('A3').font = bold;
|
|
1163
|
+
worksheet.getCell('A3').alignment = center;
|
|
1164
|
+
|
|
1165
|
+
//check relations
|
|
1166
|
+
let isRelations = false;
|
|
1167
|
+
let relations = [], tableObj = {}, obj = {}, dropdowns = [], passwords = [];
|
|
1168
|
+
let usersObj = await zRoute.getUsers();
|
|
1169
|
+
if (Object.prototype.hasOwnProperty.call(MYMODEL, "widgets")) {
|
|
1170
|
+
for (let key in MYMODEL.widgets) {
|
|
1171
|
+
let widget = MYMODEL.widgets[key];
|
|
1172
|
+
if (widget.name == "password") {
|
|
1173
|
+
passwords.push(key)
|
|
1174
|
+
} else if (widget.name == "select") {
|
|
1175
|
+
tableObj[key] = widget.fields;
|
|
1176
|
+
} else if (widget.name == "switch") {
|
|
1177
|
+
tableObj[key] = widget.fields;
|
|
1178
|
+
} else if (widget.name == "relation") {
|
|
1179
|
+
var rowsarr = await connection.results({
|
|
1180
|
+
table: widget.table,
|
|
1181
|
+
select: widget.fields[0] + "," + widget.fields[1] + " as zname "
|
|
1182
|
+
});
|
|
1183
|
+
//save to object
|
|
1184
|
+
relations[key] = Util.arrayToObject(rowsarr, "id")
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
rows.forEach(function (result) {
|
|
1190
|
+
fields.forEach((field, i) => {
|
|
1191
|
+
let t;
|
|
1192
|
+
if (field == 'company_id') {
|
|
1193
|
+
t = !callback(result, field) ? result.company_id : callback(result, field);
|
|
1194
|
+
} else if (field == 'created_at' || field == 'created_at') {
|
|
1195
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1196
|
+
} else if (field == 'updated_at' || field == 'updated_at') {
|
|
1197
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1198
|
+
} else if (Util.in_array(field, CONFIG.generator.createdupdated_by)) {
|
|
1199
|
+
if (isRaws) {
|
|
1200
|
+
t = !callback(result, field) ? result[field] : callback(result, field);
|
|
1201
|
+
} else {
|
|
1202
|
+
t = !callback(result, field) ? usersObj[result[field]] : callback(result, field);
|
|
1203
|
+
}
|
|
1204
|
+
} else {
|
|
1205
|
+
// callback will call if you have
|
|
1206
|
+
if (Util.in_array(field, relations)) {
|
|
1207
|
+
if (isRaws) {
|
|
1208
|
+
t = !callback(result, field) ? result[field] : callback(result, field);
|
|
1209
|
+
} else {
|
|
1210
|
+
const objectData = tableObj[field] || {};
|
|
1211
|
+
if (!callback(result, field)) {
|
|
1212
|
+
if (result[field] && Object.hasOwn(objectData[result[field]], "zname")) {
|
|
1213
|
+
t = objectData[result[field]]["zname"];
|
|
1214
|
+
} else {
|
|
1215
|
+
t = result[field];
|
|
1216
|
+
}
|
|
1217
|
+
} else {
|
|
1218
|
+
t = callback(result, field);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
} else if (Util.in_array(field, dropdowns)) {
|
|
1222
|
+
t = !callback(result, field) ? MYMODEL.dropdowns[field].fields[result[field]] : callback(result, field);
|
|
1223
|
+
} else if (Util.in_array(field, passwords)) {
|
|
1224
|
+
t = 'xxxxxx';
|
|
1225
|
+
} else if (MYMODEL.widgets[field].name == "select") {
|
|
1226
|
+
if (isRaws) {
|
|
1227
|
+
t = !callback(result, field) ? result[field] : callback(result, field);
|
|
1228
|
+
} else {
|
|
1229
|
+
t = !callback(result, field) ? Object.hasOwn(tableObj[field], result[field]) ? tableObj[field][result[field]] : result[field] : callback(result, field);
|
|
1230
|
+
}
|
|
1231
|
+
} else if (MYMODEL.widgets[field].name == "datetime") {
|
|
1232
|
+
if (isRaws) {
|
|
1233
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1234
|
+
} else {
|
|
1235
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1236
|
+
}
|
|
1237
|
+
} else if (MYMODEL.widgets[field].name == "datepicker") {
|
|
1238
|
+
if (isRaws) {
|
|
1239
|
+
t = !callback(result, field) ? Util.dateFormat(result[field]) : callback(result, field);
|
|
1240
|
+
} else {
|
|
1241
|
+
t = !callback(result, field) ? Util.dateFormat(result[field]) : callback(result, field);
|
|
1242
|
+
}
|
|
1243
|
+
} else if (MYMODEL.widgets[field].name == "switch") {
|
|
1244
|
+
if (isRaws) {
|
|
1245
|
+
t = !callback(result, field) ? result[field] : callback(result, field);
|
|
1246
|
+
} else {
|
|
1247
|
+
t = !callback(result, field) ? tableObj[field][result[field]] || "" : callback(result, field);
|
|
1248
|
+
}
|
|
1249
|
+
} else if (MYMODEL.widgets[field].name == "relation") {
|
|
1250
|
+
if (isRaws) {
|
|
1251
|
+
t = !callback(result, field) ? result[field] : callback(result, field);
|
|
1252
|
+
} else {
|
|
1253
|
+
if (relations[field][result[field]]) {
|
|
1254
|
+
t = !callback(result, field) ? relations[field][result[field]].zname || "" : callback(result, field);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
} else {
|
|
1258
|
+
t = !callback(result, field) ? result[field] : callback(result, field);
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
worksheet.getCell(sequence[i] + start).value = t;
|
|
1262
|
+
});
|
|
1263
|
+
start++;
|
|
1264
|
+
num++
|
|
1265
|
+
});
|
|
1266
|
+
|
|
1267
|
+
fileName = fileName || routeName + '_' + new Date().getTime() + '.xlsx'
|
|
1268
|
+
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
1269
|
+
res.setHeader('Content-Disposition', 'attachment; filename=' + fileName);
|
|
1270
|
+
await workbook.xlsx.write(res);
|
|
1271
|
+
res.end();
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1274
|
+
//for pdf
|
|
1275
|
+
zRoute.pdf = async (req, res, MYMODEL, fields, rows, callback) => {
|
|
1276
|
+
io.to(res.locals.token).emit("message", "Please wait, compiling..")
|
|
1277
|
+
callback = callback || function () {};
|
|
1278
|
+
let labels = MYMODEL.labels;
|
|
1279
|
+
let html = ``
|
|
1280
|
+
html += `<h2>${MYMODEL.title}</h2>`;
|
|
1281
|
+
html += `<br>`;
|
|
1282
|
+
html += `<div class="container">`
|
|
1283
|
+
html += `<table class="table">`;
|
|
1284
|
+
html += `<thead><tr>`
|
|
1285
|
+
for (var i = 0; i < fields.length; i++) {
|
|
1286
|
+
html += `<td>${labels[fields[i]]}</td>`
|
|
1287
|
+
}
|
|
1288
|
+
html += `</tr></thead>`;
|
|
1289
|
+
//check relations
|
|
1290
|
+
let isRelations = false;
|
|
1291
|
+
let relations = [], tableObj = {}, obj = {}, dropdowns = [], passwords = [];
|
|
1292
|
+
let usersObj = await zRoute.getUsers();
|
|
1293
|
+
if (Object.prototype.hasOwnProperty.call(MYMODEL, "widgets")) {
|
|
1294
|
+
for (let key in MYMODEL.widgets) {
|
|
1295
|
+
let widget = MYMODEL.widgets[key];
|
|
1296
|
+
if (widget.name == "password") {
|
|
1297
|
+
passwords.push(key)
|
|
1298
|
+
} else if (widget.name == "select") {
|
|
1299
|
+
tableObj[key] = widget.fields;
|
|
1300
|
+
} else if (widget.name == "switch") {
|
|
1301
|
+
tableObj[key] = widget.fields;
|
|
1302
|
+
} else if (widget.name == "relation") {
|
|
1303
|
+
const rowsarr = await connection.results({
|
|
1304
|
+
table: widget.table,
|
|
1305
|
+
select: widget.fields[0] + "," + widget.fields[1] + " as zname "
|
|
1306
|
+
})
|
|
1307
|
+
//save to object
|
|
1308
|
+
relations[key] = Util.arrayToObject(rowsarr, "id")
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
html += `<tbody>`;
|
|
1313
|
+
rows.forEach(function (result) {
|
|
1314
|
+
html += `<tr>`
|
|
1315
|
+
fields.forEach((field, i) => {
|
|
1316
|
+
var t;
|
|
1317
|
+
if (field == 'company_id') {
|
|
1318
|
+
t = !callback(result, field) ? result.company_id : callback(result, field);
|
|
1319
|
+
} else if (field == 'created_at' || field == 'created_at') {
|
|
1320
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1321
|
+
} else if (field == 'updated_at' || field == 'updated_at') {
|
|
1322
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1323
|
+
} else if (Util.in_array(field, CONFIG.generator.createdupdated_by)) {
|
|
1324
|
+
t = !callback(result, field) ? usersObj[result[field]] : callback(result, field);
|
|
1325
|
+
} else {
|
|
1326
|
+
// callback will call if you have
|
|
1327
|
+
if (Util.in_array(field, relations)) {
|
|
1328
|
+
const objectData = tableObj[field] || {};
|
|
1329
|
+
if (!callback(result, field)) {
|
|
1330
|
+
if (result[field] && Object.hasOwn(objectData[result[field]], "zname")) {
|
|
1331
|
+
t = objectData[result[field]]["zname"];
|
|
1332
|
+
} else {
|
|
1333
|
+
t = result[field];
|
|
1334
|
+
}
|
|
1335
|
+
} else {
|
|
1336
|
+
t = callback(result, field);
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
} else if (Util.in_array(field, dropdowns)) {
|
|
1340
|
+
t = !callback(result, field) ? MYMODEL.dropdowns[field].fields[result[field]] : callback(result, field);
|
|
1341
|
+
} else if (Util.in_array(field, passwords)) {
|
|
1342
|
+
t = 'xxxxxx';
|
|
1343
|
+
} else if (MYMODEL.widgets[field].name == "select") {
|
|
1344
|
+
t = !callback(result, field) ? Object.hasOwn(tableObj[field], result[field]) ? tableObj[field][result[field]] : result[field] : callback(result, field);
|
|
1345
|
+
} else if (MYMODEL.widgets[field].name == "datetime") {
|
|
1346
|
+
t = !callback(result, field) ? Util.timeSql(result[field]) : callback(result, field);
|
|
1347
|
+
} else if (MYMODEL.widgets[field].name == "datepicker") {
|
|
1348
|
+
t = !callback(result, field) ? Util.dateFormat(result[field]) : callback(result, field);
|
|
1349
|
+
} else if (MYMODEL.widgets[field].name == "switch") {
|
|
1350
|
+
t = !callback(result, field) ? tableObj[field][result[field]] || "" : callback(result, field);
|
|
1351
|
+
} else if (MYMODEL.widgets[field].name == "relation") {
|
|
1352
|
+
if (relations[field][result[field]]) {
|
|
1353
|
+
t = !callback(result, field) ? relations[field][result[field]].zname || "" : callback(result, field);
|
|
1354
|
+
}
|
|
1355
|
+
} else {
|
|
1356
|
+
t = !callback(result, field) ? result[field] || "" : callback(result, field);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
//worksheet.getCell(sequence[i] + start).value = t;
|
|
1360
|
+
html += `<td>${t}</td>`
|
|
1361
|
+
});
|
|
1362
|
+
html += `</tr>`
|
|
1363
|
+
});
|
|
1364
|
+
|
|
1365
|
+
html += `</tbody></table></div>`;
|
|
1366
|
+
let time = Util.timeSql();
|
|
1367
|
+
time = Util.replaceAll(time, " ", "_");
|
|
1368
|
+
let file = {content: html};
|
|
1369
|
+
let count = fields.length;
|
|
1370
|
+
let options = {}
|
|
1371
|
+
if (count > 8) {
|
|
1372
|
+
options = {
|
|
1373
|
+
landscape: true
|
|
1374
|
+
}
|
|
1375
|
+
} else if (count > 10) {
|
|
1376
|
+
options = {
|
|
1377
|
+
format: 'A3',
|
|
1378
|
+
//landscape:true
|
|
1379
|
+
}
|
|
1380
|
+
} else if (count > 12) {
|
|
1381
|
+
options = {
|
|
1382
|
+
format: 'A3',
|
|
1383
|
+
landscape: true
|
|
1384
|
+
}
|
|
1385
|
+
} else if (count > 14) {
|
|
1386
|
+
options = {
|
|
1387
|
+
format: 'A2',
|
|
1388
|
+
//landscape:true
|
|
1389
|
+
}
|
|
1390
|
+
} else if (count > 16) {
|
|
1391
|
+
options = {
|
|
1392
|
+
format: 'A0',
|
|
1393
|
+
landscape: true
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
const pdf = await zRoute.generatePDF(file, 'pdf_blank', options);
|
|
1397
|
+
res.download(pdf, MYMODEL.table + time + ".pdf");
|
|
1398
|
+
};
|
|
1399
|
+
|
|
1400
|
+
/*
|
|
1401
|
+
let options = { format: 'A4' };
|
|
1402
|
+
// Example of options with args //
|
|
1403
|
+
// let options = { format: 'A4', args: ['--no-sandbox', '--disable-setuid-sandbox'] };
|
|
1404
|
+
|
|
1405
|
+
let file = { content: "<h1>Welcome to html-pdf-node</h1>" };
|
|
1406
|
+
// or //
|
|
1407
|
+
let file = { url: "https://example.com" };
|
|
1408
|
+
let layout = "pdf_blank";
|
|
1409
|
+
var pdf = await zRoute.generatePDF(file, layout,options)
|
|
1410
|
+
*/
|
|
1411
|
+
zRoute.generatePDF = async (file, layout = "pdf_bootstrap", options = {}) => {
|
|
1412
|
+
// we are using headless mode
|
|
1413
|
+
let args = [
|
|
1414
|
+
'--headless=new',
|
|
1415
|
+
'--no-sandbox',
|
|
1416
|
+
'--disable-setuid-sandbox',
|
|
1417
|
+
];
|
|
1418
|
+
let env = CONFIG.environment;
|
|
1419
|
+
let puppeterOptions = {
|
|
1420
|
+
args: args
|
|
1421
|
+
};
|
|
1422
|
+
if (env == "production") {
|
|
1423
|
+
puppeterOptions.executablePath = '/usr/bin/google-chrome-stable';
|
|
1424
|
+
puppeterOptions.defaultViewport = {width: 1920, height: 1080};
|
|
1425
|
+
}
|
|
1426
|
+
const browser = await puppeteer.launch(puppeterOptions);
|
|
1427
|
+
const page = await browser.newPage();
|
|
1428
|
+
let mylayout = `${dirRoot}/views/layouts/${layout}.ejs`
|
|
1429
|
+
if (file.content) {
|
|
1430
|
+
const html = await ejs.renderFile(mylayout, {data: file.content}, {async: true});
|
|
1431
|
+
await page.setContent(html, {
|
|
1432
|
+
waitUntil: 'load', timeout: 60000, // wait for page to load completely
|
|
1433
|
+
});
|
|
1434
|
+
} else {
|
|
1435
|
+
await page.goto(file.url, {
|
|
1436
|
+
waitUntil: 'load', timeout: 60000 // wait for page to load completely
|
|
1437
|
+
});
|
|
1438
|
+
}
|
|
1439
|
+
let fileName = new Date().getTime() + ".pdf";
|
|
1440
|
+
const filePath = `${dirRoot}/public/_pdf/${fileName}`;
|
|
1441
|
+
const myoptions = {
|
|
1442
|
+
path: filePath,
|
|
1443
|
+
format: 'A4',
|
|
1444
|
+
};
|
|
1445
|
+
for (let key in options) {
|
|
1446
|
+
myoptions[key] = options[key];
|
|
1447
|
+
}
|
|
1448
|
+
await page.pdf(myoptions);
|
|
1449
|
+
await browser.close();
|
|
1450
|
+
return filePath;
|
|
1451
|
+
};
|
|
1452
|
+
|
|
1453
|
+
|
|
1454
|
+
/*
|
|
1455
|
+
Grids Data Table
|
|
1456
|
+
save grid
|
|
1457
|
+
*/
|
|
1458
|
+
zRoute.dataTableSave = async (routeName, userId, body) => {
|
|
1459
|
+
const results = await connection.results({
|
|
1460
|
+
table: "zgrid",
|
|
1461
|
+
where: {
|
|
1462
|
+
user_id: userId,
|
|
1463
|
+
route_name: routeName
|
|
1464
|
+
}
|
|
1465
|
+
});
|
|
1466
|
+
if (results.length) {
|
|
1467
|
+
await connection.update({
|
|
1468
|
+
table: "zgrid",
|
|
1469
|
+
data: {
|
|
1470
|
+
visibles: JSON.stringify(body.fields),
|
|
1471
|
+
filter: JSON.stringify(body)
|
|
1472
|
+
},
|
|
1473
|
+
where: {
|
|
1474
|
+
user_id: userId,
|
|
1475
|
+
route_name: routeName
|
|
1476
|
+
}
|
|
1477
|
+
})
|
|
1478
|
+
} else {
|
|
1479
|
+
await connection.insert({
|
|
1480
|
+
table: "zgrid",
|
|
1481
|
+
data: {
|
|
1482
|
+
route_name: routeName,
|
|
1483
|
+
user_id: userId,
|
|
1484
|
+
visibles: JSON.stringify(body.fields),
|
|
1485
|
+
filter: JSON.stringify(body)
|
|
1486
|
+
},
|
|
1487
|
+
where: {
|
|
1488
|
+
user_id: userId,
|
|
1489
|
+
route_name: routeName
|
|
1490
|
+
}
|
|
1491
|
+
})
|
|
1492
|
+
}
|
|
1493
|
+
return "ok";
|
|
1494
|
+
};
|
|
1495
|
+
|
|
1496
|
+
zRoute.listData = async (req, res, MYMODEL, zRole) => {
|
|
1497
|
+
const relations = await zRoute.relations(req, res, MYMODEL.table);
|
|
1498
|
+
const body = req.body;
|
|
1499
|
+
const fields = body.fields;
|
|
1500
|
+
const select = Util.selectMysql(fields, relations);
|
|
1501
|
+
let whereArray = [];
|
|
1502
|
+
const columns = body.columns;
|
|
1503
|
+
whereArray.push({
|
|
1504
|
+
field: "company_id",
|
|
1505
|
+
option: "=",
|
|
1506
|
+
value: res.locals.companyId,
|
|
1507
|
+
operator: "AND"
|
|
1508
|
+
});
|
|
1509
|
+
columns.forEach(function (item) {
|
|
1510
|
+
if (item.search.value) {
|
|
1511
|
+
whereArray.push({
|
|
1512
|
+
field: fields[item.data],
|
|
1513
|
+
option: MYMODEL.options[fields[item.data]],
|
|
1514
|
+
value: item.search.value,
|
|
1515
|
+
operator: "AND"
|
|
1516
|
+
})
|
|
1517
|
+
}
|
|
1518
|
+
});
|
|
1519
|
+
const orderColumn = fields[body.order[0].column] == "actionColumn" ? "id" : fields[body.order[0].column] == "no" ? "id" : fields[body.order[0].column] == "actionColum" ? "id" : fields[body.order[0].column];
|
|
1520
|
+
const rows = await connection.results({
|
|
1521
|
+
select: select,
|
|
1522
|
+
table: MYMODEL.table,
|
|
1523
|
+
whereArray: whereArray,
|
|
1524
|
+
limit: body.length,
|
|
1525
|
+
offset: body.start,
|
|
1526
|
+
orderBy: [orderColumn, body.order[0].dir]
|
|
1527
|
+
});
|
|
1528
|
+
const count = await connection.result({
|
|
1529
|
+
select: "count(id) as count",
|
|
1530
|
+
table: MYMODEL.table,
|
|
1531
|
+
whereArray: whereArray
|
|
1532
|
+
});
|
|
1533
|
+
let datas = [];
|
|
1534
|
+
const levels = zRole.levels(MYMODEL.routeName, zRole.routes.indexOf(MYMODEL.routeName) > -1 ? await zRole.rules(res.locals.roleId) : {});
|
|
1535
|
+
rows.forEach(function (row, index) {
|
|
1536
|
+
let arr = [];
|
|
1537
|
+
fields.forEach(function (item) {
|
|
1538
|
+
if (item == "no") {
|
|
1539
|
+
arr.push((index + 1 + parseInt(body.start)));
|
|
1540
|
+
} else if (item == "actionColumn") {
|
|
1541
|
+
arr.push(zRoute.actionButtons(levels, row, MYMODEL.table));
|
|
1542
|
+
} else {
|
|
1543
|
+
arr.push(zRoute.dataTableData(item, row[item], MYMODEL, relations));
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
datas.push(arr)
|
|
1547
|
+
});
|
|
1548
|
+
const data = {
|
|
1549
|
+
draw: body.draw,
|
|
1550
|
+
recordsTotal: count.count || 0,
|
|
1551
|
+
recordsFiltered: count.count || 0,
|
|
1552
|
+
data: datas
|
|
1553
|
+
};
|
|
1554
|
+
//save grid filter async
|
|
1555
|
+
zRoute.dataTableSave(MYMODEL.routeName, res.locals.userId, body);
|
|
1556
|
+
res.json(data);
|
|
1557
|
+
};
|
|
1558
|
+
|
|
1559
|
+
zRoute.actionButtons = (levels, row, table, callback = null) => {
|
|
1560
|
+
let arr = [];
|
|
1561
|
+
let obj = {}
|
|
1562
|
+
if (levels.delete) {
|
|
1563
|
+
let icon_delete = `<span class="icon-small icons-danger" title="${LANGUAGE.delete}" ><img data-id="${row.id}" class="icons-bg-white griddelete icon-image" src="/assets/icons/trash-filled.svg"></span>`;
|
|
1564
|
+
arr.push(icon_delete);
|
|
1565
|
+
obj['delete'] = icon_delete;
|
|
1566
|
+
}
|
|
1567
|
+
if (levels.update) {
|
|
1568
|
+
let icon_update = `<span class="icon-small icons-primary" title="${LANGUAGE.update}" ><img data-id="${row.id}" class="icons-bg-white gridupdate icon-image" src="/assets/icons/edit.svg"></span>`;
|
|
1569
|
+
arr.push(icon_update);
|
|
1570
|
+
obj['update'] = icon_update;
|
|
1571
|
+
}
|
|
1572
|
+
if (levels.view) {
|
|
1573
|
+
let icon_view = `<span class="icon-small icons-light" title="${LANGUAGE.view}" ><img data-id="${row.id}" class="icons-bg-black gridview icon-image" src="/assets/icons/eye.svg"></span>`;
|
|
1574
|
+
arr.push(icon_view);
|
|
1575
|
+
obj['view'] = icon_view;
|
|
1576
|
+
}
|
|
1577
|
+
if (levels.approval) {
|
|
1578
|
+
let icon_approval = `<span class="icon-small icons-warning" title="${LANGUAGE.approval}" ><img data-id="${row.id}" class="icons-bg-white gridapproval icon-image" src="/assets/icons/rubber-stamp.svg"></span>`;
|
|
1579
|
+
arr.push(icon_approval);
|
|
1580
|
+
obj['approval'] = icon_approval;
|
|
1581
|
+
}
|
|
1582
|
+
let view = '<div class="no-wrap">';
|
|
1583
|
+
view += arr.join(" ");
|
|
1584
|
+
view += `</div>`;
|
|
1585
|
+
if (callback) {
|
|
1586
|
+
callback({
|
|
1587
|
+
arr: arr,
|
|
1588
|
+
view: view,
|
|
1589
|
+
levels: levels,
|
|
1590
|
+
row: row,
|
|
1591
|
+
table: table,
|
|
1592
|
+
obj: obj
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
|
|
1596
|
+
return view;
|
|
1597
|
+
};
|
|
1598
|
+
|
|
1599
|
+
zRoute.dataTableViewLevel = (levels, row, table) => {
|
|
1600
|
+
return zRoute.actionButtons(levels, row, table);
|
|
1601
|
+
};
|
|
1602
|
+
|
|
1603
|
+
zRoute.postGridReload = async (req, res) => {
|
|
1604
|
+
let routeName = res.locals.routeName;
|
|
1605
|
+
let userId = res.locals.userId;
|
|
1606
|
+
let json = Util.jsonSuccess("Successfully to reset grid filter ");
|
|
1607
|
+
await connection.delete({
|
|
1608
|
+
table: gridTable,
|
|
1609
|
+
where: {user_id: userId, route_name: routeName}
|
|
1610
|
+
});
|
|
1611
|
+
//await zRoute.attributeData(res, )
|
|
1612
|
+
res.json(json)
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1615
|
+
zRoute.postGrid = async (req, res) => {
|
|
1616
|
+
try {
|
|
1617
|
+
let query = req.body;
|
|
1618
|
+
//console.log(query);
|
|
1619
|
+
let visible = query.serialize_left;
|
|
1620
|
+
let invisible = query.serialize_right;
|
|
1621
|
+
let post = {
|
|
1622
|
+
user_id: res.locals.userId,
|
|
1623
|
+
route_name: res.locals.routeName,
|
|
1624
|
+
visibles: visible,
|
|
1625
|
+
invisibles: invisible,
|
|
1626
|
+
company_id: 1,
|
|
1627
|
+
updated_at: Util.now()
|
|
1628
|
+
};
|
|
1629
|
+
let results = await connection.results({
|
|
1630
|
+
table: gridTable,
|
|
1631
|
+
where: {user_id: res.locals.userId, route_name: res.locals.routeName}
|
|
1632
|
+
});
|
|
1633
|
+
if (results.length == 0) {
|
|
1634
|
+
await connection.insert({table: gridTable, data: post});
|
|
1635
|
+
} else {
|
|
1636
|
+
await connection.update({table: gridTable, data: post, where: {id: results[0].id}})
|
|
1637
|
+
}
|
|
1638
|
+
res.json(Util.jsonSuccess(LANGUAGE['grid_saved']))
|
|
1639
|
+
} catch (err) {
|
|
1640
|
+
debug(req, res, err);
|
|
1641
|
+
res.json(err)
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
|
|
1645
|
+
zRoute.chains = async (req, res) => {
|
|
1646
|
+
try {
|
|
1647
|
+
let body = req.body;
|
|
1648
|
+
let id = body.id;
|
|
1649
|
+
let currentValue = body.currentValue;
|
|
1650
|
+
let target = body.target;
|
|
1651
|
+
let column = body.column;
|
|
1652
|
+
let table = body.table;
|
|
1653
|
+
let name = body.name;
|
|
1654
|
+
let data = {}
|
|
1655
|
+
let obj = body.obj;
|
|
1656
|
+
if (id) {
|
|
1657
|
+
const results = await connection.results({
|
|
1658
|
+
select: ` id, ${name} as zname `,
|
|
1659
|
+
table: table,
|
|
1660
|
+
where: {
|
|
1661
|
+
[column]: id,
|
|
1662
|
+
company_id: res.locals.companyId
|
|
1663
|
+
},
|
|
1664
|
+
orderBy: ["zname", "asc"]
|
|
1665
|
+
});
|
|
1666
|
+
data[target] = `<option value="">Please Select</option>`;
|
|
1667
|
+
if (results.length) {
|
|
1668
|
+
results.forEach(function (result) {
|
|
1669
|
+
var selected = result.id == currentValue ? " selected " : "";
|
|
1670
|
+
data[target] += `<option value="${result.id}" ${selected} >${result.zname}</option>`;
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
res.json(data);
|
|
1675
|
+
} catch (e) {
|
|
1676
|
+
res.json(Util.flashError(e.toString()));
|
|
1677
|
+
}
|
|
1678
|
+
};
|
|
1679
|
+
|
|
1680
|
+
zRoute.getAttributes = async (req, res) => {
|
|
1681
|
+
let id = req.body.id;
|
|
1682
|
+
let table = req.body.table;
|
|
1683
|
+
let result = {}
|
|
1684
|
+
if(id && table) {
|
|
1685
|
+
result = await connection.result({
|
|
1686
|
+
table : table,
|
|
1687
|
+
where : {
|
|
1688
|
+
id:id
|
|
1689
|
+
}
|
|
1690
|
+
})
|
|
1691
|
+
}
|
|
1692
|
+
res.json(result);
|
|
1693
|
+
};
|
|
1694
|
+
|
|
1695
|
+
zRoute.formUser = (relations = {}, data = {}) => {
|
|
1696
|
+
let obj = {}
|
|
1697
|
+
let isUser = false;
|
|
1698
|
+
if (data.hasOwnProperty('created_by')) {
|
|
1699
|
+
isUser = true;
|
|
1700
|
+
if (relations.hasOwnProperty('created_byObject')) {
|
|
1701
|
+
obj.created_by = relations.created_byObject[data['created_by']];
|
|
1702
|
+
obj.updated_by = relations.updated_byObject[data['updated_by']];
|
|
1703
|
+
obj.created_at = Util.timeSql(data['created_at']);
|
|
1704
|
+
obj.updated_at = Util.timeSql(data['updated_at']);
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
obj.isUser = isUser;
|
|
1708
|
+
return obj;
|
|
1709
|
+
};
|
|
1710
|
+
|
|
1711
|
+
zRoute.formField = (req, res, MYMODEL, relations, data = {}) => {
|
|
1712
|
+
let forms = zRoute.forms(req, res, MYMODEL, relations, data);
|
|
1713
|
+
let obj = forms.obj;
|
|
1714
|
+
for (let key in obj) {
|
|
1715
|
+
forms.build[key] = cForm.build(obj[key]);
|
|
1716
|
+
}
|
|
1717
|
+
forms.users = zRoute.formUser(relations, data);
|
|
1718
|
+
return forms;
|
|
1719
|
+
};
|
|
1720
|
+
|
|
1721
|
+
zRoute.formsFieldSync = async (req, res, MYMODEL, data = {}) => {
|
|
1722
|
+
const relations = await zRoute.relations(req, res, MYMODEL.table);
|
|
1723
|
+
let forms = zRoute.forms(req, res, MYMODEL, relations, data);
|
|
1724
|
+
let obj = forms.obj;
|
|
1725
|
+
for (let key in obj) {
|
|
1726
|
+
forms.build[key] = cForm.build(obj[key]);
|
|
1727
|
+
}
|
|
1728
|
+
zRoute.moduleLib(req, res, MYMODEL, relations, forms);
|
|
1729
|
+
return forms;
|
|
1730
|
+
};
|
|
1731
|
+
|
|
1732
|
+
zRoute.formFieldSync = async (req, res, MYMODEL, relations, data = {}) => {
|
|
1733
|
+
let forms = zRoute.forms(req, res, MYMODEL, relations, data);
|
|
1734
|
+
let obj = forms.obj;
|
|
1735
|
+
for (let key in obj) {
|
|
1736
|
+
forms.build[key] = cForm.build(obj[key]);
|
|
1737
|
+
}
|
|
1738
|
+
zRoute.moduleLib(req, res, MYMODEL, relations, forms);
|
|
1739
|
+
return forms;
|
|
1740
|
+
};
|
|
1741
|
+
|
|
1742
|
+
zRoute.forms = (req, res, MYMODEL, relations, data = {}) => {
|
|
1743
|
+
relations = relations || {};
|
|
1744
|
+
let fields = MYMODEL.fields;
|
|
1745
|
+
let dropdowns = MYMODEL.dropdowns || {};
|
|
1746
|
+
let modules = MYMODEL.modules || {};
|
|
1747
|
+
let relationsModel = MYMODEL.relations || {};
|
|
1748
|
+
let widgets = MYMODEL.widgets || {};
|
|
1749
|
+
let additionalScripts = {};
|
|
1750
|
+
let forms = {};
|
|
1751
|
+
let tabIndex = 0;
|
|
1752
|
+
forms.label = {};
|
|
1753
|
+
forms.field = {};
|
|
1754
|
+
forms.obj = {};
|
|
1755
|
+
forms.build = {}
|
|
1756
|
+
forms.fn = {};
|
|
1757
|
+
forms.group = {};
|
|
1758
|
+
forms.scriptGroup = "";
|
|
1759
|
+
let script = '';
|
|
1760
|
+
for (let key in fields) {
|
|
1761
|
+
// for label
|
|
1762
|
+
//forms.label[key] = cForm.label(key, fields[key].title, fields[key].required);
|
|
1763
|
+
//for object property
|
|
1764
|
+
let obj = {
|
|
1765
|
+
type: "text",
|
|
1766
|
+
id: key,
|
|
1767
|
+
routeName: MYMODEL.routeName,
|
|
1768
|
+
name: MYMODEL.table + "[" + fields[key].name + "]",
|
|
1769
|
+
title: fields[key].title || "",
|
|
1770
|
+
required: fields[key].required,
|
|
1771
|
+
placeholder: fields[key].placeholder || "",
|
|
1772
|
+
value: data[key] == undefined ? "" : data[key],
|
|
1773
|
+
frameworkcss: res.locals.frameworkcss,
|
|
1774
|
+
form_css: res.locals.form_css,
|
|
1775
|
+
float: fields[key].float || false,
|
|
1776
|
+
inline: fields[key].inline || false,
|
|
1777
|
+
attributes: widgets[key],
|
|
1778
|
+
tabIndex: tabIndex,
|
|
1779
|
+
labelOptions: "",
|
|
1780
|
+
class: 'form-control '
|
|
1781
|
+
};
|
|
1782
|
+
|
|
1783
|
+
//check if widgets
|
|
1784
|
+
if (widgets.hasOwnProperty(key)) {
|
|
1785
|
+
tabIndex++;
|
|
1786
|
+
let widgetName = widgets[key].name;
|
|
1787
|
+
let keyFields = key + "Fields";
|
|
1788
|
+
if (widgets[key].hasOwnProperty("information")) {
|
|
1789
|
+
obj.information = widgets[key].information;
|
|
1790
|
+
}
|
|
1791
|
+
obj.readonly = widgets[key].readonly || false;
|
|
1792
|
+
obj.class = 'form-control ';
|
|
1793
|
+
switch (widgetName) {
|
|
1794
|
+
case "text" :
|
|
1795
|
+
if (widgets[key].hidden) {
|
|
1796
|
+
obj.type = "hidden";
|
|
1797
|
+
} else {
|
|
1798
|
+
obj.type = "input";
|
|
1799
|
+
}
|
|
1800
|
+
break;
|
|
1801
|
+
case "tags" :
|
|
1802
|
+
obj.type = "tags";
|
|
1803
|
+
break;
|
|
1804
|
+
case "checkbox" :
|
|
1805
|
+
obj.type = "checkbox";
|
|
1806
|
+
break;
|
|
1807
|
+
case "range" :
|
|
1808
|
+
obj.type = "range";
|
|
1809
|
+
break;
|
|
1810
|
+
case "color" :
|
|
1811
|
+
obj.type = "color";
|
|
1812
|
+
break;
|
|
1813
|
+
case "textarea" :
|
|
1814
|
+
if (widgets[key].hidden) {
|
|
1815
|
+
obj.style = "display:none";
|
|
1816
|
+
}
|
|
1817
|
+
obj.type = "textarea";
|
|
1818
|
+
break;
|
|
1819
|
+
case "image" :
|
|
1820
|
+
obj.type = "image";
|
|
1821
|
+
obj.width = widgets[key].width || '300';
|
|
1822
|
+
break;
|
|
1823
|
+
case "file" :
|
|
1824
|
+
obj.type = "file";
|
|
1825
|
+
break;
|
|
1826
|
+
case "email" :
|
|
1827
|
+
obj.type = "email";
|
|
1828
|
+
break;
|
|
1829
|
+
case "lexical" :
|
|
1830
|
+
obj.type = "lexical";
|
|
1831
|
+
if (obj.value) {
|
|
1832
|
+
script += `document.addEventListener("DOMContentLoaded", () => {
|
|
1833
|
+
setTimeout(function () {
|
|
1834
|
+
window.importFile(window.LexicalEditor,${JSON.stringify(obj.value)});
|
|
1835
|
+
}, 1000);
|
|
1836
|
+
});`;
|
|
1837
|
+
}
|
|
1838
|
+
break;
|
|
1839
|
+
case "select" :
|
|
1840
|
+
obj.type = "select";
|
|
1841
|
+
obj.data = relations[key];
|
|
1842
|
+
obj.array = relations[key + "Array"];
|
|
1843
|
+
obj.please_select = widgets[key].please_select;
|
|
1844
|
+
break;
|
|
1845
|
+
case "radio" :
|
|
1846
|
+
obj.type = "radio";
|
|
1847
|
+
obj.data = relations[key]
|
|
1848
|
+
obj.array = relations[key + "Array"];
|
|
1849
|
+
break;
|
|
1850
|
+
case "switch" :
|
|
1851
|
+
obj.type = "switch";
|
|
1852
|
+
obj.class = "form-control switch";
|
|
1853
|
+
break;
|
|
1854
|
+
case "dropdown_checkbox" :
|
|
1855
|
+
obj.type = "dropdown_checkbox";
|
|
1856
|
+
obj.data = widgets[key].fields || [];
|
|
1857
|
+
break;
|
|
1858
|
+
case "relation" :
|
|
1859
|
+
obj.type = "select";
|
|
1860
|
+
var htmlOptions = ` <a href="/${widgets[key].table}" target="_blank"> > </a>`;
|
|
1861
|
+
forms.label[key] = cForm.label(key, fields[key].title, fields[key].required, htmlOptions);
|
|
1862
|
+
obj.data = relations[key];
|
|
1863
|
+
obj.please_select = widgets[key].please_select;
|
|
1864
|
+
break;
|
|
1865
|
+
case "typeahead" :
|
|
1866
|
+
obj.type = "typeahead";
|
|
1867
|
+
forms.label[key] = cForm.label(key, fields[key].title, fields[key].required);
|
|
1868
|
+
obj.data = relations[key];
|
|
1869
|
+
obj.typeaheadvalue = !data[key] ? "" : relations[key + "Object"][data[key]];
|
|
1870
|
+
break;
|
|
1871
|
+
case "dropdown_chain" :
|
|
1872
|
+
obj.type = "select";
|
|
1873
|
+
var htmlOptions = ` <a href="/${widgets[key].table}" target="_blank"> > </a>`;
|
|
1874
|
+
forms.label[key] = cForm.label(key, fields[key].title, fields[key].required, htmlOptions);
|
|
1875
|
+
obj.data = relations[key + "Row"];
|
|
1876
|
+
break;
|
|
1877
|
+
case "dropdown_multi" :
|
|
1878
|
+
obj.type = "multi";
|
|
1879
|
+
obj.data = relations[key] || [];
|
|
1880
|
+
obj.multi = relations[key + "Object"];
|
|
1881
|
+
break;
|
|
1882
|
+
case "number" :
|
|
1883
|
+
obj.type = "number";
|
|
1884
|
+
obj.class = "form-control number";
|
|
1885
|
+
break;
|
|
1886
|
+
case "integer" :
|
|
1887
|
+
obj.type = "number";
|
|
1888
|
+
obj.class = "form-control number";
|
|
1889
|
+
break;
|
|
1890
|
+
case "email" :
|
|
1891
|
+
obj.type = "input";
|
|
1892
|
+
break;
|
|
1893
|
+
case "password" :
|
|
1894
|
+
obj.type = "password";
|
|
1895
|
+
break;
|
|
1896
|
+
case "datepicker" :
|
|
1897
|
+
obj.type = "datepicker";
|
|
1898
|
+
obj.class = "form-control datepicker";
|
|
1899
|
+
obj.value = obj.value == "0000-00-00" ? "" : Util.dateSql(obj.value);
|
|
1900
|
+
break;
|
|
1901
|
+
case "datetime" :
|
|
1902
|
+
obj.type = "datetimepicker";
|
|
1903
|
+
obj.class = "form-control datetimepicker";
|
|
1904
|
+
obj.value = obj.value == "0000-00-00 00:00:00" ? "" : Util.timeSql(obj.value);
|
|
1905
|
+
break;
|
|
1906
|
+
case "clockpicker" :
|
|
1907
|
+
obj.type = "input";
|
|
1908
|
+
obj.class = "form-control clockpicker";
|
|
1909
|
+
break;
|
|
1910
|
+
case "editor" :
|
|
1911
|
+
obj.type = "textarea";
|
|
1912
|
+
obj.class = "form-control editor";
|
|
1913
|
+
break;
|
|
1914
|
+
case "tinymce" :
|
|
1915
|
+
obj.type = "textarea";
|
|
1916
|
+
obj.class = "form-control tinymce";
|
|
1917
|
+
break;
|
|
1918
|
+
case "ide_editor" :
|
|
1919
|
+
forms.label[key] = cForm.label(key, fields[key].title, fields[key].required, ` <span class="badge bg-primary float-end boxy-small">${widgets[key].language}</span>`);
|
|
1920
|
+
obj.labelOptions = ` <span class="badge bg-primary float-end boxy-small">${widgets[key].language}</span>`;
|
|
1921
|
+
obj.type = "ide_editor";
|
|
1922
|
+
obj.class = "form-control ide_editor";
|
|
1923
|
+
var myobjvalue = obj.value;
|
|
1924
|
+
if (myobjvalue.includes("`")) {
|
|
1925
|
+
myobjvalue = Util.replaceAll(obj.value, "`", "\\`");
|
|
1926
|
+
}
|
|
1927
|
+
if (myobjvalue.includes("</script>")) {
|
|
1928
|
+
myobjvalue = Util.replaceAll(myobjvalue, "</script>", "<//script>");
|
|
1929
|
+
}
|
|
1930
|
+
if (myobjvalue.includes("${")) {
|
|
1931
|
+
myobjvalue = Util.replaceAll(myobjvalue, "${", "$___{");
|
|
1932
|
+
}
|
|
1933
|
+
script += ` var ide_editor_${key} = \`${myobjvalue}\`;`;
|
|
1934
|
+
break;
|
|
1935
|
+
case "table" :
|
|
1936
|
+
obj.type = "table";
|
|
1937
|
+
obj.data = relations[key];
|
|
1938
|
+
obj.properties = relations[`properties_${key}`];
|
|
1939
|
+
break;
|
|
1940
|
+
case "multi_line_editor" :
|
|
1941
|
+
obj.type = "multi_line_editor";
|
|
1942
|
+
obj.data = relations[key];
|
|
1943
|
+
obj.description = widgets[key].description;
|
|
1944
|
+
obj.fields = relations[key + "Fields"];
|
|
1945
|
+
break;
|
|
1946
|
+
case "json" :
|
|
1947
|
+
obj.type = "json";
|
|
1948
|
+
obj.data = relations[key];
|
|
1949
|
+
break;
|
|
1950
|
+
case "virtual" :
|
|
1951
|
+
obj.type = "virtual";
|
|
1952
|
+
break;
|
|
1953
|
+
|
|
1954
|
+
default :
|
|
1955
|
+
obj.type = "text";
|
|
1956
|
+
break;
|
|
1957
|
+
}
|
|
1958
|
+
} else {
|
|
1959
|
+
obj.type = "text";
|
|
1960
|
+
}
|
|
1961
|
+
forms.obj[key] = obj;
|
|
1962
|
+
//forms.build[key] = cForm.build(obj[key]);
|
|
1963
|
+
}
|
|
1964
|
+
forms.users = zRoute.formUser(relations, data);
|
|
1965
|
+
if(script) {
|
|
1966
|
+
res.locals.relationsVariable = `<script>${script}</script>`;
|
|
1967
|
+
}
|
|
1968
|
+
return forms;
|
|
1969
|
+
};
|
|
1970
|
+
|
|
1971
|
+
zRoute.viewFormPlainText = (req, res, MYMODEL, relations, data = {}) => {
|
|
1972
|
+
return zRoute.viewForm(req, res, MYMODEL, relations, data);
|
|
1973
|
+
};
|
|
1974
|
+
|
|
1975
|
+
zRoute.viewFormsSync = async (req, res, MYMODEL, data = {}) => {
|
|
1976
|
+
const relations = await zRoute.relations(req, res, MYMODEL.table);
|
|
1977
|
+
let forms = zRoute.viewForm(req, res, MYMODEL, relations, data);
|
|
1978
|
+
//zRoute.moduleLib(req, res, MYMODEL, relations, forms);
|
|
1979
|
+
let tables = [];
|
|
1980
|
+
for (let key in forms.obj) {
|
|
1981
|
+
if(forms.obj[key].type == 'table') {
|
|
1982
|
+
let obj = forms.obj[key];
|
|
1983
|
+
let MODEL = require(`./../models/${MYMODEL.widgets[obj.id].table}`);
|
|
1984
|
+
const relationsTable = await zRoute.relations(req,res,MODEL.table);
|
|
1985
|
+
let tableForms = zRoute.viewForm(req,res,MODEL,relationsTable, obj.value || []);
|
|
1986
|
+
let properties = obj.properties;
|
|
1987
|
+
let tableProperties = {};
|
|
1988
|
+
for(let k in properties) {
|
|
1989
|
+
tableProperties[k] = tableForms.obj[k];
|
|
1990
|
+
}
|
|
1991
|
+
let html = ``;
|
|
1992
|
+
html += `<div class="card boxy"><div class="card-header"><h5 class="card-title">${obj.title}</h5></div><div class="card-body"><div class="table-responsive">
|
|
1993
|
+
<table class="table table-hover table-sm">
|
|
1994
|
+
<thead>
|
|
1995
|
+
<tr>`;
|
|
1996
|
+
for(let k in obj.data) {
|
|
1997
|
+
html += `<th>${obj.data[k]}</th>`;
|
|
1998
|
+
}
|
|
1999
|
+
html += `</tr></thead><tbody>`;
|
|
2000
|
+
let val = obj.value || [];
|
|
2001
|
+
if(val.length) {
|
|
2002
|
+
val.forEach(function (item) {
|
|
2003
|
+
let myforms = zRoute.viewForm(req,res,MODEL,relationsTable,item)
|
|
2004
|
+
html += `<tr>`;
|
|
2005
|
+
for(let k in obj.data) {
|
|
2006
|
+
html += `<td>${cForm.field(myforms.obj[k])}</td>`;
|
|
2007
|
+
}
|
|
2008
|
+
html += `</tr>`;
|
|
2009
|
+
});
|
|
2010
|
+
}
|
|
2011
|
+
html += `</tbody></table></div></div></div>`;
|
|
2012
|
+
forms.obj[key].html = html;
|
|
2013
|
+
forms.obj[key].type = "data_table";
|
|
2014
|
+
}
|
|
2015
|
+
forms.build[key] = cForm.build(forms.obj[key]);
|
|
2016
|
+
}
|
|
2017
|
+
return forms;
|
|
2018
|
+
};
|
|
2019
|
+
|
|
2020
|
+
zRoute.viewFormSync = (req, res, MYMODEL, relations, data = {}) => {
|
|
2021
|
+
let forms = zRoute.viewForm(req, res, MYMODEL, relations, data);
|
|
2022
|
+
zRoute.moduleLib(req, res, MYMODEL, relations, forms);
|
|
2023
|
+
for (let key in forms.obj) {
|
|
2024
|
+
forms.build[key] = cForm.build(forms.obj[key]);
|
|
2025
|
+
}
|
|
2026
|
+
return forms;
|
|
2027
|
+
};
|
|
2028
|
+
|
|
2029
|
+
zRoute.viewForm = (req, res, MYMODEL, relations, data = {}) => {
|
|
2030
|
+
let forms = zRoute.forms(req, res, MYMODEL, relations, data);
|
|
2031
|
+
const widgets = MYMODEL.widgets;
|
|
2032
|
+
let obj = forms.obj;
|
|
2033
|
+
let prepend = '';
|
|
2034
|
+
let value = '';
|
|
2035
|
+
for (let key in obj) {
|
|
2036
|
+
if (widgets.hasOwnProperty(key)) {
|
|
2037
|
+
let className = 'form-control-plaintext ';
|
|
2038
|
+
if (widgets[key].float) {
|
|
2039
|
+
className += ` boxy-small`;
|
|
2040
|
+
} else {
|
|
2041
|
+
className += ` purple-border`;
|
|
2042
|
+
}
|
|
2043
|
+
obj[key].class = className;
|
|
2044
|
+
obj[key].readonly = true;
|
|
2045
|
+
obj[key].placeholder = " ";
|
|
2046
|
+
obj[key].view_only = true;
|
|
2047
|
+
//obj[key].disabled = true;
|
|
2048
|
+
let widgetName = widgets[key].name;
|
|
2049
|
+
switch (widgetName) {
|
|
2050
|
+
case "password" :
|
|
2051
|
+
obj[key].value = "xxxxxx";
|
|
2052
|
+
break;
|
|
2053
|
+
case "image" :
|
|
2054
|
+
obj[key].type = "plaintext";
|
|
2055
|
+
let width = widgets[key].width || '300';
|
|
2056
|
+
obj[key].value = "<br><br>" + Util.fileView(`/uploads/${MYMODEL.routeName}/`, data[key], {
|
|
2057
|
+
width: width,
|
|
2058
|
+
class: 'boxy'
|
|
2059
|
+
});
|
|
2060
|
+
break;
|
|
2061
|
+
case "file" :
|
|
2062
|
+
obj[key].type = "plaintext";
|
|
2063
|
+
obj[key].value = "<br><br>" + Util.fileView(`/uploads/${MYMODEL.routeName}/`, data[key], {withIcon: true});
|
|
2064
|
+
break;
|
|
2065
|
+
case "switch" :
|
|
2066
|
+
obj[key].type = "plaintext";
|
|
2067
|
+
if (widgets[key].inline) {
|
|
2068
|
+
prepend = `<br>`
|
|
2069
|
+
}
|
|
2070
|
+
if (widgets[key].float) {
|
|
2071
|
+
prepend = `<br>`
|
|
2072
|
+
}
|
|
2073
|
+
value = data[key] ? widgets[key].fields[data[key]] : widgets[key].fields[0];
|
|
2074
|
+
obj[key].value = `${prepend}<div class="purple-border">${value}</div>`;
|
|
2075
|
+
break;
|
|
2076
|
+
case "relation" :
|
|
2077
|
+
obj[key].type = "text";
|
|
2078
|
+
obj[key].value = relations[key + "Object"][data[key]] || "";
|
|
2079
|
+
break;
|
|
2080
|
+
case "select" :
|
|
2081
|
+
obj[key].type = "text";
|
|
2082
|
+
obj[key].value = widgets[key].fields[[data[key]]] || "";
|
|
2083
|
+
break;
|
|
2084
|
+
case "radio" :
|
|
2085
|
+
obj[key].type = "text";
|
|
2086
|
+
obj[key].value = widgets[key].fields[[data[key]]] || "";
|
|
2087
|
+
break;
|
|
2088
|
+
case "datepicker" :
|
|
2089
|
+
obj[key].type = "text";
|
|
2090
|
+
obj[key].value = Util.dateSql(data[key], widgets[key].format) || "";
|
|
2091
|
+
break;
|
|
2092
|
+
case "editor" :
|
|
2093
|
+
obj[key].type = "textarea";
|
|
2094
|
+
obj[key].value = data[key] || "";
|
|
2095
|
+
break;
|
|
2096
|
+
case "range" :
|
|
2097
|
+
obj[key].type = "text";
|
|
2098
|
+
obj[key].value = data[key] || "";
|
|
2099
|
+
break;
|
|
2100
|
+
case "typeahead" :
|
|
2101
|
+
obj[key].type = "text";
|
|
2102
|
+
obj[key].value = relations[key + "Object"][data[key]] || "";
|
|
2103
|
+
break;
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
//forms.build[key] = cForm.build(obj[key]);
|
|
2107
|
+
}
|
|
2108
|
+
forms.users = zRoute.formUser(relations, data);
|
|
2109
|
+
return forms;
|
|
2110
|
+
};
|
|
2111
|
+
|
|
2112
|
+
zRoute.usersCommon = (res) => {
|
|
2113
|
+
return {
|
|
2114
|
+
company_id: res.locals.companyId || 1,
|
|
2115
|
+
updated_by: res.locals.userId || 1,
|
|
2116
|
+
created_by: res.locals.userId || 1,
|
|
2117
|
+
created_at: Util.now(),
|
|
2118
|
+
updated_at: Util.now()
|
|
2119
|
+
}
|
|
2120
|
+
};
|
|
2121
|
+
|
|
2122
|
+
zRoute.viewTable = async (req, res, MYMODEL, results, isPreview, hasKeys = "") => {
|
|
2123
|
+
isPreview = isPreview || false;
|
|
2124
|
+
let data = {};
|
|
2125
|
+
let widgets = MYMODEL.widgets;
|
|
2126
|
+
let widgetsArray = Object.keys(widgets);
|
|
2127
|
+
let routeName = MYMODEL.routeName;
|
|
2128
|
+
let hasIdeEditor = false;
|
|
2129
|
+
let hasLexical = false;
|
|
2130
|
+
let editors = [];
|
|
2131
|
+
let lexicals = {};
|
|
2132
|
+
let row = {};
|
|
2133
|
+
for (let key in results) {
|
|
2134
|
+
if (Util.in_array(key, widgetsArray)) {
|
|
2135
|
+
let widgetName = widgets[key].name;
|
|
2136
|
+
let html = '';
|
|
2137
|
+
let arr = [];
|
|
2138
|
+
switch (widgetName) {
|
|
2139
|
+
case "datepicker" :
|
|
2140
|
+
data[key] = Util.dateSql(results[key], widgets[key].format || "");
|
|
2141
|
+
break;
|
|
2142
|
+
case "color" :
|
|
2143
|
+
data[key] = `<input type="color" value="${results[key]}">`;
|
|
2144
|
+
break;
|
|
2145
|
+
case "number" :
|
|
2146
|
+
data[key] = Util.formatNumber(results[key]);
|
|
2147
|
+
break;
|
|
2148
|
+
case "image" :
|
|
2149
|
+
if (hasKeys) {
|
|
2150
|
+
data[key] = Util.fileView("/uploads/" + hasKeys + "/", results[key]);
|
|
2151
|
+
} else {
|
|
2152
|
+
data[key] = Util.fileView("/uploads/" + routeName + "/", results[key]);
|
|
2153
|
+
}
|
|
2154
|
+
break;
|
|
2155
|
+
case "file" :
|
|
2156
|
+
if (hasKeys) {
|
|
2157
|
+
data[key] = Util.fileView("/uploads/" + hasKeys + "/", results[key]);
|
|
2158
|
+
} else {
|
|
2159
|
+
data[key] = Util.fileView("/uploads/" + routeName + "/", results[key]);
|
|
2160
|
+
}
|
|
2161
|
+
break;
|
|
2162
|
+
case "password" :
|
|
2163
|
+
data[key] = "xxxxxxxx";
|
|
2164
|
+
break;
|
|
2165
|
+
case "datetime" :
|
|
2166
|
+
data[key] = Util.timeSql(results[key], widgets[key].format || "");
|
|
2167
|
+
break;
|
|
2168
|
+
case "switch" :
|
|
2169
|
+
data[key] = widgets[key].fields[results[key]] || "";
|
|
2170
|
+
break;
|
|
2171
|
+
case "select" :
|
|
2172
|
+
data[key] = widgets[key].fields[results[key]] || "";
|
|
2173
|
+
break;
|
|
2174
|
+
case "radio" :
|
|
2175
|
+
data[key] = widgets[key].fields[results[key]] || "";
|
|
2176
|
+
break;
|
|
2177
|
+
case "relation" :
|
|
2178
|
+
if (results[key]) {
|
|
2179
|
+
row = await connection.result({
|
|
2180
|
+
table: widgets[key].table,
|
|
2181
|
+
select: widgets[key].fields[1] + " as zname",
|
|
2182
|
+
where: {id: results[key]}
|
|
2183
|
+
}) || {};
|
|
2184
|
+
}
|
|
2185
|
+
data[key] = !row.zname ? "" : row.zname;
|
|
2186
|
+
break;
|
|
2187
|
+
case "typeahead" :
|
|
2188
|
+
if (results[key]) {
|
|
2189
|
+
row = await connection.result({
|
|
2190
|
+
table: widgets[key].table,
|
|
2191
|
+
select: widgets[key].fields[1] + " as zname",
|
|
2192
|
+
where: {id: results[key]}
|
|
2193
|
+
}) || {};
|
|
2194
|
+
}
|
|
2195
|
+
data[key] = !row.zname ? "" : row.zname;
|
|
2196
|
+
break;
|
|
2197
|
+
case "dropdown_multi" :
|
|
2198
|
+
rows = await connection.results({
|
|
2199
|
+
select: widgets[key].fields.join(",") + "as zname",
|
|
2200
|
+
table: widgets[key].table
|
|
2201
|
+
});
|
|
2202
|
+
let valArr = Util.arrayToList(results[key], Util.arrayWithObject(rows, "id", "zname"))
|
|
2203
|
+
data[key] = typeof valArr == "object" ? valArr.join("<br>") : valArr;
|
|
2204
|
+
break;
|
|
2205
|
+
case "dropdown_chain" :
|
|
2206
|
+
if (results[key]) {
|
|
2207
|
+
row = await connection.result({
|
|
2208
|
+
table: widgets[key].table,
|
|
2209
|
+
select: widgets[key].fields[1] + " as zname",
|
|
2210
|
+
where: {id: results[key]}
|
|
2211
|
+
}) || {};
|
|
2212
|
+
}
|
|
2213
|
+
data[key] = !row.zname ? "" : row.zname;
|
|
2214
|
+
break;
|
|
2215
|
+
|
|
2216
|
+
case "dropdown_checkbox" :
|
|
2217
|
+
arr = widgets[key].fields || [];
|
|
2218
|
+
let val = results[key] || [];
|
|
2219
|
+
arr.map(item => {
|
|
2220
|
+
var checked = val.includes(item) ? 'checked="checked"' : "";
|
|
2221
|
+
html += `<div class="checkbox">
|
|
2222
|
+
<label class="">
|
|
2223
|
+
<input type="checkbox" ${checked} >
|
|
2224
|
+
${item}
|
|
2225
|
+
</label>
|
|
2226
|
+
</div>`;
|
|
2227
|
+
})
|
|
2228
|
+
data[key] = html;
|
|
2229
|
+
break;
|
|
2230
|
+
|
|
2231
|
+
case "ide_editor" :
|
|
2232
|
+
hasIdeEditor = true;
|
|
2233
|
+
editors.push(key);
|
|
2234
|
+
const editorValue = !results ? "" : Util.replaceAll(results[key], "</script>", `<//script>`);
|
|
2235
|
+
//data[key] = editorValue;
|
|
2236
|
+
moduleLib.addScript(req, res, "var ide_editor_" + key + " = `" + editorValue + "` ");
|
|
2237
|
+
break;
|
|
2238
|
+
case "lexical" :
|
|
2239
|
+
hasLexical = true;
|
|
2240
|
+
/*
|
|
2241
|
+
lexicals[key] = results[key];
|
|
2242
|
+
data[key] = `<div id="lexical${key}"></div><div id="text${key}" style="display:none"></div><div id="container${key}"></div>`;
|
|
2243
|
+
*/
|
|
2244
|
+
break;
|
|
2245
|
+
case "json" :
|
|
2246
|
+
data[key] = results[key] ? JSON.stringify(results[key], undefined, 2) : "";
|
|
2247
|
+
break;
|
|
2248
|
+
case "table" :
|
|
2249
|
+
let tableClass = isPreview ? "" : "table-striped table-hover";
|
|
2250
|
+
//let html = '';
|
|
2251
|
+
|
|
2252
|
+
html = `<table class="table ${tableClass}">`;
|
|
2253
|
+
html += `<tr>`;
|
|
2254
|
+
let MODEL_TABLE = require("./../models/" + MYMODEL.widgets[key].table);
|
|
2255
|
+
var nots = [...CONFIG.generator.notRenderField, ...['no', 'actionColumn']];
|
|
2256
|
+
var visibles = MODEL_TABLE.grids.visibles || [];
|
|
2257
|
+
var invisibles = MODEL_TABLE.grids.invisibles || [];
|
|
2258
|
+
var obj = {}
|
|
2259
|
+
visibles.forEach(function (item) {
|
|
2260
|
+
if (!Util.in_array(item, nots)) {
|
|
2261
|
+
obj[item] = MODEL_TABLE.labels[item];
|
|
2262
|
+
html += `<th>${MODEL_TABLE.labels[item]}</th>`;
|
|
2263
|
+
}
|
|
2264
|
+
});
|
|
2265
|
+
invisibles.forEach(function (item) {
|
|
2266
|
+
if (!Util.in_array(item, nots)) {
|
|
2267
|
+
obj[item] = MODEL_TABLE.labels[item];
|
|
2268
|
+
html += `<th>${MODEL_TABLE.labels[item]}</th>`;
|
|
2269
|
+
}
|
|
2270
|
+
});
|
|
2271
|
+
html += `</tr>`;
|
|
2272
|
+
arr = results[key] || [];
|
|
2273
|
+
for (let i = 0; i < arr.length; i++) {
|
|
2274
|
+
var item = arr[i];
|
|
2275
|
+
var data_table = await zRoute.viewTable(req, res, MODEL_TABLE, item, false, `${MYMODEL.table}/${key}`);
|
|
2276
|
+
html += `<tr>`;
|
|
2277
|
+
for (var k in obj) {
|
|
2278
|
+
html += `<td>${data_table[k]}</td>`;
|
|
2279
|
+
}
|
|
2280
|
+
html += `</tr>`;
|
|
2281
|
+
}
|
|
2282
|
+
html += `</table>`;
|
|
2283
|
+
data[key] = html;
|
|
2284
|
+
break;
|
|
2285
|
+
|
|
2286
|
+
default :
|
|
2287
|
+
data[key] = results[key];
|
|
2288
|
+
}
|
|
2289
|
+
} else {
|
|
2290
|
+
data[key] = results[key];
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2293
|
+
if (hasIdeEditor) {
|
|
2294
|
+
var contentScript = '';
|
|
2295
|
+
editors.forEach(function (item) {
|
|
2296
|
+
contentScript += `var editor_${item} = ace.edit("editor_${item}");
|
|
2297
|
+
editor_${item}.getSession().setMode("ace/mode/${widgets[item].language}");
|
|
2298
|
+
editor_${item}.setValue(ace_value(ide_editor_${item}));
|
|
2299
|
+
$("#editor_${item}").css({height:${widgets[item].height ? widgets[item].height : 400}});
|
|
2300
|
+
`;
|
|
2301
|
+
});
|
|
2302
|
+
moduleLib.ideCDN(req, res);
|
|
2303
|
+
moduleLib.addScript(req, res, contentScript)
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
if (hasLexical) {
|
|
2307
|
+
/* var scriptForm = '';
|
|
2308
|
+
moduleLib.lexical(req,res);
|
|
2309
|
+
for(var key in lexicals) {
|
|
2310
|
+
scriptForm += `document.addEventListener("DOMContentLoaded", () => {
|
|
2311
|
+
window.buildLexicalEditor("lexical${key}");
|
|
2312
|
+
});
|
|
2313
|
+
setTimeout(function () {
|
|
2314
|
+
window.importFile(window.LexicalEditor,${JSON.stringify(lexicals[key])});
|
|
2315
|
+
$(".toolbar").hide();
|
|
2316
|
+
$(".${key} .ContentEditable__root").focus();
|
|
2317
|
+
$(".action-button .lock").click();
|
|
2318
|
+
$(".actions").hide();
|
|
2319
|
+
$("#text${key}").html(window.LexicalGetContent);
|
|
2320
|
+
}, 1000);
|
|
2321
|
+
`
|
|
2322
|
+
};
|
|
2323
|
+
moduleLib.addScript(req,res,scriptForm);*/
|
|
2324
|
+
}
|
|
2325
|
+
return data;
|
|
2326
|
+
};
|
|
2327
|
+
|
|
2328
|
+
|
|
2329
|
+
//generate all scripts in one line
|
|
2330
|
+
zRoute.moduleLib = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
|
|
2331
|
+
//check a file in directory
|
|
2332
|
+
//make a directory
|
|
2333
|
+
let table = MYMODEL.table;
|
|
2334
|
+
let path_script = `${dirRoot}/public/runtime/script/${table}`;
|
|
2335
|
+
Util.dirExist(path_script,true);
|
|
2336
|
+
let path_head = `${dirRoot}/public/runtime/head/${table}`;
|
|
2337
|
+
Util.dirExist(path_head,true);
|
|
2338
|
+
let path_end = `${dirRoot}/public/runtime/end/${table}`;
|
|
2339
|
+
Util.dirExist(path_end,true);
|
|
2340
|
+
let files = Util.getAllFiles(path_script);
|
|
2341
|
+
let head = res.locals.moduleHead;
|
|
2342
|
+
let end = res.locals.moduleEnd;
|
|
2343
|
+
if(files.length) {
|
|
2344
|
+
let head_files = Util.getAllFiles(path_head);
|
|
2345
|
+
let end_files = Util.getAllFiles(path_end);
|
|
2346
|
+
if(head_files.length) {
|
|
2347
|
+
head += Util.readFile(`${path_head}/head.txt`);
|
|
2348
|
+
}
|
|
2349
|
+
if(end_files.length) {
|
|
2350
|
+
end += Util.readFile(`${path_end}/end.txt`);
|
|
2351
|
+
}
|
|
2352
|
+
end += `<script src="/runtime/script/${table}/${files[0]}"></script>`;
|
|
2353
|
+
} else {
|
|
2354
|
+
let jsObj = zRoute.generateJS(req, res, MYMODEL, relations);
|
|
2355
|
+
let time = new Date().getTime();
|
|
2356
|
+
Util.deleteAllFiles(path_head);
|
|
2357
|
+
Util.deleteAllFiles(path_end);
|
|
2358
|
+
//minify js
|
|
2359
|
+
const uglifyJS = require("uglify-js");
|
|
2360
|
+
Util.writeFile(`${path_script}/${time}.js`, uglifyJS.minify(jsObj.script));
|
|
2361
|
+
Util.writeFile(`${path_head}/head.txt`, jsObj.head);
|
|
2362
|
+
Util.writeFile(`${path_end}/end.txt`, jsObj.end);
|
|
2363
|
+
end += `<script src="/runtime/script/${table}/${time}/.js"></script>`;
|
|
2364
|
+
if(jsObj.head) {
|
|
2365
|
+
head +=jsObj.head;
|
|
2366
|
+
}
|
|
2367
|
+
if(jsObj.end) {
|
|
2368
|
+
end += jsObj.end;
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
if(head) {
|
|
2373
|
+
res.locals.moduleHead = head;
|
|
2374
|
+
}
|
|
2375
|
+
if(end) {
|
|
2376
|
+
res.locals.moduleEnd = end;
|
|
2377
|
+
}
|
|
2378
|
+
};
|
|
2379
|
+
|
|
2380
|
+
/*
|
|
2381
|
+
Generate javascript code into runtime folder
|
|
2382
|
+
*/
|
|
2383
|
+
zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
|
|
2384
|
+
//add additional script
|
|
2385
|
+
let lib_css = '';
|
|
2386
|
+
let scriptForm = '';
|
|
2387
|
+
let lib_js = '';
|
|
2388
|
+
let headObj = {};
|
|
2389
|
+
let endObj = {};
|
|
2390
|
+
if (zForms) {
|
|
2391
|
+
//moduleLib.addScript(req, res, zForms.scriptGroup);
|
|
2392
|
+
//scriptForm += zForms.scriptGroup;
|
|
2393
|
+
}
|
|
2394
|
+
let obj = {};
|
|
2395
|
+
let widgets = MYMODEL.widgets,
|
|
2396
|
+
widgetsArray = Object.keys(widgets) || [];
|
|
2397
|
+
let hasDatePicker = false;
|
|
2398
|
+
let hasNumber = false;
|
|
2399
|
+
let hasClockPicker = false;
|
|
2400
|
+
let hasEditor = false;
|
|
2401
|
+
let hasDateTimePicker = false;
|
|
2402
|
+
let hasTable = false;
|
|
2403
|
+
let chainsObj = {}
|
|
2404
|
+
let chainsArr = [];
|
|
2405
|
+
let hasChain = false;
|
|
2406
|
+
let hasIde = false;
|
|
2407
|
+
let hasTinymce = false;
|
|
2408
|
+
let defaultScript = "";
|
|
2409
|
+
let hasTags = false;
|
|
2410
|
+
let hasLexical = false;
|
|
2411
|
+
let lexicals = [];
|
|
2412
|
+
let hasAttributes = [];
|
|
2413
|
+
for (let key in widgets) {
|
|
2414
|
+
if (widgets[key].name == "datepicker") {
|
|
2415
|
+
hasDatePicker = true;
|
|
2416
|
+
} else if (widgets[key].name == "number") {
|
|
2417
|
+
hasNumber = true;
|
|
2418
|
+
} else if (widgets[key].name == "clockpicker") {
|
|
2419
|
+
hasClockPicker = true;
|
|
2420
|
+
} else if (widgets[key].name == "editor") {
|
|
2421
|
+
hasEditor = true;
|
|
2422
|
+
} else if (widgets[key].name == "ide_editor") {
|
|
2423
|
+
hasIde = true;
|
|
2424
|
+
} else if (widgets[key].name == "switch") {
|
|
2425
|
+
let switchObj = moduleLib.switch(req, res, `#${key}`, widgets[key].fields);
|
|
2426
|
+
scriptForm += switchObj.script;
|
|
2427
|
+
headObj.switch = switchObj.head;
|
|
2428
|
+
endObj.switch = switchObj.end;
|
|
2429
|
+
} else if (widgets[key].name == "typeahead") {
|
|
2430
|
+
let typeaheadObj = moduleLib.typeahead(req, res, `#${key}Typeahead`, relations[key]);
|
|
2431
|
+
scriptForm += typeaheadObj.script;
|
|
2432
|
+
headObj.typeahead = typeaheadObj.head;
|
|
2433
|
+
endObj.typeahead = typeaheadObj.end;
|
|
2434
|
+
} else if (widgets[key].name == "datetime") {
|
|
2435
|
+
hasDateTimePicker = true;
|
|
2436
|
+
} else if (widgets[key].name == "table") {
|
|
2437
|
+
hasTable = true;
|
|
2438
|
+
} else if (widgets[key].name == "tags") {
|
|
2439
|
+
hasTags = true;
|
|
2440
|
+
} else if (widgets[key].name == "lexical") {
|
|
2441
|
+
hasLexical = true;
|
|
2442
|
+
lexicals.push(key);
|
|
2443
|
+
} else if (widgets[key].name == "tinymce") {
|
|
2444
|
+
hasTinymce = true;
|
|
2445
|
+
}
|
|
2446
|
+
// has chains
|
|
2447
|
+
if (widgets[key].name == "relation") {
|
|
2448
|
+
if (widgets[key].isChain) {
|
|
2449
|
+
if (widgets[key].chains.length) {
|
|
2450
|
+
chainsObj[key] = widgets[key].chains;
|
|
2451
|
+
hasChain = true;
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
//relation_all_attributes
|
|
2455
|
+
if (widgets[key].isAttributes) {
|
|
2456
|
+
hasAttributes.push(key);
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
if (hasDatePicker) {
|
|
2461
|
+
let datePickerObj = moduleLib.datepicker(req, res);
|
|
2462
|
+
scriptForm += datePickerObj.script;
|
|
2463
|
+
headObj.datepicker = datePickerObj.head;
|
|
2464
|
+
endObj.datepicker = datePickerObj.end;
|
|
2465
|
+
}
|
|
2466
|
+
if (hasNumber) {
|
|
2467
|
+
let numberObj = moduleLib.number(req, res);
|
|
2468
|
+
scriptForm += numberObj.script;
|
|
2469
|
+
headObj.number = numberObj.head;
|
|
2470
|
+
endObj.number = numberObj.end;
|
|
2471
|
+
}
|
|
2472
|
+
if (hasClockPicker) {
|
|
2473
|
+
let clockpickerObj = moduleLib.clockpicker(req, res);
|
|
2474
|
+
scriptForm += clockpickerObj.script;
|
|
2475
|
+
headObj.clockpicker = clockpickerObj.head;
|
|
2476
|
+
endObj.clockpicker = clockpickerObj.end;
|
|
2477
|
+
}
|
|
2478
|
+
if (hasEditor) {
|
|
2479
|
+
let editorObj = moduleLib.editor(req, res);
|
|
2480
|
+
scriptForm += editorObj.script;
|
|
2481
|
+
headObj.editor = editorObj.head;
|
|
2482
|
+
endObj.editor = editorObj.end;
|
|
2483
|
+
}
|
|
2484
|
+
if (hasDateTimePicker) {
|
|
2485
|
+
let datetimepickerObj = moduleLib.datetimepicker(req, res);
|
|
2486
|
+
scriptForm += datetimepickerObj.script;
|
|
2487
|
+
headObj.datetimepicker = datetimepickerObj.head;
|
|
2488
|
+
endObj.datetimepicker = datetimepickerObj.end;
|
|
2489
|
+
}
|
|
2490
|
+
/*if (hasTable) {
|
|
2491
|
+
scriptForm += moduleLib.script(req, res, MYMODEL.table);
|
|
2492
|
+
}*/
|
|
2493
|
+
if (hasIde) {
|
|
2494
|
+
let ideCDNObj = moduleLib.ideCDN(req, res);
|
|
2495
|
+
//scriptForm += ideCDNObj.script;
|
|
2496
|
+
//headObj.ideCDN = ideCDNObj.head;
|
|
2497
|
+
endObj.ideCDN = ideCDNObj.end;
|
|
2498
|
+
}
|
|
2499
|
+
if (hasTags) {
|
|
2500
|
+
let tagsObj = moduleLib.tags(req, res);
|
|
2501
|
+
scriptForm += tagsObj.script;
|
|
2502
|
+
headObj.tags = tagsObj.head;
|
|
2503
|
+
endObj.tags = tagsObj.end;
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
if (hasTinymce) {
|
|
2507
|
+
let tinymceObj = moduleLib.tinymce(req, res);
|
|
2508
|
+
scriptForm += tinymceObj.script;
|
|
2509
|
+
headObj.tinymce = tinymceObj.head;
|
|
2510
|
+
endObj.tinymce = tinymceObj.end;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
if (hasLexical) {
|
|
2514
|
+
moduleLib.lexical(req, res);
|
|
2515
|
+
lexicals.forEach(function (lexical) {
|
|
2516
|
+
scriptForm += `document.addEventListener("DOMContentLoaded", () => {
|
|
2517
|
+
window.buildLexicalEditor("${lexical}");
|
|
2518
|
+
});`
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
if (hasChain) {
|
|
2523
|
+
for (let key in chainsObj) {
|
|
2524
|
+
if (chainsObj[key].length > 0) {
|
|
2525
|
+
scriptForm += `$("body").on("change", "#${key}", function () {`;
|
|
2526
|
+
chainsObj[key].forEach(function (objItem) {
|
|
2527
|
+
scriptForm += `chains("${key}","${objItem.table}","${objItem.target}","${objItem.column}","${objItem.name}", $("#${objItem.target}").val());`;
|
|
2528
|
+
});
|
|
2529
|
+
scriptForm += `});${Util.newLine}`;
|
|
2530
|
+
chainsObj[key].forEach(function (objItem) {
|
|
2531
|
+
scriptForm += ` if($("#${objItem.target}").val()){`
|
|
2532
|
+
scriptForm += `chains("${key}","${objItem.table}","${objItem.target}","${objItem.column}","${objItem.name}", $("#${objItem.target}").val());`;
|
|
2533
|
+
scriptForm += `}${Util.newLine}`
|
|
2534
|
+
})
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
defaultScript = `${Util.newLine} $(function () {
|
|
2540
|
+
$(".isfile").each(function (index, value) {
|
|
2541
|
+
let filename = $(this).attr("data-filename") || "";
|
|
2542
|
+
let id = $(this).attr("data-id");
|
|
2543
|
+
let table = $(this).attr("data-table") || " ";
|
|
2544
|
+
let width = $(this).attr("data-width") || "300";
|
|
2545
|
+
if (filename.length > 3) {
|
|
2546
|
+
if(filename.includes('https:')) {
|
|
2547
|
+
$("#file"+id).attr("src",filename);
|
|
2548
|
+
} else {
|
|
2549
|
+
let ext = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
|
|
2550
|
+
if (ext == "gif" || ext == "png" || ext == "jpeg" || ext == "jpg" || ext == "bmp" || ext == "webp" || ext == "jiff" || ext == "svg") {
|
|
2551
|
+
$("#file"+id).attr("src","/uploads/"+table+"/"+filename).attr("width",width+"px");
|
|
2552
|
+
} else {
|
|
2553
|
+
let file = 'file.png';
|
|
2554
|
+
if(ext == "docx" || ext == "doc") {
|
|
2555
|
+
file = 'word.png'
|
|
2556
|
+
} else if(ext == 'xls' || ext == 'xlsx') {
|
|
2557
|
+
file = 'excel.png'
|
|
2558
|
+
} else if(ext == 'pdf') {
|
|
2559
|
+
file = 'pdf.png'
|
|
2560
|
+
} else if(ext == 'ppt' || ext == 'pptx'){
|
|
2561
|
+
file = 'ppt.png';
|
|
2562
|
+
} else if(ext == 'txt') {
|
|
2563
|
+
file = 'txt.png';
|
|
2564
|
+
} else if(ext == 'zip') {
|
|
2565
|
+
file = 'zip.jpg';
|
|
2566
|
+
} else if(ext == 'rar') {
|
|
2567
|
+
file = 'rar.jpg';
|
|
2568
|
+
} else if(ext == 'rar') {
|
|
2569
|
+
file = 'file.png';
|
|
2570
|
+
}
|
|
2571
|
+
$("#file"+id).attr("src","/img/"+file).attr("height","45px").attr("width","45px").addClass("boxy-small");
|
|
2572
|
+
}
|
|
2573
|
+
$("#file"+id).on("click", function () {
|
|
2574
|
+
location.href = "/uploads/"+table+"/"+filename;
|
|
2575
|
+
});
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
if($(this).data("required") == true) {
|
|
2579
|
+
var imageElement = "#file"+id;
|
|
2580
|
+
if(!$(imageElement).attr("src")) {
|
|
2581
|
+
$("#"+id).attr("required",true);
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
});
|
|
2585
|
+
});`;
|
|
2586
|
+
|
|
2587
|
+
for (let keys in widgets) {
|
|
2588
|
+
let widgetName = widgets[keys].name;
|
|
2589
|
+
switch (widgetName) {
|
|
2590
|
+
case "multi_line_editor" :
|
|
2591
|
+
scriptForm += `$(".text-toggle").on("click", function(){
|
|
2592
|
+
let editorId = $(this).data("id");
|
|
2593
|
+
$("#"+editorId).attr("type","text");
|
|
2594
|
+
$("#a_"+editorId).hide();
|
|
2595
|
+
$("#"+editorId).show();
|
|
2596
|
+
});
|
|
2597
|
+
|
|
2598
|
+
$(".editor-value").on("change",function(index,item){
|
|
2599
|
+
if($(this).attr("type") == "text") {
|
|
2600
|
+
if($(this).val()) {
|
|
2601
|
+
var editorId = $(this).data("id");
|
|
2602
|
+
$("#a_"+editorId).html($(this).val()).show();
|
|
2603
|
+
$(this).attr("type","hidden");
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
});`;
|
|
2607
|
+
break;
|
|
2608
|
+
|
|
2609
|
+
case "dropdown_multi" :
|
|
2610
|
+
scriptForm += ` $("#dropdownadd${keys}").on("click", function () {
|
|
2611
|
+
var val = $("#${keys}").val();
|
|
2612
|
+
if(val == ""){
|
|
2613
|
+
alert("Please select data");
|
|
2614
|
+
return false;
|
|
2615
|
+
}
|
|
2616
|
+
var count = $(".span${keys}").length;
|
|
2617
|
+
var data = "<span class='span${keys}' > "+(count+1)+". <input type='hidden' name='${MYMODEL.table}[${keys}][]' value='"+val+"' /> " + $("#${keys} option:selected").text()+" <i class='fa fa-trash pointer text-danger pull-right' onclick='$(this).closest(\`span\`).remove();' title='Delete'></i><br></span>";
|
|
2618
|
+
$("#dropdownbox${keys}").append(data);
|
|
2619
|
+
$("#${keys}").val("");
|
|
2620
|
+
});${Util.newLine}`;
|
|
2621
|
+
break;
|
|
2622
|
+
|
|
2623
|
+
case "table" :
|
|
2624
|
+
let MODEL_TABLE = require("./../models/" + MYMODEL.widgets[keys].table);
|
|
2625
|
+
//let MODEL_TABLE_RELATIONS = await zRoute.relations(req, res, MODEL_TABLE.table);
|
|
2626
|
+
//relations[key + "TABLE"]
|
|
2627
|
+
let MODEL_TABLE_RELATIONS = relations[keys + "TABLE"];
|
|
2628
|
+
let zForm = zRoute.formField(req, res, MODEL_TABLE, MODEL_TABLE_RELATIONS);
|
|
2629
|
+
zRoute.moduleLib(req, res, MODEL_TABLE, MODEL_TABLE_RELATIONS, zForms);
|
|
2630
|
+
let trash = `trash_${keys}_${MYMODEL.widgets[keys].table}`;
|
|
2631
|
+
let trtd = '';
|
|
2632
|
+
for (let key in relations[keys]) {
|
|
2633
|
+
obj = zForm.obj[key] || {}
|
|
2634
|
+
let name = MYMODEL.table + "[" + keys + "][${increment}][" + key + "]";
|
|
2635
|
+
obj.name = name;
|
|
2636
|
+
//obj.class = MYMODEL.table + "_" + keys + "_" + key;
|
|
2637
|
+
obj.class = `${MYMODEL.table}_${keys}_${key} form-control`;
|
|
2638
|
+
obj.id = key;
|
|
2639
|
+
obj.options = {
|
|
2640
|
+
"data-name": key,
|
|
2641
|
+
"data-id": obj.class
|
|
2642
|
+
};
|
|
2643
|
+
trtd += `<td class="td_${key}_${MYMODEL.widgets[keys].table}">${cForm.field(obj)}</td>`;
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
trtd += `<td style="vertical-align:top"><span class="fas fa-trash-alt ${trash}" ></span></td></tr>`;
|
|
2647
|
+
let subname = MYMODEL.table + "_" + keys;
|
|
2648
|
+
scriptForm += `$("table").on("click", ".${trash}", function () {$(this).closest('tr').remove();});`;
|
|
2649
|
+
scriptForm += Util.newLine;
|
|
2650
|
+
scriptForm += 'var append' + keys + ' = function (increment) {return `<tr data-id="${increment}" data-name="' + MYMODEL.table + '[' + keys + ']">';
|
|
2651
|
+
scriptForm += trtd;
|
|
2652
|
+
scriptForm += "`}";
|
|
2653
|
+
scriptForm += Util.newLine;
|
|
2654
|
+
scriptForm += `var append${keys}Max = $('tbody#body-${keys}>tr').length;${Util.newLine}`;
|
|
2655
|
+
scriptForm += `function ${keys}Handler(){
|
|
2656
|
+
var index = $("#body-${keys}>tr").length || 0;
|
|
2657
|
+
$("#body-${keys}>tr").each(function (index, tr) {
|
|
2658
|
+
let dataname = $(tr).data("name") || "";
|
|
2659
|
+
$(tr).attr("data-id", index);
|
|
2660
|
+
if(dataname != "") {
|
|
2661
|
+
var inputs = $(tr).find("input");
|
|
2662
|
+
inputs.each(function (i,input) {
|
|
2663
|
+
if($(input).data("name")){
|
|
2664
|
+
$(input).removeAttr("name");
|
|
2665
|
+
$(input).attr("name",dataname+"["+index+"]["+$(input).data("name")+"]");
|
|
2666
|
+
}
|
|
2667
|
+
if($(input).attr("type") == "file") {
|
|
2668
|
+
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
|
|
2672
|
+
var selects = $(tr).find("select");
|
|
2673
|
+
selects.each(function (i,input) {
|
|
2674
|
+
if($(input).data("name")){
|
|
2675
|
+
$(input).removeAttr("name");
|
|
2676
|
+
$(input).attr("name",dataname+"["+index+"]["+$(input).data("name")+"]");
|
|
2677
|
+
}
|
|
2678
|
+
});
|
|
2679
|
+
|
|
2680
|
+
var textareas = $(tr).find("textarea");
|
|
2681
|
+
textareas.each(function (i,input) {
|
|
2682
|
+
if($(input).data("name")){
|
|
2683
|
+
$(input).removeAttr("name");
|
|
2684
|
+
$(input).attr("name",dataname+"["+index+"]["+$(input).data("name")+"]");
|
|
2685
|
+
}
|
|
2686
|
+
});
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
}); ${Util.newLine}};${Util.newLine}`;
|
|
2690
|
+
|
|
2691
|
+
scriptForm += ` $(function () {
|
|
2692
|
+
$('#add${keys}').on('click',function(){
|
|
2693
|
+
$('#body-${keys}').append(append${keys}(append${keys}Max));
|
|
2694
|
+
append${keys}Max++;
|
|
2695
|
+
${keys}Handler();
|
|
2696
|
+
});
|
|
2697
|
+
var ${keys} = $("#body-${keys}").data("value") ? $("#body-${keys}").data("value") : [];
|
|
2698
|
+
${keys}.forEach(function (myobj, index) {
|
|
2699
|
+
$("#body-${keys}").append(append${keys}(index));
|
|
2700
|
+
${keys}Handler();
|
|
2701
|
+
for(var key in myobj){
|
|
2702
|
+
if($(".${subname}_" + key).eq(index).attr("type") == "checkbox" && myobj[key] == 1){
|
|
2703
|
+
$(".${subname}_" + key).eq(index).prop("checked", true);
|
|
2704
|
+
$(".${subname}_" + key).eq(index).val(myobj[key] ? myobj[key] : '');
|
|
2705
|
+
} else if($(".${subname}_" + key).eq(index).attr("type") == "file"){
|
|
2706
|
+
var myimg = myobj[key] ? myobj[key] : '';
|
|
2707
|
+
var pathName = "/uploads/${MYMODEL.table}/${keys}/";
|
|
2708
|
+
if(myimg) {
|
|
2709
|
+
var filename = filenamex = pathName+myimg;
|
|
2710
|
+
if (!myimg.match(/\\.(jpg|jpeg|png|gif|svg|jiff)$/i)) {
|
|
2711
|
+
filename = "/img/file.png";
|
|
2712
|
+
}
|
|
2713
|
+
$(".${subname}_" + key).eq(index).closest("TD").find("img").attr("src",filename).addClass("boxy");
|
|
2714
|
+
$(".${subname}_" + key).eq(index).closest("TD").append('<a href="'+filenamex+'" target="_blank" style="font-size: 12px">'+myimg+'</a>');
|
|
2715
|
+
}
|
|
2716
|
+
} else {
|
|
2717
|
+
$(".${subname}_" + key).eq(index).val(myobj[key] ? myobj[key] : '');
|
|
2718
|
+
}
|
|
2719
|
+
|
|
2720
|
+
}
|
|
2721
|
+
append${keys}Max = index + 1;
|
|
2722
|
+
});
|
|
2723
|
+
});${Util.newLine}`;
|
|
2724
|
+
break;
|
|
2725
|
+
|
|
2726
|
+
case "ide_editor" :
|
|
2727
|
+
//var additionalScripts = `if (!!session.$worker) {session.$worker.send("setOptions", [{"esversion": 9,"esnext": false,}]);}`;
|
|
2728
|
+
let script_annotaions = '';
|
|
2729
|
+
let script_enabled = '';
|
|
2730
|
+
let script_looping = '';
|
|
2731
|
+
if (widgets[keys].language == "javascript") {
|
|
2732
|
+
script_annotaions = `editor_${keys}.session.setOption("useWorker", true);`;
|
|
2733
|
+
script_enabled = `editor_${keys}.session.setOption("useWorker", true);`;
|
|
2734
|
+
script_looping = `
|
|
2735
|
+
var errors = editor_${keys}.getSession().getAnnotations().filter(a=>a.type==='error');
|
|
2736
|
+
arr = [];
|
|
2737
|
+
errors.forEach(function(erItem) {
|
|
2738
|
+
if(erItem.text == 'Missing ";" before statement') {
|
|
2739
|
+
} else {
|
|
2740
|
+
arr.push(erItem);
|
|
2741
|
+
}
|
|
2742
|
+
});
|
|
2743
|
+
editor_${keys}.getSession().setAnnotations(arr);
|
|
2744
|
+
editor_${keys}.session.setOption("useWorker", true);
|
|
2745
|
+
`;
|
|
2746
|
+
}
|
|
2747
|
+
scriptForm += `var editor_${keys} = ace.edit("editor_${keys}");
|
|
2748
|
+
editor_${keys}.getSession().setMode("ace/mode/${widgets[keys].language}");
|
|
2749
|
+
editor_${keys}.setValue(ace_value(ide_editor_${keys}));
|
|
2750
|
+
$("#${keys}").text(ace_value(ide_editor_${keys}));
|
|
2751
|
+
$("#editor_${keys}").css({height:${widgets[keys].height ? widgets[keys].height : 400}});
|
|
2752
|
+
${script_annotaions}
|
|
2753
|
+
editor_${keys}.on("change",function(e,session){
|
|
2754
|
+
$("#${keys}").text(editor_${keys}.getValue());
|
|
2755
|
+
});
|
|
2756
|
+
`;
|
|
2757
|
+
|
|
2758
|
+
break;
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
if(hasAttributes) {
|
|
2763
|
+
hasAttributes.forEach(function (item) {
|
|
2764
|
+
let tableItem = MYMODEL.widgets[item].table;
|
|
2765
|
+
scriptForm += `
|
|
2766
|
+
function getAttribute_${item}(cb){
|
|
2767
|
+
ajaxPost('/${MYMODEL.table}/get_attributes',{id:$('#${item}').val(),table:'${tableItem}'},function(dt){cb(dt);});
|
|
2768
|
+
};
|
|
2769
|
+
`;
|
|
2770
|
+
});
|
|
2771
|
+
}
|
|
2772
|
+
scriptForm += defaultScript;
|
|
2773
|
+
|
|
2774
|
+
let head = '';
|
|
2775
|
+
let end = '';
|
|
2776
|
+
for(let key in headObj) {
|
|
2777
|
+
if(headObj[key]){
|
|
2778
|
+
head += headObj[key];
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
for(let key in endObj) {
|
|
2782
|
+
if(endObj[key]) {
|
|
2783
|
+
end += endObj[key];
|
|
2784
|
+
}
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
return {
|
|
2788
|
+
script : scriptForm,
|
|
2789
|
+
head : head,
|
|
2790
|
+
end : end
|
|
2791
|
+
}
|
|
2792
|
+
};
|
|
2793
|
+
|
|
2794
|
+
/*
|
|
2795
|
+
MySQL CRUD with context
|
|
2796
|
+
*/
|
|
2797
|
+
zRoute.insertSQL = async (req, res, table, data) => {
|
|
2798
|
+
let MYMODEL = require("./../models/" + table);
|
|
2799
|
+
let fields = MYMODEL.keys;
|
|
2800
|
+
if (fields.includes("company_id")) data.company_id = res.locals.companyId || 1;
|
|
2801
|
+
if (fields.includes("updated_at")) data.updated_at = Util.now();
|
|
2802
|
+
if (fields.includes("created_at")) data.created_at = Util.now();
|
|
2803
|
+
if (fields.includes("updated_by")) data.updated_by = res.locals.userId || 1;
|
|
2804
|
+
if (fields.includes("created_by")) data.created_by = res.locals.userId || 1;
|
|
2805
|
+
const result = await connection.insert({table: table, data: data});
|
|
2806
|
+
zRoute.modelsCacheRenew(table, res.locals.companyId);
|
|
2807
|
+
return result;
|
|
2808
|
+
};
|
|
2809
|
+
|
|
2810
|
+
zRoute.updateSQL = async (req, res, table, data, whereData) => {
|
|
2811
|
+
let MYMODEL = require("./../models/" + table);
|
|
2812
|
+
let fields = MYMODEL.keys;
|
|
2813
|
+
if (fields.includes('updated_at')) {
|
|
2814
|
+
data.updated_at = Util.now();
|
|
2815
|
+
}
|
|
2816
|
+
if (fields.includes('updated_by')) {
|
|
2817
|
+
data.updated_by = res.locals.userId;
|
|
2818
|
+
}
|
|
2819
|
+
//check if has table and image/file
|
|
2820
|
+
let hasImages = false;
|
|
2821
|
+
let tables = [];
|
|
2822
|
+
let tableFields = {}
|
|
2823
|
+
for (let key in MYMODEL.widgets) {
|
|
2824
|
+
if (MYMODEL.widgets[key].name == "table") {
|
|
2825
|
+
tableFields[key] = [];
|
|
2826
|
+
const MYMODEL_TABLE = require("./../models/" + MYMODEL.widgets[key].table);
|
|
2827
|
+
for (let q in MYMODEL_TABLE.widgets) {
|
|
2828
|
+
if (MYMODEL_TABLE.widgets[q].name == "file" || MYMODEL_TABLE.widgets[q].name == "image") {
|
|
2829
|
+
hasImages = true;
|
|
2830
|
+
tables.push(key);
|
|
2831
|
+
tableFields[key].push(q);
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
if (hasImages) {
|
|
2837
|
+
let result = await connection.result({
|
|
2838
|
+
table: MYMODEL.table,
|
|
2839
|
+
where: whereData
|
|
2840
|
+
});
|
|
2841
|
+
tables.forEach((item) => {
|
|
2842
|
+
let dataTables = data[item] ? JSON.parse(data[item]) : [];
|
|
2843
|
+
let temp = [];
|
|
2844
|
+
if (dataTables.length) {
|
|
2845
|
+
dataTables.forEach((obj, index) => {
|
|
2846
|
+
tableFields[item].forEach((key) => {
|
|
2847
|
+
if (!obj[key]) {
|
|
2848
|
+
let resultItem = result[item];
|
|
2849
|
+
if(resultItem && Object.prototype.hasOwnProperty.call(resultItem,index)) {
|
|
2850
|
+
let resultItemIndex = resultItem[index];
|
|
2851
|
+
if(resultItemIndex && Object.prototype.hasOwnProperty.call(resultItemIndex,key)) {
|
|
2852
|
+
obj[key] = !result[item][index] ? "" : result[item][index][key];
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
});
|
|
2857
|
+
temp.push(obj);
|
|
2858
|
+
});
|
|
2859
|
+
data[item] = JSON.stringify(temp);
|
|
2860
|
+
}
|
|
2861
|
+
});
|
|
2862
|
+
}
|
|
2863
|
+
delete data.created_at;
|
|
2864
|
+
delete data.created_by;
|
|
2865
|
+
const result = await connection.update({table: table, where: whereData, data: data});
|
|
2866
|
+
zRoute.modelsCacheRenew(table, res.locals.companyId);
|
|
2867
|
+
return result;
|
|
2868
|
+
};
|
|
2869
|
+
|
|
2870
|
+
zRoute.deleteSQL = async (table, id, company_id) => {
|
|
2871
|
+
try {
|
|
2872
|
+
const where = {
|
|
2873
|
+
id: id,
|
|
2874
|
+
company_id: company_id
|
|
2875
|
+
};
|
|
2876
|
+
const results = await connection.results({
|
|
2877
|
+
table: table,
|
|
2878
|
+
where: where
|
|
2879
|
+
});
|
|
2880
|
+
if (results.length) {
|
|
2881
|
+
await connection.delete({table: table, where: where});
|
|
2882
|
+
zRoute.modelsCacheRenew(table, company_id);
|
|
2883
|
+
} else {
|
|
2884
|
+
throw Error('Data not found');
|
|
2885
|
+
}
|
|
2886
|
+
return results[0];
|
|
2887
|
+
} catch (e) {
|
|
2888
|
+
throw Error(e.toString());
|
|
2889
|
+
}
|
|
2890
|
+
};
|
|
2891
|
+
|
|
2892
|
+
//for import
|
|
2893
|
+
zRoute.import = async (req, res, MYMODEL) => {
|
|
2894
|
+
const userId = res.locals[CONFIG.generator.userId];
|
|
2895
|
+
const room = res.locals.token;
|
|
2896
|
+
let progress = 0;
|
|
2897
|
+
let datas = [];
|
|
2898
|
+
let headers = [];
|
|
2899
|
+
let dataObj = {};
|
|
2900
|
+
let fields = Object.keys(MYMODEL.fields);
|
|
2901
|
+
dataObj.type = MYMODEL.routeName;
|
|
2902
|
+
let jsonObj = {
|
|
2903
|
+
progress: progress,
|
|
2904
|
+
headers: headers,
|
|
2905
|
+
datas: datas
|
|
2906
|
+
};
|
|
2907
|
+
let json = Util.jsonSuccess(LANGUAGE['import_success']);
|
|
2908
|
+
try {
|
|
2909
|
+
if (Object.keys(req.files).length == 0) {
|
|
2910
|
+
return res.json(Util.flashError(LANGUAGE['import_no_file']));
|
|
2911
|
+
}
|
|
2912
|
+
} catch (err) {
|
|
2913
|
+
return res.json(Util.flashError(err.toString()));
|
|
2914
|
+
}
|
|
2915
|
+
const filename = `${dirRoot}/public/excel/tmp/${Util.generateUnique()}.xlsx`;
|
|
2916
|
+
let excelFile = req.files.excel, labels = MYMODEL.labels, keys = {};
|
|
2917
|
+
if(!excelFile) {
|
|
2918
|
+
return res.json(Util.flashError(LANGUAGE['import_no_file']));
|
|
2919
|
+
}
|
|
2920
|
+
await Util.moveFile(excelFile, filename);
|
|
2921
|
+
io.to(room).emit('message', LANGUAGE['import_process']);
|
|
2922
|
+
const toJson = excelToJson({source: fs.readFileSync(filename)});
|
|
2923
|
+
let result;
|
|
2924
|
+
for (let prop in toJson) {
|
|
2925
|
+
let i = 0;
|
|
2926
|
+
if (i == 0) result = toJson[prop];
|
|
2927
|
+
i++;
|
|
2928
|
+
}
|
|
2929
|
+
if (!result.length) {
|
|
2930
|
+
let message = "No Data Found!!. Please uploading an excel file into 1 sheet only. Can not Multiple sheets";
|
|
2931
|
+
io.to(room).emit('message', message);
|
|
2932
|
+
res.json(Util.flashError(message));
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
//convert to table header
|
|
2936
|
+
let hd = '<tr>';
|
|
2937
|
+
for (let prop in result[1]) {
|
|
2938
|
+
let i = 0;
|
|
2939
|
+
keys[prop] = result[1][prop];
|
|
2940
|
+
hd += `<th>${result[0][prop]}</th>`;
|
|
2941
|
+
headers.push({i: i, prop: prop, value: result[0][prop]});
|
|
2942
|
+
i++;
|
|
2943
|
+
}
|
|
2944
|
+
hd += `<th>${LANGUAGE['noted']}</th>`;
|
|
2945
|
+
hd += `</tr>`;
|
|
2946
|
+
//convert to table header
|
|
2947
|
+
io.to(room).emit('import', hd);
|
|
2948
|
+
|
|
2949
|
+
let isInsert = true;
|
|
2950
|
+
hd += `<tr>`
|
|
2951
|
+
for (let i = 3; i < result.length; i++) {
|
|
2952
|
+
const data = {}
|
|
2953
|
+
hd += `${(i - 2)}`
|
|
2954
|
+
for (var prop in keys) {
|
|
2955
|
+
let value = result[i][prop];
|
|
2956
|
+
if (value) {
|
|
2957
|
+
data[keys[prop]] = value;
|
|
2958
|
+
}
|
|
2959
|
+
hd += `<td>${value}</td>`
|
|
2960
|
+
if (keys[prop] == "id")
|
|
2961
|
+
isInsert = false;
|
|
2962
|
+
}
|
|
2963
|
+
try {
|
|
2964
|
+
if (isInsert) {
|
|
2965
|
+
if (Util.in_array("company_id", fields)) data.company_id = res.locals.companyId;
|
|
2966
|
+
if (Util.in_array("created_at", fields)) data.created_at = Util.now();
|
|
2967
|
+
if (Util.in_array("created_by", fields)) data.created_by = res.locals.userId;
|
|
2968
|
+
if (Util.in_array("updated_at", fields)) data.updated_at = Util.now();
|
|
2969
|
+
if (Util.in_array("updated_by", fields)) data.updated_by = res.locals.userId;
|
|
2970
|
+
await connection.insert({table: MYMODEL.table, data: data});
|
|
2971
|
+
} else {
|
|
2972
|
+
if (Util.in_array("updated_at", fields)) data.updated_at = Util.now();
|
|
2973
|
+
if (Util.in_array("updated_by", fields)) data.updated_by = res.locals.userId;
|
|
2974
|
+
var update = await connection.update({
|
|
2975
|
+
table: MYMODEL.table,
|
|
2976
|
+
data: data,
|
|
2977
|
+
where: {
|
|
2978
|
+
id: data.id
|
|
2979
|
+
}
|
|
2980
|
+
})
|
|
2981
|
+
}
|
|
2982
|
+
hd += `<td class='text text-success'>${LANGUAGE['success']}</td>`
|
|
2983
|
+
} catch (err) {
|
|
2984
|
+
hd += `<td class='text text-danger'>${err.toString()}</td>`
|
|
2985
|
+
}
|
|
2986
|
+
hd += '</tr>';
|
|
2987
|
+
io.to(room).emit('import', hd);
|
|
2988
|
+
}
|
|
2989
|
+
hd += '';
|
|
2990
|
+
io.to(room).emit('import', hd);
|
|
2991
|
+
fs.removeSync(filename);
|
|
2992
|
+
if (myCache.has(MYMODEL.table)) {
|
|
2993
|
+
zRoute.modelsCacheRenew(req,res,MYMODEL);
|
|
2994
|
+
}
|
|
2995
|
+
res.json(json);
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2998
|
+
zRoute.buildFileModel = (json, index = 0) => {
|
|
2999
|
+
//let text = `module.exports = { ${Util.newLine}`;
|
|
3000
|
+
let text = '';
|
|
3001
|
+
let separator = index == 0 ? "" : Util.tabs(index);
|
|
3002
|
+
for (let key in json) {
|
|
3003
|
+
text += `${separator}${Util.tabs(2)} ${key} : `;
|
|
3004
|
+
let type = typeof json[key];
|
|
3005
|
+
if (type == "string") {
|
|
3006
|
+
let title = Util.replaceAll(json[key], '"', "'");
|
|
3007
|
+
text += `"${title}",${Util.newLine}`;
|
|
3008
|
+
} else if (Array.isArray(json[key])) {
|
|
3009
|
+
let textArray = '';
|
|
3010
|
+
let isStringArray = false;
|
|
3011
|
+
if (json[key].length == 0) {
|
|
3012
|
+
text += `[], ${Util.newLine}`;
|
|
3013
|
+
} else {
|
|
3014
|
+
json[key].map((item) => {
|
|
3015
|
+
if (typeof item == "string") {
|
|
3016
|
+
isStringArray = true;
|
|
3017
|
+
textArray += `${Util.tabs(3)} ${separator}"${Util.replaceAll(item, '"', "'")}",${Util.newLine}`;
|
|
3018
|
+
}
|
|
3019
|
+
});
|
|
3020
|
+
if (isStringArray) {
|
|
3021
|
+
text += `[${Util.newLine}${textArray.slice(0, -3)}${Util.newLine}${separator}${Util.tabs(2)} ], ${Util.newLine}`;
|
|
3022
|
+
} else {
|
|
3023
|
+
text += `${JSON.stringify(json[key])}, ${Util.newLine}`
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
} else if (type == "boolean") {
|
|
3028
|
+
text += json[key] ? "true" : "false";
|
|
3029
|
+
text += "," + Util.newLine;
|
|
3030
|
+
} else if (type == "object") {
|
|
3031
|
+
text += `{${Util.newLine}`;
|
|
3032
|
+
let textObjext = zRoute.buildFileModel(json[key], (index + 1));
|
|
3033
|
+
text += textObjext.slice(0, -3);
|
|
3034
|
+
text += `${Util.newLine}${separator}${Util.tabs(2)} }, ${Util.newLine}`
|
|
3035
|
+
} else {
|
|
3036
|
+
text += `"", ${Util.newLine}`
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
//text += '}';
|
|
3040
|
+
return text;
|
|
3041
|
+
};
|
|
3042
|
+
|
|
3043
|
+
zRoute.approversFooter = async (results, noActivity) => {
|
|
3044
|
+
noActivity = noActivity || false;
|
|
3045
|
+
let MYMODEL = require("./../models/zapprovals_details");
|
|
3046
|
+
let users = Util.arrayToObject(await connection.results({table: "zuser"}), "id");
|
|
3047
|
+
let html = '';
|
|
3048
|
+
let id = 0;
|
|
3049
|
+
let knowings = [], approvals = [];
|
|
3050
|
+
results.forEach(function (result) {
|
|
3051
|
+
if (result.type == 2) {
|
|
3052
|
+
let html = "";
|
|
3053
|
+
html += `<span class="status-approver">${MYMODEL.widgets.status.fields[result.status]}</span>`;
|
|
3054
|
+
html += `<p > <span style="text-decoration: underline;">${users[result.user_id].fullname}</span><span class="small-time"> ${users[result.user_id].position}</span></p>`;
|
|
3055
|
+
knowings.push(html);
|
|
3056
|
+
}
|
|
3057
|
+
if (result.type == 1) {
|
|
3058
|
+
let html = "";
|
|
3059
|
+
let sign = users[result.user_id].verify_signed && result.status == 3 ? `<img src="${CONFIG.app.url}/uploads/zuser/${users[result.user_id].verify_signed}" width="200">` : MYMODEL.widgets.status.fields[result.status];
|
|
3060
|
+
//var sign = "";
|
|
3061
|
+
html += `<span class="status-approver">${sign}</span>`;
|
|
3062
|
+
html += `<p class="footer-title"> <span style="text-decoration: underline;">${users[result.user_id].fullname}</span><span class="small-time"> ${users[result.user_id].position} <br> ${Util.dateFormat(result.updated_at, "DD MMM YYYY HH:mm")}</span></p>
|
|
3063
|
+
`;
|
|
3064
|
+
approvals.push(html);
|
|
3065
|
+
}
|
|
3066
|
+
})
|
|
3067
|
+
|
|
3068
|
+
let divColumn = (num) => {
|
|
3069
|
+
if (!num)
|
|
3070
|
+
return "";
|
|
3071
|
+
|
|
3072
|
+
if (num > 4) {
|
|
3073
|
+
num = num % 4;
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
var div = "";
|
|
3077
|
+
if (num == 1) {
|
|
3078
|
+
div = "col-12 text-center";
|
|
3079
|
+
} else if (num == 2) {
|
|
3080
|
+
div = "col-6 text-center";
|
|
3081
|
+
} else if (num == 3) {
|
|
3082
|
+
div = "col-4 text-center";
|
|
3083
|
+
} else {
|
|
3084
|
+
div = "col-3 text-center";
|
|
3085
|
+
}
|
|
3086
|
+
return div;
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3089
|
+
html += `<div class="row"><div class="col-12 text-center "><h5 class="knowing">Menyetujui</h5></div></div>`;
|
|
3090
|
+
html += `<div class="row d-flex justify-content-start align-items-end">`;
|
|
3091
|
+
let divClass = divColumn(approvals.length);
|
|
3092
|
+
approvals.forEach(function (item) {
|
|
3093
|
+
html += `<div class="${divClass}">`
|
|
3094
|
+
html += item;
|
|
3095
|
+
html += `</div>`;
|
|
3096
|
+
});
|
|
3097
|
+
html += `</div>`;
|
|
3098
|
+
|
|
3099
|
+
const knowingDiv = divColumn(knowings.length)
|
|
3100
|
+
if (knowings.length) {
|
|
3101
|
+
html += `<div class="row align-items-end"><div class="col-12 text-center mt-5"><h5 class="knowing">Mengetahui</h5></div></div>`;
|
|
3102
|
+
html += `<div class="row">`;
|
|
3103
|
+
knowings.forEach(function (item) {
|
|
3104
|
+
html += `<div class="${knowingDiv}">`
|
|
3105
|
+
html += item;
|
|
3106
|
+
html += `</div>`;
|
|
3107
|
+
})
|
|
3108
|
+
html += `</div>`;
|
|
3109
|
+
}
|
|
3110
|
+
return html;
|
|
3111
|
+
};
|
|
3112
|
+
|
|
3113
|
+
|
|
3114
|
+
/*
|
|
3115
|
+
Caches include WPA
|
|
3116
|
+
cache models in so it's no need call database repeatly
|
|
3117
|
+
*/
|
|
3118
|
+
|
|
3119
|
+
zRoute.modelsCache = async() => {
|
|
3120
|
+
let models = zRoute.MYMODELS() || {};
|
|
3121
|
+
delete models.zrole;
|
|
3122
|
+
delete models.zuser_company;
|
|
3123
|
+
let obj = {};
|
|
3124
|
+
let companies;
|
|
3125
|
+
let mustCaches = ['relation', 'typeahead', 'multi_line_editor', 'dropdown_multi'];
|
|
3126
|
+
let nots = ['created_by','updated_by'];
|
|
3127
|
+
for (let keys in models) {
|
|
3128
|
+
let widgets = models[keys].widgets;
|
|
3129
|
+
for (let key in widgets) {
|
|
3130
|
+
if (Util.in_array(widgets[key].name, mustCaches)) {
|
|
3131
|
+
let widget = widgets[key];
|
|
3132
|
+
let table = widget.table;
|
|
3133
|
+
if (widget.fields[1] != undefined) {
|
|
3134
|
+
if (!obj[table]) {
|
|
3135
|
+
obj[table] = {}
|
|
3136
|
+
}
|
|
3137
|
+
if(!Util.in_array(key,nots)){
|
|
3138
|
+
obj[table][`${keys}___${key}`] = `${widgets[key].fields[1]} as ${key}`;
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3141
|
+
}
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
companies = await connection.results({
|
|
3145
|
+
table : 'zcompany'
|
|
3146
|
+
});
|
|
3147
|
+
obj.zuser = {};
|
|
3148
|
+
obj.zuser = {
|
|
3149
|
+
created_by : 'fullname as created_by',
|
|
3150
|
+
updated_by : 'fullname as updated_by'
|
|
3151
|
+
};
|
|
3152
|
+
|
|
3153
|
+
try {
|
|
3154
|
+
for(let keys in obj) {
|
|
3155
|
+
let checks = await connection.query(`SELECT EXISTS ( SELECT 1 FROM pg_tables WHERE tablename = '${keys}') AS oke;`);
|
|
3156
|
+
if(checks[0].oke) {
|
|
3157
|
+
if (!Util.in_array(keys, zRoute.tableHasNoCompanyId)) {
|
|
3158
|
+
let selects = ``;
|
|
3159
|
+
for(let key in obj[keys]) {
|
|
3160
|
+
selects += `${obj[keys][key]},`;
|
|
3161
|
+
}
|
|
3162
|
+
selects += `id, company_id`;
|
|
3163
|
+
for(const company of companies) {
|
|
3164
|
+
const results = await connection.results({
|
|
3165
|
+
table: keys,
|
|
3166
|
+
select: selects,
|
|
3167
|
+
where : {
|
|
3168
|
+
company_id : company.id
|
|
3169
|
+
}
|
|
3170
|
+
});
|
|
3171
|
+
for (let key in obj[keys]) {
|
|
3172
|
+
const splits = key.split("___") || [];
|
|
3173
|
+
let item = splits.length > 1 ? splits[1] : key;
|
|
3174
|
+
let arr = [];
|
|
3175
|
+
for (const result of results) {
|
|
3176
|
+
arr.push({id: result.id, zname: result[item]});
|
|
3177
|
+
}
|
|
3178
|
+
const myarray = Util.sortArray(arr, 'zname');
|
|
3179
|
+
myCache.set(`${keys}_${key}_${company.id}`, myarray);
|
|
3180
|
+
}
|
|
3181
|
+
}
|
|
3182
|
+
}
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3185
|
+
} catch (e) {
|
|
3186
|
+
//debug(req,res,e.toString());
|
|
3187
|
+
console.log('modelsCache :',e.toString())
|
|
3188
|
+
}
|
|
3189
|
+
|
|
3190
|
+
return obj;
|
|
3191
|
+
};
|
|
3192
|
+
|
|
3193
|
+
zRoute.modelsCacheRenew = (table, companyId) => {
|
|
3194
|
+
if(myCache.has('MODELS_RELATIONS')) {
|
|
3195
|
+
let MODELS = myCache.get('MODELS_RELATIONS');
|
|
3196
|
+
let arr = Object.keys(MODELS) || [];
|
|
3197
|
+
let obj = MODELS[table] || {};
|
|
3198
|
+
if(Util.in_array(table,arr)) {
|
|
3199
|
+
let selects = '';
|
|
3200
|
+
for (let key in obj) {
|
|
3201
|
+
selects += `${obj[key]},`
|
|
3202
|
+
}
|
|
3203
|
+
selects += `id`;
|
|
3204
|
+
connection.results({
|
|
3205
|
+
select : selects,
|
|
3206
|
+
table : table,
|
|
3207
|
+
where : {
|
|
3208
|
+
company_id : companyId
|
|
3209
|
+
}
|
|
3210
|
+
}).then(function (results) {
|
|
3211
|
+
for (let key in obj) {
|
|
3212
|
+
const splits = key.split("___") || [];
|
|
3213
|
+
let item = splits.length > 1 ? splits[1] : key;
|
|
3214
|
+
let arr = [];
|
|
3215
|
+
for (const result of results) {
|
|
3216
|
+
arr.push({id: result.id, zname: result[item]});
|
|
3217
|
+
}
|
|
3218
|
+
const myarray = Util.sortArray(arr, 'zname');
|
|
3219
|
+
myCache.set(`${table}_${key}_${companyId}`, myarray);
|
|
3220
|
+
}
|
|
3221
|
+
});
|
|
3222
|
+
}
|
|
3223
|
+
}
|
|
3224
|
+
};
|
|
3225
|
+
|
|
3226
|
+
module.exports = zRoute;
|