zet-lib 6.0.2 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1342 +1,546 @@
1
1
  /**
2
2
  * Created by sintret dev on 10/1/2021.
3
3
  */
4
- const configGenerator = require("./config_generator");
5
- const fs = require("fs-extra");
6
4
  const path = require("path");
5
+ const fs = require("fs-extra");
6
+ const configGenerator = require("./config_generator");
7
7
  const generatorModel = require("./generatorModel");
8
- const connection = require('./connection');
9
- const Util = require('./Util');
8
+ const connection = require("./connection");
9
+ const Util = require("./Util");
10
+
10
11
  const generatorApp = {};
12
+ const asArray = (value) => (Array.isArray(value) ? value : []);
13
+ const isPlainObject = (value) => !!value && typeof value === "object" && !Array.isArray(value);
14
+ const hasOwn = (obj, key) => !!obj && Object.prototype.hasOwnProperty.call(obj, key);
15
+ const readFileSafe = (file, fallback = "") => {
16
+ try {
17
+ return fs.readFileSync(file, "utf-8");
18
+ } catch (err) {
19
+ return fallback;
20
+ }
21
+ };
22
+ const applyTokens = (content, tokens) => {
23
+ let out = content == null ? "" : String(content);
24
+ Object.keys(tokens).forEach((key) => {
25
+ out = Util.replaceAll(out, key, tokens[key] == null ? "" : String(tokens[key]));
26
+ });
27
+ return out;
28
+ };
29
+ const viewSourceKey = (filename) => String(filename).replace("_", "").replace(".", "_");
11
30
 
12
31
  generatorApp.DIRECTORY = path.join(__dirname, "views", "zgenerator");
13
32
  generatorApp.DIRECTORY_MODELS = path.join(__dirname, "models");
14
- generatorApp.DIRECTORY_ROUTES = path.join(__dirname, "routes");
33
+ generatorApp.DIRECTORY_ROUTES = path.join(__dirname, "routes");
15
34
  generatorApp.DIRECTORY_VIEWS = path.join(__dirname, "views");
16
35
  generatorApp.DIRECTORY_GENERATOR_VIEWS = path.join(generatorApp.DIRECTORY, "views");
17
36
 
18
- //generate model file
19
- generatorApp.CREATE_MODEL = async (MYMODEL) => {
20
- return generatorModel.create(MYMODEL);
21
- };
22
- generatorApp.CREATE_MODEL_API = async (columns, constraintList, MYMODEL) => {
23
- return generatorModel.createApi(columns, constraintList, MYMODEL);
37
+ const VIEW_FILES = [
38
+ "_form.ejs",
39
+ "create.ejs",
40
+ "createjs.ejs",
41
+ "import.ejs",
42
+ "importjs.ejs",
43
+ "index.ejs",
44
+ "indexcss.ejs",
45
+ "indexjs.ejs",
46
+ "update.ejs",
47
+ "updatejs.ejs",
48
+ "view.ejs",
49
+ "approval.ejs",
50
+ ];
51
+
52
+ const splitTabToken = (value) => {
53
+ if (typeof value !== "string" || !value.includes("___")) return null;
54
+ const parts = value.split("___");
55
+ return { name: parts[0], tab: parts[1] };
24
56
  };
25
57
 
26
- //genereate route file
27
- /*
28
- [[[TABLE_NAME]]]
29
- [[[HARDCODE_GRID]]]
30
- [[[ADDITIONAL_FIELDS_CREATE]]]
31
- ///additional_fields///
32
- */
33
-
34
- generatorApp.CREATE_ROUTER = async (MYMODEL, zFields) => {
35
- let CONTENT =
36
- zFields.router ||
37
- fs.readFileSync(path.join(generatorApp.DIRECTORY, "routerApp.ejs"), "utf-8");
38
- const zfields = await connection.result({
39
- table: "zfields",
40
- where: { table: MYMODEL.table },
41
- });
42
- const ADDITIONAL_FIELDS = generatorApp.ADDITIONAL_FIELDS(MYMODEL);
43
- const OBJ = {
44
- TABLE_NAME: MYMODEL.table,
45
- HARDCODE_GRID: zfields.hardcode_grid,
46
- ADDITIONAL_FIELDS_CREATE: ADDITIONAL_FIELDS.CREATE,
47
- ADDITIONAL_FIELDS_UPDATE: ADDITIONAL_FIELDS.UPDATE,
48
- BEFORE_CREATE: zfields.before_create || "",
49
- AFTER_CREATE: zfields.after_create || "",
50
- BEFORE_UPDATE: zfields.before_update || "",
51
- AFTER_UPDATE: zfields.after_update || "",
52
- BEFORE_DELETE: zfields.before_delete || "",
53
- AFTER_DELETE: zfields.after_delete || "",
54
- };
55
-
56
- for (let KEY in OBJ) {
57
- CONTENT = Util.replaceAll(CONTENT, "[[[" + KEY + "]]]", OBJ[KEY]);
58
+ const findTabKey = (item) => {
59
+ if (!Array.isArray(item)) return "";
60
+ for (let i = 0; i < item.length; i++) {
61
+ const zitems = item[i];
62
+ if (asArray(zitems).length && typeof zitems[0] === "string" && zitems[0].includes("___")) {
63
+ return zitems[0].split("___")[1];
58
64
  }
59
-
60
- fs.writeFileSync(
61
- path.join(generatorApp.DIRECTORY_ROUTES, MYMODEL.table + ".js"),
62
- CONTENT,
63
- "utf-8"
64
- );
65
+ }
66
+ return "";
65
67
  };
66
68
 
67
- generatorApp.CREATE_ROUTER_API = (MYMODEL, zfields) => {
68
- let CONTENT =
69
- zfields.router ||
70
- fs.readFileSync(path.join(generatorApp.DIRECTORY, "routerApp.ejs"), "utf-8");
71
- //var zfields = await connection.result({table: "zfields", where: {table: MYMODEL.table}});
72
- const ADDITIONAL_FIELDS = generatorApp.ADDITIONAL_FIELDS(MYMODEL);
73
- const OBJ = {
74
- TABLE_NAME: MYMODEL.table,
75
- HARDCODE_GRID: zfields.hardcode_grid,
76
- ADDITIONAL_FIELDS_CREATE: ADDITIONAL_FIELDS.CREATE,
77
- ADDITIONAL_FIELDS_UPDATE: ADDITIONAL_FIELDS.UPDATE,
78
- BEFORE_CREATE: zfields.before_create || "",
79
- AFTER_CREATE: zfields.after_create || "",
80
- BEFORE_UPDATE: zfields.before_update || "",
81
- AFTER_UPDATE: zfields.after_update || "",
82
- BEFORE_DELETE: zfields.before_delete || "",
83
- AFTER_DELETE: zfields.after_delete || "",
84
- };
85
-
86
- for (let KEY in OBJ) {
87
- CONTENT = Util.replaceAll(CONTENT, "[[[" + KEY + "]]]", OBJ[KEY]);
69
+ const stripTabNames = (item) => asArray(item).map((row) =>
70
+ asArray(row).map((value) => (typeof value === "string" && value.includes("___") ? value.split("___")[0] : value))
71
+ );
72
+
73
+ const assignContainerSide = (list, tabObj, used) => {
74
+ asArray(list).forEach((item) => {
75
+ if (typeof item === "string") {
76
+ const parsed = splitTabToken(item);
77
+ if (!parsed) return;
78
+ if (!tabObj[parsed.tab]) tabObj[parsed.tab] = [];
79
+ tabObj[parsed.tab].push(parsed.name);
80
+ used.push(item);
81
+ return;
88
82
  }
89
- //fs.writeFileSync(path.join(generatorApp.DIRECTORY_ROUTES, MYMODEL.table + ".js"), CONTENT, 'utf-8');
90
- return {
91
- filename: MYMODEL.table + ".js",
92
- content: CONTENT,
93
- };
94
- };
95
-
96
- //generate views file
97
- generatorApp.CREATE_VIEWS = async (MYMODEL, zFields) => {
98
- const views = [
99
- "_form.ejs",
100
- "create.ejs",
101
- "createjs.ejs",
102
- "import.ejs",
103
- "importjs.ejs",
104
- "index.ejs",
105
- "indexcss.ejs",
106
- "indexjs.ejs",
107
- "update.ejs",
108
- "updatejs.ejs",
109
- "view.ejs",
110
- "approval.ejs",
111
- "preview.ejs",
112
- ];
113
83
 
114
- const GENERATE_FORM = generatorApp.GENERATE_FORM(MYMODEL, zFields);
115
- const GENERATE_INDEXJS = await generatorApp.GENERATE_INDEXJS(MYMODEL);
116
- const GENERATE_VIEW = await generatorApp.GENERATE_VIEW(MYMODEL, zFields);
117
-
118
- // onkeydown="return event.key != 'Enter';"
119
- const OBJ = {
120
- "[[[NO_VALI_DATE_NOVALIDATE]]]": " ",
121
- "[[[GENERATE_FORM]]]": GENERATE_FORM,
122
- "[[[GENERATE_INDEXJS]]]": GENERATE_INDEXJS,
123
- "[[[GENERATE_VIEW]]]": GENERATE_VIEW,
124
- };
125
-
126
- const DIR_VIEW = path.join(generatorApp.DIRECTORY_VIEWS, MYMODEL.table);
127
- if (!fs.existsSync(DIR_VIEW)) {
128
- fs.mkdirSync(DIR_VIEW);
84
+ const keyname = findTabKey(item);
85
+ if (keyname) {
86
+ if (!tabObj[keyname]) tabObj[keyname] = [];
87
+ tabObj[keyname].push(stripTabNames(item));
88
+ used.push(item);
129
89
  }
130
-
131
- views.forEach(function async(item) {
132
- let name = item.replace("_", "");
133
- name = name.replace(".", "_");
134
- let source = zFields[name];
135
- if (source) {
136
- fs.writeFileSync(path.join(DIR_VIEW, item), source);
137
- } else {
138
- source = path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item);
139
- fs.copySync(source, path.join(DIR_VIEW, item));
140
- }
141
- console.log(path.join(DIR_VIEW, item));
142
- for (let KEY in OBJ) {
143
- generatorApp.MODIFIY(
144
- path.join(DIR_VIEW, item),
145
- path.join(DIR_VIEW, item),
146
- KEY,
147
- OBJ[KEY]
148
- );
149
- }
150
- });
90
+ });
151
91
  };
152
92
 
153
- generatorApp.CREATE_VIEWS_API = (MYMODEL, zFields) => {
154
- let datas = {};
155
- const views = [
156
- "_form.ejs",
157
- "create.ejs",
158
- "createjs.ejs",
159
- "import.ejs",
160
- "importjs.ejs",
161
- "index.ejs",
162
- "indexcss.ejs",
163
- "indexjs.ejs",
164
- "update.ejs",
165
- "updatejs.ejs",
166
- "view.ejs",
167
- "approval.ejs",
168
- ];
169
- const GENERATE_FORM = generatorApp.GENERATE_FORM(MYMODEL, zFields);
170
- const GENERATE_INDEXJS = generatorApp.GENERATE_INDEXJS(MYMODEL);
171
- const GENERATE_VIEW = generatorApp.GENERATE_VIEW(MYMODEL, zFields);
172
- const token = `views_${Util.generateUnique(10)}`;
173
-
174
- // onkeydown="return event.key != 'Enter';"
175
-
176
- const tabs = zFields.tabs ? zFields.tabs : [];
177
- const isTabs = tabs.length > 0 ? true : false;
178
- const novalidate = isTabs ? " novalidate " : "";
179
- const OBJ = {
180
- "[[[NO_VALI_DATE_NOVALIDATE]]]": novalidate,
181
- "[[[GENERATE_FORM]]]": GENERATE_FORM,
182
- "[[[GENERATE_INDEXJS]]]": GENERATE_INDEXJS,
183
- "[[[GENERATE_VIEW]]]": GENERATE_VIEW,
184
- };
185
-
186
- const DIR_VIEW = path.join(dirRoot, "public", "temp", token);
187
- if (!fs.existsSync(DIR_VIEW)) {
188
- fs.mkdirSync(DIR_VIEW);
189
- }
93
+ const containerObject = (left, right, oneColumn, tabs = []) => {
94
+ const leftObj = {};
95
+ const rightObj = {};
96
+ const oneColumnObj = {};
97
+ const leftUsed = [];
98
+ const rightUsed = [];
99
+ const oneUsed = [];
100
+
101
+ asArray(tabs).forEach((_, i) => {
102
+ const arrName = `arr${i}`;
103
+ leftObj[arrName] = [];
104
+ rightObj[arrName] = [];
105
+ oneColumnObj[arrName] = [];
106
+ });
107
+
108
+ assignContainerSide(left, leftObj, leftUsed);
109
+ assignContainerSide(right, rightObj, rightUsed);
110
+ assignContainerSide(oneColumn, oneColumnObj, oneUsed);
111
+
112
+ return {
113
+ left: asArray(left).filter((item) => !leftUsed.includes(item)),
114
+ right: asArray(right).filter((item) => !rightUsed.includes(item)),
115
+ oneColumn: asArray(oneColumn).filter((item) => !oneUsed.includes(item)),
116
+ tabLeft: leftObj,
117
+ tabRight: rightObj,
118
+ tabOneColumn: oneColumnObj,
119
+ };
120
+ };
190
121
 
191
- for (let i = 0; i < views.length; i++) {
192
- let item = views[i];
193
- let name = item.replace("_", "");
194
- name = name.replace(".", "_");
195
- let source = zFields.hasOwnProperty(name)
196
- ? zFields[name]
197
- : fs.readFileSync(path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item), {
198
- encoding: "utf8",
199
- flag: "r",
200
- });
201
- if (source) {
202
- fs.writeFileSync(path.join(DIR_VIEW, item), source);
203
- } else {
204
- source = fs.readFileSync(
205
- path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item),
206
- { encoding: "utf8", flag: "r" }
207
- );
208
- fs.copySync(source, path.join(DIR_VIEW, item));
209
- }
210
- for (let KEY in OBJ) {
211
- generatorApp.MODIFIY(
212
- path.join(DIR_VIEW, item),
213
- path.join(DIR_VIEW, item),
214
- KEY,
215
- OBJ[KEY]
216
- );
217
- }
218
- }
219
- for (let i = 0; i < views.length; i++) {
220
- const item = views[i];
221
- datas[item] = fs.readFileSync(path.join(DIR_VIEW, item), {
222
- encoding: "utf8",
223
- flag: "r",
224
- });
225
- }
226
- //remove directory
227
- fs.rmSync(DIR_VIEW, { recursive: true, force: true });
228
- return datas;
122
+ const splitFlatAndTabbed = (list) => {
123
+ const flat = [];
124
+ const tabbed = [];
125
+ asArray(list).forEach((item) => {
126
+ if (typeof item === "string") flat.push(item);
127
+ else tabbed.push(item);
128
+ });
129
+ return { flat, tabbed };
229
130
  };
230
131
 
231
- generatorApp.MODIFIY = (SOURCE, TARGET, REPLACE, REPLACE_NEW) => {
232
- const data = fs.readFileSync(SOURCE, "utf-8");
233
- const newValue = Util.replaceAll(data, REPLACE, REPLACE_NEW);
234
- fs.writeFileSync(TARGET, newValue, "utf-8");
235
- console.log(TARGET);
132
+ const fieldsForTab = (tabbed, arrName) => {
133
+ let found = [];
134
+ asArray(tabbed).forEach((item) => {
135
+ if (item && item[arrName]) found = item[arrName];
136
+ });
137
+ return asArray(found);
236
138
  };
237
139
 
238
- generatorApp.ADDITIONAL_FIELDS = (MYMODEL) => {
239
- const bytime = configGenerator.createdUpdatedAt;
240
- const byman = configGenerator.createdUpdatedBy;
241
- let create = [],
242
- update = [],
243
- str = "";
244
- const fields = MYMODEL.fields || {};
245
- for (let key in fields) {
246
- if (Util.in_array(key, bytime)) {
247
- create.push({ field: key, value: "Util.now()" });
248
- }
249
- if (Util.in_array(key, byman)) {
250
- create.push({ field: key, value: "res.locals.userId" });
251
- }
140
+ const formBuild = (arr, properties) => {
141
+ let out = "";
142
+ asArray(arr).forEach((item) => {
143
+ if (typeof item === "string") {
144
+ const prop = properties && properties[item];
145
+ if (!prop || !prop.values || prop.values.hidden) return;
146
+ out += prop.type === "custom"
147
+ ? `${Util.tabs(3)}<%- ${prop.values.code} %>${Util.newLine}`
148
+ : `${Util.tabs(3)}<%- zForms.build["${item}"] %>${Util.newLine}`;
149
+ return;
252
150
  }
253
- update = create.filter((item) => {
254
- return item.field.indexOf("create") < 0;
151
+
152
+ const cols = asArray(item);
153
+ if (!cols.length) return;
154
+ const colMd = `col-md-${12 / cols.length}`;
155
+ out += `${Util.newLine}${Util.tabs(3)}<div class="row">${Util.newLine}`;
156
+ cols.forEach((myitems) => {
157
+ out += `${Util.tabs(4)}<div class="${colMd}">${Util.newLine}`;
158
+ asArray(myitems).forEach((itemX) => {
159
+ const prop = properties && properties[itemX];
160
+ if (!prop) return;
161
+ out += prop.type === "custom"
162
+ ? `${Util.tabs(3)}<%- ${prop.values && prop.values.code} %>${Util.newLine}`
163
+ : `${Util.tabs(5)}<%- zForms.build["${itemX}"] %>${Util.newLine}`;
164
+ });
165
+ out += `${Util.tabs(4)}</div>${Util.newLine}`;
255
166
  });
256
- let widgets = MYMODEL.widgets;
257
- for (let key in widgets) {
258
- if (widgets[key].name == "number") {
259
- str += `${Util.tabs(2)}data.${key} = Util.replaceAll(data.${key},'.','')${
260
- Util.newLine
261
- }`;
262
- }
263
- }
264
- return {
265
- CREATE:
266
- str +
267
- create.reduce((result, item) => {
268
- return (
269
- result +
270
- `${Util.tabs(2)}data.${item.field} = ${item.value};${Util.newLine}`
271
- );
272
- }, ""),
273
- UPDATE:
274
- str +
275
- update.reduce((result, item) => {
276
- return (
277
- result +
278
- `${Util.tabs(2)}data.${item.field} = ${item.value};${Util.newLine}`
279
- );
280
- }, ""),
281
- };
167
+ out += `${Util.tabs(3)}</div>${Util.newLine}`;
168
+ });
169
+ return out;
282
170
  };
283
171
 
284
- generatorApp.GENERATE_INDEXJS = (MYMODEL) => {
285
- const fields = MYMODEL.fields;
286
- const widgets = MYMODEL.widgets;
287
- const widgetsArr = Object.keys(widgets) || [];
288
- let out = "";
289
- let itemTemplate = "";
290
- out += Util.newLine;
291
- for (const key in fields) {
292
- if (key != "company_id") {
293
- if (Util.in_array(key, widgetsArr)) {
294
- const widgetName = widgets[key].name;
295
- switch (widgetName) {
296
- case "text":
297
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
298
- Util.ejsOpen
299
- } attributeData.labels['${key}'] ${
300
- Util.ejsClose
301
- }", type:"text", width: 80}, ${Util.newLine} `;
302
- break;
303
- case "color":
304
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
305
- Util.ejsOpen
306
- } attributeData.labels['${key}'] ${
307
- Util.ejsClose
308
- }", type:"color", width: 50}, ${Util.newLine} `;
309
- break;
310
- case "textarea":
311
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
312
- Util.ejsOpen
313
- } attributeData.labels['${key}'] ${
314
- Util.ejsClose
315
- }", type:"text", itemTemplate: function (value) {return (value && value.length > 100) ? value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').substring(0,50) + '...' : value}, width: 90}, ${
316
- Util.newLine
317
- } `;
318
- break;
319
- case "number":
320
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
321
- Util.ejsOpen
322
- } attributeData.labels['${key}'] ${
323
- Util.ejsClose
324
- }", type:"text", itemTemplate: function (value) {return formatNumber(value)}, align: 'right', width: 70}, ${
325
- Util.newLine
326
- } `;
327
- break;
328
- case "image":
329
- itemTemplate = `function (value) { return value == null || value == '' ? '' : '<img width="60" height="60" src="/uploads/<%- routeName %>/'+value+'" class="img-circle" />'; }`;
330
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
331
- Util.ejsOpen
332
- } attributeData.labels['${key}'] ${
333
- Util.ejsClose
334
- }", type:"text", itemTemplate: ${itemTemplate}, align: 'right', width: 70}, ${
335
- Util.newLine
336
- } `;
337
- break;
338
- case "file":
339
- itemTemplate =
340
- 'function(value) { return value ? `<a href="/uploads/<%- routeName%>/${value}">${value}</a>`:""}';
341
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
342
- Util.ejsOpen
343
- } attributeData.labels['${key}'] ${
344
- Util.ejsClose
345
- }", type:"text", itemTemplate: ${itemTemplate}, width: 80}, ${
346
- Util.newLine
347
- } `;
348
- break;
349
- case "email":
350
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
351
- Util.ejsOpen
352
- } attributeData.labels['${key}'] ${
353
- Util.ejsClose
354
- }", type:"text", width: 80}, ${Util.newLine} `;
355
- break;
356
- case "password":
357
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
358
- Util.ejsOpen
359
- } attributeData.labels['${key}'] ${
360
- Util.ejsClose
361
- }", type:"text", itemTemplate: function (value) {return "xxxxxx"}, width: 80}, ${
362
- Util.newLine
363
- } `;
364
- break;
365
- case "datepicker":
366
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
367
- Util.ejsOpen
368
- } attributeData.labels['${key}'] ${
369
- Util.ejsClose
370
- }", type:"text", itemTemplate: function (value) {return value ? value == '0000-00-00' ? '' : moment(value).format('YYYY-MM-DD') : '';}, width: 80}, ${
371
- Util.newLine
372
- } `;
373
- break;
374
- case "datetime":
375
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
376
- Util.ejsOpen
377
- } attributeData.labels['${key}'] ${
378
- Util.ejsClose
379
- }", type:"text", itemTemplate: function (value) {return value ? value == '0000-00-00 00:00:00' ? '' : moment(value).format('YYYY-MM-DD HH:mm:ss') : '';}, width: 80}, ${
380
- Util.newLine
381
- } `;
382
- break;
383
- case "clockpicker":
384
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
385
- Util.ejsOpen
386
- } attributeData.labels['${key}'] ${
387
- Util.ejsClose
388
- }", type:"text", width: 80}, ${Util.newLine} `;
389
- break;
390
- case "switch":
391
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
392
- Util.ejsOpen
393
- } attributeData.labels['${key}'] ${
394
- Util.ejsClose
395
- }", type:"select", items: ${
396
- Util.ejsOpen
397
- } JSON.stringify(relations.${key}) ${
398
- Util.ejsClose
399
- }, valueField: 'id', textField: 'name', width: 50}, ${
400
- Util.newLine
401
- } `;
402
- break;
403
- case "editor":
404
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
405
- Util.ejsOpen
406
- } attributeData.labels['${key}'] ${
407
- Util.ejsClose
408
- }", type:"text", itemTemplate: function (value) {return (value && value.length > 100) ? value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').substring(0,50) + '...' : value}, width: 90}, ${
409
- Util.newLine
410
- } `;
411
- break;
412
- case "ide_editor":
413
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
414
- Util.ejsOpen
415
- } attributeData.labels['${key}'] ${
416
- Util.ejsClose
417
- }", type:"text", itemTemplate: function (value) {return (value && value.length > 100) ? value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').substring(0,50) + '...' : value}, width: 90}, ${
418
- Util.newLine
419
- } `;
420
- break;
421
- case "select":
422
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
423
- Util.ejsOpen
424
- } attributeData.labels['${key}'] ${
425
- Util.ejsClose
426
- }", type:"select", items: ${
427
- Util.ejsOpen
428
- } JSON.stringify(relations.${key}Row) ${
429
- Util.ejsClose
430
- }, valueField: "id", textField: "name", width: 80}, ${
431
- Util.newLine
432
- } `;
433
- break;
434
- case "relation":
435
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
436
- Util.ejsOpen
437
- } attributeData.labels['${key}'] ${
438
- Util.ejsClose
439
- }", type:"select", items: ${
440
- Util.ejsOpen
441
- } JSON.stringify(relations.${key}Row) ${
442
- Util.ejsClose
443
- }, valueField: "${Util.ejsOpen} relations.${key}[0] ${
444
- Util.ejsClose
445
- }", textField: "name", width: 80}, ${Util.newLine} `;
446
- break;
447
- case "typeahead":
448
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
449
- Util.ejsOpen
450
- } attributeData.labels['${key}'] ${
451
- Util.ejsClose
452
- }", type:"select", items: ${
453
- Util.ejsOpen
454
- } JSON.stringify(relations.${key}) ${
455
- Util.ejsClose
456
- }, valueField: "id", textField: "name", width: 80}, ${
457
- Util.newLine
458
- } `;
459
- break;
460
- case "table":
461
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
462
- Util.ejsOpen
463
- } attributeData.labels['${key}'] ${
464
- Util.ejsClose
465
- }", type:"text", itemTemplate: function (value) {return (value && value.length > 100) ? value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').substring(0,50) + '...' : value}, width: 90}, ${
466
- Util.newLine
467
- } `;
468
- break;
469
- case "dropdown_multi":
470
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
471
- Util.ejsOpen
472
- } attributeData.labels['${key}'] ${
473
- Util.ejsClose
474
- }", type:"select", itemTemplate: function (value) {return gridValues(value,${
475
- Util.ejsOpen
476
- } JSON.stringify(relations.${key}Row ) ${
477
- Util.ejsClose
478
- })}, items: ${Util.ejsOpen} JSON.stringify(relations.${key}) ${
479
- Util.ejsClose
480
- }, valueField: "id", textField: "name", width: 80}, ${
481
- Util.newLine
482
- } `;
483
- break;
484
- case "dropdown_chain":
485
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
486
- Util.ejsOpen
487
- } attributeData.labels['${key}'] ${
488
- Util.ejsClose
489
- }", type:"select", items: ${
490
- Util.ejsOpen
491
- } JSON.stringify(relations.${key}Row) ${
492
- Util.ejsClose
493
- }, valueField: "id", textField: "name", width: 80}, ${
494
- Util.newLine
495
- } `;
496
- break;
497
- case "dropdown_checkbox":
498
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
499
- Util.ejsOpen
500
- } attributeData.labels['${key}'] ${
501
- Util.ejsClose
502
- }", type:"text", itemTemplate: function (value) {return formatString(value)}, width: 90}, ${
503
- Util.newLine
504
- } `;
505
- break;
506
- case "virtual":
507
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
508
- Util.ejsOpen
509
- } attributeData.labels['${key}'] ${
510
- Util.ejsClose
511
- }", type:"text", width: 80}, ${Util.newLine} `;
512
- break;
513
-
514
- default:
515
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
516
- Util.ejsOpen
517
- } attributeData.labels['${key}'] ${
518
- Util.ejsClose
519
- }", type:"text", width: 80}, ${Util.newLine} `;
520
- break;
521
- }
522
- } else {
523
- out += `${Util.tabs(2)} ${key} : {name: "${key}", title: "${
524
- Util.ejsOpen
525
- } attributeData.labels['${key}'] ${
526
- Util.ejsClose
527
- }", type:"text", width: 80}, ${Util.newLine} `;
528
- }
529
- }
530
- }
531
-
532
- return out;
172
+ const formBuildDiv = (type = 1, obj = {}) => {
173
+ if (Number(type) === 1) {
174
+ return `${Util.tab}<div class="row">${Util.newLine}${Util.tabs(2)}<div class="col-md-12">${Util.newLine}` +
175
+ formBuild(obj.oneColumn, obj.properties) +
176
+ `${Util.tabs(2)}</div>${Util.newLine}${Util.tab}</div>${Util.newLine}`;
177
+ }
178
+ return `${Util.tab}<div class="row">${Util.newLine}` +
179
+ `${Util.tabs(2)}<div class="col-md-6">${Util.newLine}${formBuild(obj.left, obj.properties)}${Util.tabs(2)}</div>${Util.newLine}` +
180
+ `${Util.tabs(2)}<div class="col-md-6">${Util.newLine}${formBuild(obj.right, obj.properties)}${Util.tabs(2)}</div>${Util.newLine}` +
181
+ `${Util.tab}</div>${Util.newLine}`;
533
182
  };
534
183
 
535
- generatorApp.GENERATE_FORM = (MYMODEL, zFields) => {
536
- let others = zFields.others || {};
537
- if (Object.keys(others).length) {
538
- return generatorApp.GENERATE_FORM_WITH_CONTAINER(MYMODEL, zFields);
184
+ const generateForm = (properties, sorting, left = [], right = [], oneColumn = []) => {
185
+ const tables = [];
186
+ const oneColumns = [];
187
+ asArray(oneColumn).forEach((item) => {
188
+ if (typeof item === "string" && properties && properties[item] && properties[item].type === "table") {
189
+ tables.push(item);
539
190
  } else {
540
- return generatorApp.GENERATE_FORM_CLASSIC(MYMODEL, zFields);
191
+ oneColumns.push(item);
541
192
  }
193
+ });
194
+ const obj = {
195
+ left: asArray(left),
196
+ right: asArray(right),
197
+ oneColumn,
198
+ properties,
199
+ tables,
200
+ };
201
+ return asArray(sorting).map((item) => formBuildDiv(item, obj)).join("");
542
202
  };
543
203
 
544
- function containerObject(left, right, oneColumn, tabs = []) {
545
- /*
546
- For generator helper
547
- */
548
-
549
- let obj = {};
550
- let hasTabs = tabs.length;
551
- let leftObj = {},
552
- rightObj = {},
553
- oneColumnObj = {};
554
- let leftsNew = [],
555
- rightsNew = [],
556
- oneColumnsNew = [];
557
-
558
- if (hasTabs) {
559
- tabs.forEach(function (tab, i) {
560
- let arrName = `arr${i}`;
561
- if (!leftObj.hasOwnProperty(arrName)) {
562
- leftObj[arrName] = [];
563
- }
564
- if (!rightObj.hasOwnProperty(arrName)) {
565
- rightObj[arrName] = [];
566
- }
567
- if (!oneColumnObj.hasOwnProperty(arrName)) {
568
- oneColumnObj[arrName] = [];
569
- }
570
- });
571
- }
572
-
573
- left.forEach(function (item) {
574
- if (typeof item == "string") {
575
- if (item.includes("___")) {
576
- let arr = item.split("___");
577
- leftObj[arr[1]].push(arr[0]);
578
- leftsNew.push(item);
579
- }
580
- } else {
581
- let keyname = "";
582
- for (let i = 0; i < item.length; i++) {
583
- let zitems = item[i];
584
- if (zitems.length) {
585
- if (zitems[0].includes("___")) {
586
- keyname = zitems[0].split("___")[1];
587
- }
588
- }
589
- }
590
- //console.log(keyname)
591
- if (keyname) {
592
- let myarr = [];
593
- item.forEach(function (myitem) {
594
- let me = [];
595
- myitem.forEach(function (inem) {
596
- if (inem.includes("___")) {
597
- me.push(inem.split("___")[0]);
598
- } else {
599
- me.push(inem);
600
- }
601
- });
602
- myarr.push(me);
603
- });
604
- leftObj[keyname].push(myarr);
605
- leftsNew.push(item);
606
- } else {
607
- if (item.includes("___")) {
608
- let arr = item.split("___");
609
- leftObj[arr[1]].push(arr[0]);
610
- leftsNew.push(item);
611
- }
612
- }
613
- }
614
- });
615
-
616
- //right
617
- right.forEach(function (item) {
618
- if (typeof item == "string") {
619
- if (item.includes("___")) {
620
- let arr = item.split("___");
621
- rightObj[arr[1]].push(arr[0]);
622
- rightsNew.push(item);
623
- }
624
- } else {
625
- let keyname = "";
626
- for (let i = 0; i < item.length; i++) {
627
- let zitems = item[i];
628
- if (zitems.length) {
629
- if (zitems[0].includes("___")) {
630
- keyname = zitems[0].split("___")[1];
631
- }
632
- }
633
- }
634
- //console.log(keyname)
635
- if (keyname) {
636
- let myarr = [];
637
- item.forEach(function (myitem) {
638
- let me = [];
639
- myitem.forEach(function (inem) {
640
- if (inem.includes("___")) {
641
- me.push(inem.split("___")[0]);
642
- } else {
643
- me.push(inem);
644
- }
645
- });
646
- myarr.push(me);
647
- });
648
- rightObj[keyname].push(myarr);
649
- rightsNew.push(item);
650
- } else {
651
- if (item.includes("___")) {
652
- let arr = item.split("___");
653
- rightObj[arr[1]].push(arr[0]);
654
- rightsNew.push(item);
655
- }
656
- }
657
- }
658
- });
204
+ const renderTabNav = (tabs) => {
205
+ let out = `<ul class="nav nav-tabs" id="myTab" role="tablist">${Util.newLine}`;
206
+ asArray(tabs).forEach((tab, i) => {
207
+ const active = i === 0 ? "active" : "";
208
+ out += ` <li class="nav-item arr${i}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#arr${i}" type="button" role="tab" aria-controls="arr${i}" aria-selected="true">${tab}</button></li>${Util.newLine}`;
209
+ });
210
+ out += `</ul>${Util.newLine}`;
211
+ return out;
212
+ };
659
213
 
660
- //oneColumn
661
- oneColumn.forEach(function (item) {
662
- if (typeof item == "string") {
663
- if (item.includes("___")) {
664
- let arr = item.split("___");
665
- oneColumnObj[arr[1]].push(arr[0]);
666
- oneColumnsNew.push(item);
667
- }
668
- } else {
669
- let keyname = "";
670
- for (let i = 0; i < item.length; i++) {
671
- let zitems = item[i];
672
- if (zitems.length) {
673
- if (zitems[0].includes("___")) {
674
- keyname = zitems[0].split("___")[1];
675
- }
676
- }
677
- }
678
- //console.log(keyname)
679
- if (keyname) {
680
- let myarr = [];
681
- item.forEach(function (myitem) {
682
- let me = [];
683
- myitem.forEach(function (inem) {
684
- if (inem.includes("___")) {
685
- me.push(inem.split("___")[0]);
686
- } else {
687
- me.push(inem);
688
- }
689
- });
690
- myarr.push(me);
691
- });
692
- oneColumnObj[keyname].push(myarr);
693
- oneColumnsNew.push(item);
694
- } else {
695
- if (item.includes("___")) {
696
- let arr = item.split("___");
697
- oneColumnObj[arr[1]].push(arr[0]);
698
- oneColumnsNew.push(item);
699
- }
700
- }
701
- }
702
- });
214
+ const viewCreatedBy = () => `<div class="ps-lg-4 my-5 text-lg-start col-lg-3 mb-3 float-end">
215
+ <div class="dropdown">
216
+ <button class="btn boxy dropdown-toggle" type="button" id="viewCreatedBy" data-bs-toggle="dropdown" aria-expanded="false">
217
+ Last update : <%- zForms.users.updated_by %>
218
+ </button>
219
+ <ul class="dropdown-menu" aria-labelledby="viewCreatedBy">
220
+ <li><a class="dropdown-item" href="#">Updated at <%- zForms.users.updated_at %></a></li>
221
+ <li><a class="dropdown-item" href="#">Created at <%- zForms.users.created_at %></a></li>
222
+ <li><a class="dropdown-item" href="#">Created by <%- zForms.users.created_by %></a></li>
223
+ </ul>
224
+ </div>
225
+ </div>`;
703
226
 
704
- //caption left or right
705
- let datasLeft = left.filter((x) => !leftsNew.includes(x));
706
- let datasRight = right.filter((x) => !rightsNew.includes(x));
707
- let datasOneColumn = oneColumn.filter((x) => !oneColumnsNew.includes(x));
227
+ const viewApproval = () => `<div class="ps-lg-4 my-5 text-lg-start col-lg-3 mb-3 float-end">
228
+ <%- zForms.approval_history_table %>
229
+ </div>`;
708
230
 
709
- let myObject = {
710
- left: datasLeft || [],
711
- right: datasRight || [],
712
- oneColumn: datasOneColumn || [],
713
- tabLeft: leftObj || [],
714
- tabRight: rightObj || [],
715
- tabOneColumn: oneColumnObj || [],
716
- };
231
+ const ejsTitle = (key) => `${Util.ejsOpen} attributeData.labels['${key}'] ${Util.ejsClose}`;
232
+ const indexCol = (key, body) => `${Util.tabs(2)} ${key} : {name: "${key}", title: "${ejsTitle(key)}", ${body}}, ${Util.newLine}`;
233
+ const truncateTpl = `function (value) {return (value && value.length > 100) ? value.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').substring(0,50) + '...' : value}`;
234
+
235
+ const INDEXJS_WIDGET = {
236
+ text: (key) => indexCol(key, `type:"text", width: 80`),
237
+ color: (key) => indexCol(key, `type:"color", width: 50`),
238
+ textarea: (key) => indexCol(key, `type:"text", itemTemplate: ${truncateTpl}, width: 90`),
239
+ number: (key) => indexCol(key, `type:"text", itemTemplate: function (value) {return formatNumber(value)}, align: 'right', width: 70`),
240
+ image: (key) => indexCol(key, `type:"text", itemTemplate: function (value) { return value == null || value == '' ? '' : '<img width="60" height="60" src="/uploads/<%- routeName %>/'+value+'" class="img-circle" />'; }, align: 'right', width: 70`),
241
+ file: (key) => indexCol(key, `type:"text", itemTemplate: function(value) { return value ? \`<a href="/uploads/<%- routeName%>/\${value}">\${value}</a>\`:""}, width: 80`),
242
+ email: (key) => indexCol(key, `type:"text", width: 80`),
243
+ password: (key) => indexCol(key, `type:"text", itemTemplate: function (value) {return "xxxxxx"}, width: 80`),
244
+ datepicker: (key) => indexCol(key, `type:"text", itemTemplate: function (value) {return value ? value == '0000-00-00' ? '' : moment(value).format('YYYY-MM-DD') : '';}, width: 80`),
245
+ datetime: (key) => indexCol(key, `type:"text", itemTemplate: function (value) {return value ? value == '0000-00-00 00:00:00' ? '' : moment(value).format('YYYY-MM-DD HH:mm:ss') : '';}, width: 80`),
246
+ clockpicker: (key) => indexCol(key, `type:"text", width: 80`),
247
+ switch: (key) => indexCol(key, `type:"select", items: ${Util.ejsOpen} JSON.stringify(relations.${key}) ${Util.ejsClose}, valueField: 'id', textField: 'name', width: 50`),
248
+ editor: (key) => indexCol(key, `type:"text", itemTemplate: ${truncateTpl}, width: 90`),
249
+ ide_editor: (key) => indexCol(key, `type:"text", itemTemplate: ${truncateTpl}, width: 90`),
250
+ select: (key) => indexCol(key, `type:"select", items: ${Util.ejsOpen} JSON.stringify(relations.${key}Row) ${Util.ejsClose}, valueField: "id", textField: "name", width: 80`),
251
+ relation: (key) => indexCol(key, `type:"select", items: ${Util.ejsOpen} JSON.stringify(relations.${key}Row) ${Util.ejsClose}, valueField: "${Util.ejsOpen} relations.${key}[0] ${Util.ejsClose}", textField: "name", width: 80`),
252
+ typeahead: (key) => indexCol(key, `type:"select", items: ${Util.ejsOpen} JSON.stringify(relations.${key}) ${Util.ejsClose}, valueField: "id", textField: "name", width: 80`),
253
+ table: (key) => indexCol(key, `type:"text", itemTemplate: ${truncateTpl}, width: 90`),
254
+ dropdown_multi: (key) => indexCol(key, `type:"select", itemTemplate: function (value) {return gridValues(value,${Util.ejsOpen} JSON.stringify(relations.${key}Row ) ${Util.ejsClose})}, items: ${Util.ejsOpen} JSON.stringify(relations.${key}) ${Util.ejsClose}, valueField: "id", textField: "name", width: 80`),
255
+ dropdown_chain: (key) => indexCol(key, `type:"select", items: ${Util.ejsOpen} JSON.stringify(relations.${key}Row) ${Util.ejsClose}, valueField: "id", textField: "name", width: 80`),
256
+ dropdown_checkbox: (key) => indexCol(key, `type:"text", itemTemplate: function (value) {return formatString(value)}, width: 90`),
257
+ virtual: (key) => indexCol(key, `type:"text", width: 80`),
258
+ };
717
259
 
718
- return myObject;
719
- }
260
+ const routerTokens = (MYMODEL, zfields) => {
261
+ const extra = generatorApp.ADDITIONAL_FIELDS(MYMODEL);
262
+ const z = isPlainObject(zfields) ? zfields : {};
263
+ return {
264
+ "[[[TABLE_NAME]]]": MYMODEL.table || "",
265
+ "[[[HARDCODE_GRID]]]": z.hardcode_grid || "",
266
+ "[[[ADDITIONAL_FIELDS_CREATE]]]": extra.CREATE,
267
+ "[[[ADDITIONAL_FIELDS_UPDATE]]]": extra.UPDATE,
268
+ "[[[BEFORE_CREATE]]]": z.before_create || "",
269
+ "[[[AFTER_CREATE]]]": z.after_create || "",
270
+ "[[[BEFORE_UPDATE]]]": z.before_update || "",
271
+ "[[[AFTER_UPDATE]]]": z.after_update || "",
272
+ "[[[BEFORE_DELETE]]]": z.before_delete || "",
273
+ "[[[AFTER_DELETE]]]": z.after_delete || "",
274
+ };
275
+ };
720
276
 
721
- generatorApp.GENERATE_FORM_WITH_CONTAINER = (MYMODEL, zFields) => {
722
- let out = "";
723
- let others = zFields.others || {};
724
- let properties = zFields.properties || {};
725
- let labels = zFields.labels;
726
- let tabs = zFields.tabs ? zFields.tabs : [];
727
- let leftData = others.LEFT || [];
728
- let rightData = others.RIGHT || [];
729
- let oneColumnData = others.ONE_COLUMN || [];
730
- let sorting = zFields.sorting || [];
731
- var isTab = tabs.length ? true : false;
732
- let tables = [];
733
- let tabLeft = [],
734
- tabRight = [],
735
- tabOneColumn = [];
736
- let ALL_FIELDS = containerObject(leftData, rightData, oneColumnData, tabs);
737
- if (isTab) {
738
- out += `<ul class="nav nav-tabs" id="myTab" role="tablist">${Util.newLine}`;
739
- tabs.forEach(function (tab, i) {
740
- let arrName = `arr${i}`;
741
- let active = i == 0 ? "active" : "";
742
- out += ` <li class="nav-item ${arrName}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#arr${i}" type="button" role="tab" aria-controls="arr${i}" aria-selected="true">${tab}</button></li>${Util.newLine}`;
743
- });
744
- out += `</ul>${Util.newLine}`;
277
+ const defaultRouterContent = (zfields) =>
278
+ (zfields && zfields.router) || readFileSafe(path.join(generatorApp.DIRECTORY, "routerApp.ejs"));
745
279
 
746
- out += `<div class="tab-content" id="myTabContent">${Util.newLine}`;
747
- tabs.forEach(function (tab, i) {
748
- let arrName = `arr${i}`;
749
- let mytab = "";
750
- tabLeft = ALL_FIELDS.tabLeft[arrName];
751
- tabRight = ALL_FIELDS.tabRight[arrName];
752
- tabOneColumn = ALL_FIELDS.tabOneColumn[arrName];
753
- let obj = {
754
- left: tabLeft,
755
- right: tabRight,
756
- oneColumn: tabOneColumn,
757
- properties: properties,
758
- tables: tables,
759
- };
760
- sorting.forEach(function (item) {
761
- mytab += formBuildDiv(item, obj);
762
- });
280
+ const viewTokens = (MYMODEL, zFields, novalidate) => ({
281
+ "[[[NO_VALI_DATE_NOVALIDATE]]]": novalidate,
282
+ "[[[GENERATE_FORM]]]": generatorApp.GENERATE_FORM(MYMODEL, zFields) || "",
283
+ "[[[GENERATE_INDEXJS]]]": generatorApp.GENERATE_INDEXJS(MYMODEL) || "",
284
+ "[[[GENERATE_VIEW]]]": generatorApp.GENERATE_VIEW(MYMODEL, zFields) || "",
285
+ });
763
286
 
764
- //let contentTab = generateForm(properties, sorting, tabLeft, tabRight, tabOneColumn);
765
- let contentTab = mytab;
766
- let active = i == 0 ? "show active" : "";
767
- out += `${Util.tab}<div class="tab-pane fade ${active}" id="arr${i}" role="tabpanel" aria-labelledby="arr${i}"><p></p>${contentTab}</div>${Util.newLine}`;
768
- });
769
- out += `</div>${Util.newLine}`;
770
- out += `<p></p>${Util.newLine}`;
771
- }
287
+ generatorApp.containerObject = containerObject;
288
+ generatorApp.readFileSafe = readFileSafe;
289
+ generatorApp.asArray = asArray;
290
+ generatorApp.isPlainObject = isPlainObject;
772
291
 
773
- sorting.forEach(function (item) {
774
- out += formBuildDiv(item, {
775
- left: ALL_FIELDS.left,
776
- right: ALL_FIELDS.right,
777
- oneColumn: ALL_FIELDS.oneColumn,
778
- properties: properties,
779
- tables: tables,
780
- });
781
- });
292
+ generatorApp.CREATE_MODEL = async (MYMODEL) => generatorModel.create(MYMODEL);
293
+ generatorApp.CREATE_MODEL_API = async (columns, constraintList, MYMODEL) =>
294
+ generatorModel.createApi(columns, constraintList, MYMODEL);
782
295
 
783
- return out;
296
+ generatorApp.CREATE_ROUTER = async (MYMODEL, zFields) => {
297
+ if (!isPlainObject(MYMODEL) || !MYMODEL.table) throw new Error("MYMODEL.table is required");
298
+ const zfields = await connection.result({ table: "zfields", where: { table: MYMODEL.table } });
299
+ const content = applyTokens(defaultRouterContent(zFields), routerTokens(MYMODEL, isPlainObject(zfields) ? zfields : zFields));
300
+ fs.writeFileSync(path.join(generatorApp.DIRECTORY_ROUTES, `${MYMODEL.table}.js`), content, "utf-8");
301
+ return { filename: `${MYMODEL.table}.js`, content };
784
302
  };
785
303
 
786
- generatorApp.GENERATE_FORM_CLASSIC = (MYMODEL, zFields) => {
787
- let out = "";
788
- //check if it has a tab
789
- let properties = zFields.properties || {};
790
- let tabs = zFields.tabs ? zFields.tabs : [];
791
- let leftData = zFields.left || [];
792
- let sorting = zFields.sorting || [];
793
- let rightData = zFields.right || [];
794
- let oneColumnData = zFields.one_column || [];
795
- const isTab = tabs.length ? true : false;
796
- let tables = [];
797
- let left = [],
798
- right = [],
799
- oneColumn = [],
800
- leftTab = [],
801
- rightTab = [],
802
- oneColumnTab = [],
803
- lefts = [],
804
- rights = [];
805
- let tabLeft = [],
806
- tabRight = [],
807
- tabOneColumn = [];
808
-
809
- leftData.forEach(function (item) {
810
- if (typeof item == "string") {
811
- left.push(item);
812
- } else {
813
- leftTab.push(item);
814
- }
815
- });
816
- rightData.forEach(function (item) {
817
- if (typeof item == "string") {
818
- right.push(item);
819
- } else {
820
- rightTab.push(item);
821
- }
822
- });
823
- oneColumnData.forEach(function (item) {
824
- if (typeof item == "string") {
825
- oneColumn.push(item);
826
- } else {
827
- oneColumnTab.push(item);
828
- }
829
- });
830
-
831
- if (isTab) {
832
- out += `<ul class="nav nav-tabs" id="myTab" role="tablist">`;
833
- tabs.forEach(function (tab, i) {
834
- let arrName = `arr${i}`;
835
- let active = i == 0 ? "active" : "";
836
- out += ` <li class="nav-item ${arrName}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#arr${i}" type="button" role="tab" aria-controls="arr${i}" aria-selected="true">${tab}</button></li>`;
837
- });
838
- out += `</ul>`;
839
- }
840
-
841
- if (isTab) {
842
- out += `<div class="tab-content" id="myTabContent">`;
843
- tabs.forEach(function (tab, i) {
844
- let arrName = `arr${i}`;
845
- leftTab.forEach(function (item) {
846
- for (let key in item) {
847
- if (key == arrName) {
848
- tabLeft = item[key];
849
- }
850
- }
851
- });
852
- rightTab.forEach(function (item) {
853
- for (let key in item) {
854
- if (key == arrName) {
855
- tabRight = item[key];
856
- }
857
- }
858
- });
859
- oneColumnTab.forEach(function (item) {
860
- for (let key in item) {
861
- if (key == arrName) {
862
- tabOneColumn = item[key];
863
- }
864
- }
865
- });
866
- let contentTab = generateForm(
867
- properties,
868
- sorting,
869
- tabLeft,
870
- tabRight,
871
- tabOneColumn
872
- );
873
- let active = i == 0 ? "show active" : "";
874
- out += `<div class="tab-pane fade ${active}" id="arr${i}" role="tabpanel" aria-labelledby="arr${i}"><p></p>${contentTab}</div>`;
875
- });
876
- out += `</div>`;
877
- out += `<p></p>`;
878
- }
879
- out += generateForm(properties, sorting, left, right, oneColumn);
880
- return out;
304
+ generatorApp.CREATE_ROUTER_API = (MYMODEL, zfields) => {
305
+ if (!isPlainObject(MYMODEL) || !MYMODEL.table) {
306
+ return { filename: "", content: "" };
307
+ }
308
+ return {
309
+ filename: `${MYMODEL.table}.js`,
310
+ content: applyTokens(defaultRouterContent(zfields), routerTokens(MYMODEL, zfields)),
311
+ };
881
312
  };
882
313
 
883
- generatorApp.GENERATE_VIEW = (MYMODEL, zFields) => {
884
- let others = zFields.others || {};
885
- let length = Object.keys(others).length;
886
- if (length) {
887
- return generatorApp.GENERATE_VIEW_WITH_CONTAINER(MYMODEL, zFields);
888
- } else {
889
- return generatorApp.GENERATE_VIEW_CLASSIC(MYMODEL, zFields);
890
- }
314
+ generatorApp.CREATE_VIEWS = async (MYMODEL, zFields) => {
315
+ if (!isPlainObject(MYMODEL) || !MYMODEL.table) throw new Error("MYMODEL.table is required");
316
+ const tokens = viewTokens(MYMODEL, zFields || {}, " ");
317
+ const dirView = path.join(generatorApp.DIRECTORY_VIEWS, MYMODEL.table);
318
+ fs.ensureDirSync(dirView);
319
+ VIEW_FILES.concat(["preview.ejs"]).forEach((item) => {
320
+ const name = viewSourceKey(item);
321
+ const source = zFields && zFields[name]
322
+ ? zFields[name]
323
+ : readFileSafe(path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item));
324
+ fs.writeFileSync(path.join(dirView, item), applyTokens(source, tokens), "utf-8");
325
+ });
891
326
  };
892
327
 
893
- generatorApp.GENERATE_VIEW_WITH_CONTAINER = (MYMODEL, zFields) => {
894
- let out = "";
895
- //check if it has a tab
896
- let properties = zFields.properties || {};
897
- let tabs = zFields.tabs ? zFields.tabs : [];
898
- const others = zFields.others || {};
899
- let leftData = others.LEFT || [];
900
- let rightData = others.RIGHT || [];
901
- let oneColumnData = others.ONE_COLUMN || [];
902
- const isTab = tabs.length ? true : false;
903
- let tabLeft = [],
904
- tabRight = [],
905
- tabOneColum = [];
906
- let sorting = zFields.sorting;
907
- let ALL_FIELDS = containerObject(leftData, rightData, oneColumnData, tabs);
908
- let arrName = "";
328
+ generatorApp.CREATE_VIEWS_API = (MYMODEL, zFields) => {
329
+ if (!isPlainObject(MYMODEL) || !isPlainObject(zFields)) return {};
330
+ const tabs = asArray(zFields.tabs);
331
+ const tokens = viewTokens(MYMODEL, zFields, tabs.length ? " novalidate " : "");
332
+ const datas = {};
333
+ VIEW_FILES.forEach((item) => {
334
+ const name = viewSourceKey(item);
335
+ const source = hasOwn(zFields, name) && zFields[name]
336
+ ? zFields[name]
337
+ : readFileSafe(path.join(generatorApp.DIRECTORY_GENERATOR_VIEWS, item));
338
+ datas[item] = applyTokens(source, tokens);
339
+ });
340
+ return datas;
341
+ };
909
342
 
910
- if (isTab) {
911
- out += `<ul class="nav nav-tabs" id="myTab" role="tablist">${Util.newLine}`;
912
- tabs.forEach(function (tab, i) {
913
- arrName = `arr${i}`;
914
- let active = i == 0 ? "active" : "";
915
- out += `${Util.tab}<li class="nav-item ${arrName}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#tabgo${i}" type="button" role="tab" aria-controls="tabgo${i}" aria-selected="true">${tab}</button></li>${Util.newLine}`;
916
- });
917
- out += `</ul>${Util.newLine}`;
343
+ generatorApp.MODIFIY = (SOURCE, TARGET, REPLACE, REPLACE_NEW) => {
344
+ const data = readFileSafe(SOURCE);
345
+ fs.writeFileSync(TARGET, Util.replaceAll(data, REPLACE, REPLACE_NEW == null ? "" : String(REPLACE_NEW)), "utf-8");
346
+ };
918
347
 
919
- out += `${Util.tabs(2)}<div class="tab-content" id="myTabContent">${
920
- Util.newLine
921
- }`;
922
- tabs.forEach(function (tab, i) {
923
- arrName = `arr${i}`;
924
- tabLeft = ALL_FIELDS.tabLeft[arrName];
925
- tabRight = ALL_FIELDS.tabRight[arrName];
926
- tabOneColum = ALL_FIELDS.tabOneColumn[arrName];
927
- //let contentTab = generateViewContainer(properties, sorting, tabLeft, tabRight, tabOneColum);
928
- let contentTab = "";
929
- sorting.forEach(function (item) {
930
- contentTab += formBuildDiv(item, {
931
- left: tabLeft,
932
- right: tabRight,
933
- oneColumn: tabOneColum,
934
- properties: properties,
935
- tables: [],
936
- });
937
- });
938
- let active = i == 0 ? "show active" : "";
939
- out += `<div class="tab-pane fade ${active}" id="tabgo${i}" role="tabpanel" aria-labelledby="tabgo${i}"><p></p>${contentTab}</div>`;
940
- });
941
- out += `</div>`;
942
- out += `<p></p>`;
348
+ generatorApp.ADDITIONAL_FIELDS = (MYMODEL) => {
349
+ const bytime = configGenerator.createdUpdatedAt || [];
350
+ const byman = configGenerator.createdUpdatedBy || [];
351
+ const fields = (MYMODEL && MYMODEL.fields) || {};
352
+ const widgets = (MYMODEL && MYMODEL.widgets) || {};
353
+ const create = [];
354
+ Object.keys(fields).forEach((key) => {
355
+ if (Util.in_array(key, bytime)) create.push({ field: key, value: "Util.now()" });
356
+ if (Util.in_array(key, byman)) create.push({ field: key, value: "res.locals.userId" });
357
+ });
358
+ const update = create.filter((item) => String(item.field).indexOf("create") < 0);
359
+ let str = "";
360
+ Object.keys(widgets).forEach((key) => {
361
+ if (widgets[key] && widgets[key].name === "number") {
362
+ str += `${Util.tabs(2)}data.${key} = Util.replaceAll(data.${key},'.','')${Util.newLine}`;
943
363
  }
944
- //out += generateViewContainer(properties, sorting, ALL_FIELDS.left, ALL_FIELDS.right, ALL_FIELDS.oneColumn);
945
- sorting.forEach(function (item) {
946
- out += formBuildDiv(item, {
947
- left: ALL_FIELDS.left,
948
- right: ALL_FIELDS.right,
949
- oneColumn: ALL_FIELDS.oneColumn,
950
- properties: properties,
951
- tables: [],
952
- });
953
- });
954
- out += viewCreatedBy();
955
- out += viewApproval();
956
-
957
- return out;
364
+ });
365
+ const lines = (rows) => rows.reduce((result, item) => (
366
+ result + `${Util.tabs(2)}data.${item.field} = ${item.value};${Util.newLine}`
367
+ ), "");
368
+ return { CREATE: str + lines(create), UPDATE: str + lines(update) };
958
369
  };
959
370
 
960
- generatorApp.GENERATE_VIEW_CLASSIC = (MYMODEL, zFields) => {
961
- let out = "";
962
- //check if it has a tab
963
- let properties = zFields.properties || {};
964
- let labels = zFields.labels;
965
- let tabs = zFields.tabs ? zFields.tabs : [];
966
- let leftData = zFields.left || [];
967
- let rightData = zFields.right || [];
968
- let oneColumnData = zFields.one_column || [];
969
- let sorting = zFields.sorting;
970
- let left = [],
971
- right = [],
972
- oneColumn = [],
973
- leftTab = [],
974
- rightTab = [],
975
- oneColumnTab = [],
976
- lefts = [],
977
- rights = [];
978
- const isTab = tabs.length ? true : false;
979
- let arrName = "";
980
- let tables = [];
981
- let tabLeft = [],
982
- tabRight = [],
983
- tabOneColumn = [];
984
- leftData.forEach(function (item) {
985
- if (typeof item == "string") {
986
- left.push(item);
987
- } else {
988
- leftTab.push(item);
989
- }
990
- });
991
- rightData.forEach(function (item) {
992
- if (typeof item == "string") {
993
- right.push(item);
994
- } else {
995
- rightTab.push(item);
996
- }
997
- });
998
- oneColumnData.forEach(function (item) {
999
- if (typeof item == "string") {
1000
- oneColumn.push(item);
1001
- } else {
1002
- oneColumnTab.push(item);
1003
- }
1004
- });
371
+ generatorApp.GENERATE_INDEXJS = (MYMODEL) => {
372
+ const fields = (MYMODEL && MYMODEL.fields) || {};
373
+ const widgets = (MYMODEL && MYMODEL.widgets) || {};
374
+ let out = Util.newLine;
375
+ Object.keys(fields).forEach((key) => {
376
+ if (key === "company_id") return;
377
+ const widgetName = widgets[key] && widgets[key].name;
378
+ const render = (widgetName && INDEXJS_WIDGET[widgetName]) || INDEXJS_WIDGET.text;
379
+ out += render(key);
380
+ });
381
+ return out;
382
+ };
1005
383
 
1006
- if (isTab) {
1007
- out += `<ul class="nav nav-tabs" id="myTab" role="tablist">`;
1008
- tabs.forEach(function (tab, i) {
1009
- arrName = `arr${i}`;
1010
- let active = i == 0 ? "active" : "";
1011
- out += ` <li class="nav-item ${arrName}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#tabgo${i}" type="button" role="tab" aria-controls="tabgo${i}" aria-selected="true">${tab}</button></li>`;
1012
- });
1013
- out += `</ul>`;
1014
- }
384
+ generatorApp.GENERATE_FORM = (MYMODEL, zFields) => {
385
+ const others = (zFields && zFields.others) || {};
386
+ return Object.keys(others).length
387
+ ? generatorApp.GENERATE_FORM_WITH_CONTAINER(MYMODEL, zFields)
388
+ : generatorApp.GENERATE_FORM_CLASSIC(MYMODEL, zFields);
389
+ };
1015
390
 
1016
- if (isTab) {
1017
- out += `<div class="tab-content" id="myTabContent">`;
1018
- tabs.forEach(function (tab, i) {
1019
- arrName = `arr${i}`;
1020
- leftTab.forEach(function (item) {
1021
- for (let key in item) {
1022
- if (key == arrName) {
1023
- tabLeft = item[key];
1024
- }
1025
- }
1026
- });
1027
- rightTab.forEach(function (item) {
1028
- for (let key in item) {
1029
- if (key == arrName) {
1030
- tabRight = item[key];
1031
- }
1032
- }
1033
- });
1034
- oneColumnTab.forEach(function (item) {
1035
- for (let key in item) {
1036
- if (key == arrName) {
1037
- tabOneColumn = item[key];
1038
- }
1039
- }
1040
- });
1041
- //let contentTab = generateViewClassic(properties, sorting, tabLeft, tabRight, tabOneColumn);
1042
- let contentTab = "";
1043
- sorting.forEach(function (item) {
1044
- contentTab += formBuildDiv(item, {
1045
- left: tabLeft,
1046
- right: tabRight,
1047
- oneColumn: tabOneColumn,
1048
- properties: properties,
1049
- tables: tables,
1050
- });
1051
- });
1052
- let active = i == 0 ? "show active" : "";
1053
- out += `<div class="tab-pane fade ${active}" id="tabgo${i}" role="tabpanel" aria-labelledby="tabgo${i}"><p></p>${contentTab}</div>`;
1054
- });
1055
- out += `</div>`;
1056
- out += `<p></p>`;
1057
- }
1058
- //out += generateViewClassic(properties, sorting , left, right, oneColumn);
1059
- sorting.forEach(function (item) {
1060
- out += formBuildDiv(item, {
1061
- left: left,
1062
- right: right,
1063
- oneColumn: oneColumn,
1064
- properties: properties,
1065
- tables: tables,
1066
- });
391
+ generatorApp.GENERATE_FORM_WITH_CONTAINER = (MYMODEL, zFields) => {
392
+ const z = zFields || {};
393
+ const others = z.others || {};
394
+ const properties = z.properties || {};
395
+ const tabs = asArray(z.tabs);
396
+ const sorting = asArray(z.sorting);
397
+ const ALL_FIELDS = containerObject(others.LEFT, others.RIGHT, others.ONE_COLUMN, tabs);
398
+ const tables = [];
399
+ let out = "";
400
+
401
+ if (tabs.length) {
402
+ out += renderTabNav(tabs);
403
+ out += `<div class="tab-content" id="myTabContent">${Util.newLine}`;
404
+ tabs.forEach((_, i) => {
405
+ const arrName = `arr${i}`;
406
+ const obj = {
407
+ left: ALL_FIELDS.tabLeft[arrName] || [],
408
+ right: ALL_FIELDS.tabRight[arrName] || [],
409
+ oneColumn: ALL_FIELDS.tabOneColumn[arrName] || [],
410
+ properties,
411
+ tables,
412
+ };
413
+ const contentTab = sorting.map((item) => formBuildDiv(item, obj)).join("");
414
+ const active = i === 0 ? "show active" : "";
415
+ out += `${Util.tab}<div class="tab-pane fade ${active}" id="arr${i}" role="tabpanel" aria-labelledby="arr${i}"><p></p>${contentTab}</div>${Util.newLine}`;
1067
416
  });
1068
- out += viewCreatedBy();
1069
- out += viewApproval();
417
+ out += `</div>${Util.newLine}<p></p>${Util.newLine}`;
418
+ }
1070
419
 
1071
- return out;
420
+ const outside = { left: ALL_FIELDS.left, right: ALL_FIELDS.right, oneColumn: ALL_FIELDS.oneColumn, properties, tables };
421
+ out += sorting.map((item) => formBuildDiv(item, outside)).join("");
422
+ return out;
1072
423
  };
1073
424
 
1074
- function generateForm(
1075
- properties,
1076
- sorting,
1077
- left = [],
1078
- right = [],
1079
- oneColumn = []
1080
- ) {
1081
- var out = "",
1082
- lefts = [],
1083
- rights = [],
1084
- oneColumns = [],
1085
- tables = [];
1086
- left.forEach((item) => {
1087
- lefts.push(item);
1088
- /*if (properties[item].type == "table") {
1089
- tables.push(item);
1090
- } else {
1091
- lefts.push(item);
1092
- }*/
1093
- });
1094
- right.forEach((item) => {
1095
- rights.push(item);
1096
- /*if (properties[item].type == "table") {
1097
- tables.push(item);
1098
- } else {
1099
- rights.push(item);
1100
- }*/
1101
- });
1102
- oneColumn.forEach((item) => {
1103
- if (properties[item].type == "table") {
1104
- tables.push(item);
1105
- } else {
1106
- oneColumns.push(item);
1107
- }
425
+ generatorApp.GENERATE_FORM_CLASSIC = (MYMODEL, zFields) => {
426
+ const z = zFields || {};
427
+ const properties = z.properties || {};
428
+ const tabs = asArray(z.tabs);
429
+ const sorting = asArray(z.sorting);
430
+ const leftCols = splitFlatAndTabbed(z.left);
431
+ const rightCols = splitFlatAndTabbed(z.right);
432
+ const oneCols = splitFlatAndTabbed(z.one_column);
433
+ let out = "";
434
+
435
+ if (tabs.length) {
436
+ out += `<ul class="nav nav-tabs" id="myTab" role="tablist">`;
437
+ tabs.forEach((tab, i) => {
438
+ const active = i === 0 ? "active" : "";
439
+ out += ` <li class="nav-item arr${i}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#arr${i}" type="button" role="tab" aria-controls="arr${i}" aria-selected="true">${tab}</button></li>`;
1108
440
  });
1109
- var obj = {
1110
- left: lefts,
1111
- right: rights,
1112
- oneColumn: oneColumn,
1113
- properties: properties,
1114
- tables: tables,
1115
- };
1116
- sorting.forEach(function (item) {
1117
- out += formBuildDiv(item, obj);
441
+ out += `</ul>`;
442
+ out += `<div class="tab-content" id="myTabContent">`;
443
+ tabs.forEach((_, i) => {
444
+ const arrName = `arr${i}`;
445
+ const contentTab = generateForm(
446
+ properties,
447
+ sorting,
448
+ fieldsForTab(leftCols.tabbed, arrName),
449
+ fieldsForTab(rightCols.tabbed, arrName),
450
+ fieldsForTab(oneCols.tabbed, arrName)
451
+ );
452
+ const active = i === 0 ? "show active" : "";
453
+ out += `<div class="tab-pane fade ${active}" id="arr${i}" role="tabpanel" aria-labelledby="arr${i}"><p></p>${contentTab}</div>`;
1118
454
  });
1119
- return out;
1120
- }
1121
-
1122
- const viewField = (item, properties) => {
1123
- let html = "";
1124
- if (typeof item == "string") {
1125
- html += `${Util.newLine}${Util.tabs(
1126
- 2
1127
- )}<div class="row"><label for="${item}" class="col col-form-label label-view"><%- attributeData.labels.${item} %></label><div class="col label-data"><%- data.${item} %></div></div>`;
1128
- } else {
1129
- if (Array.isArray(item)) {
1130
- let count = item.length;
1131
- html += `<div class="row">`;
1132
- item.forEach(function (childs) {
1133
- html += `<div class="col">`;
1134
- childs.forEach(function (child) {
1135
- html += `${Util.newLine}${Util.tabs(
1136
- 2
1137
- )}<label for="${child}" class="col col-form-label label-view"><%- attributeData.labels.${child} %></label><div class="col label-data"><%- data.${child} %></div>`;
1138
-
1139
- //html += `${Util.newLine}${Util.tabs(2)}<div class="row"><label for="${child}" class="col col-form-label label-view"><%- attributeData.labels.${child} %></label><div class="col label-data"><%- data.${child} %></div></div>`;
1140
- });
1141
- html += `</div>`;
1142
- });
1143
- html += `</div>`;
1144
- }
1145
- }
1146
- return html;
1147
- };
455
+ out += `</div><p></p>`;
456
+ }
1148
457
 
1149
- function generateViewContainer(
1150
- properties,
1151
- sorting,
1152
- left = [],
1153
- right = [],
1154
- oneColumn = []
1155
- ) {
1156
- let out = "";
1157
- let col_md = 6;
1158
- if (left.length == 0 || right.length == 0) {
1159
- col_md = 12;
1160
- }
1161
- let count = left.length + right.length;
1162
- if (count) {
1163
- out += `<div class="container grid-striped ">${Util.newLine}`;
1164
- out += `${Util.tabs(2)}<div class="row">${Util.newLine}`;
1165
- out += `${Util.tabs(3)}<div class="col-md-${col_md} ">${Util.newLine}`;
1166
- left.forEach(function (item) {
1167
- out += viewField(item, properties);
1168
- });
1169
- out += `${Util.tabs(3)}</div>${Util.newLine}`;
1170
- out += `${Util.tabs(3)}<div class="col-md-${col_md}">${Util.newLine}`;
1171
- out += `${Util.tabs(3)}<div class="container-fluid">${Util.newLine}`;
1172
- right.forEach(function (item) {
1173
- out += viewField(item, properties);
1174
- });
1175
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1176
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1177
-
1178
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1179
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1180
- }
1181
-
1182
- if (oneColumn.length) {
1183
- out += `<div class="container grid-striped mt-5">${Util.newLine}`;
1184
- out += `<div class="row ">${Util.newLine}`;
1185
- out += `<div class="col-md-12">${Util.newLine}`;
1186
- oneColumn.forEach(function (item) {
1187
- out += viewField(item, properties);
1188
- });
1189
- out += `</div>${Util.newLine}`;
1190
- out += `</div>${Util.newLine}`;
1191
- out += `</div>${Util.newLine}`;
1192
- }
1193
-
1194
- return out;
1195
- }
1196
- const viewApproval = () => {
1197
- return `<div class="ps-lg-4 my-5 text-lg-start col-lg-3 mb-3 float-end">
1198
- <%- zForms.approval_history_table %>
1199
- </div>`;
458
+ out += generateForm(properties, sorting, leftCols.flat, rightCols.flat, oneCols.flat);
459
+ return out;
1200
460
  };
1201
461
 
1202
- const viewCreatedBy = () => {
1203
- return `<div class="ps-lg-4 my-5 text-lg-start col-lg-3 mb-3 float-end">
1204
- <div class="dropdown">
1205
- <button class="btn boxy dropdown-toggle" type="button" id="viewCreatedBy" data-bs-toggle="dropdown" aria-expanded="false">
1206
- Last update : <%- zForms.users.updated_by %>
1207
- </button>
1208
- <ul class="dropdown-menu" aria-labelledby="viewCreatedBy">
1209
- <li><a class="dropdown-item" href="#">Updated at <%- zForms.users.updated_at %></a></li>
1210
- <li><a class="dropdown-item" href="#">Created at <%- zForms.users.created_at %></a></li>
1211
- <li><a class="dropdown-item" href="#">Created by <%- zForms.users.created_by %></a></li>
1212
- </ul>
1213
- </div>
1214
- </div>`;
462
+ generatorApp.GENERATE_VIEW = (MYMODEL, zFields) => {
463
+ const others = (zFields && zFields.others) || {};
464
+ return Object.keys(others).length
465
+ ? generatorApp.GENERATE_VIEW_WITH_CONTAINER(MYMODEL, zFields)
466
+ : generatorApp.GENERATE_VIEW_CLASSIC(MYMODEL, zFields);
1215
467
  };
1216
468
 
1217
- function generateViewClassic(
1218
- properties,
1219
- sorting,
1220
- left = [],
1221
- right = [],
1222
- oneColumn = []
1223
- ) {
1224
- let out = "",
1225
- lefts = [],
1226
- rights = [],
1227
- tables = [];
1228
- (lefts = left), (rights = right);
1229
- const maxNumber = lefts.length > rights.length ? lefts.length : rights.length;
1230
- let one = "",
1231
- two = "";
1232
- two += `<table class="table table-striped"><tbody>${Util.newLine}`;
1233
-
1234
- for (var i = 0; i < maxNumber; i++) {
1235
- two += `${Util.tabs(3)}<tr>${Util.newLine}`;
1236
- let colspanRight = !rights[i] ? ` colspan="3" ` : "";
1237
- let colspanLeft = !lefts[i] ? ` colspan="3" ` : "";
1238
- if (lefts[i]) {
1239
- two += `${Util.tabs(4)}<th class="can-copy" data-name="{${
1240
- lefts[i]
1241
- }}"><%- attributeData.labels.${lefts[i]} %></th>
1242
- <td class="can-copy" ${colspanRight}><%- data.${lefts[i]} %></td>${
1243
- Util.newLine
1244
- }`;
1245
- }
1246
- if (rights[i]) {
1247
- two += `${Util.tabs(4)}<th class="can-copy" data-name="{${
1248
- rights[i]
1249
- }}"><%- attributeData.labels.${rights[i]} %></th>
1250
- <td class="can-copy" ${colspanLeft}><%- data.${
1251
- rights[i]
1252
- } %></td>${Util.newLine}`;
1253
- }
1254
- two += `${Util.tabs(3)}</tr>${Util.newLine}`;
1255
- }
1256
-
1257
- two += `</tbody></table>`;
1258
-
1259
- if (oneColumn.length) {
1260
- one += `<table class="table table-striped">`;
1261
- oneColumn.forEach(function (item) {
1262
- one += `<tr><th><%- attributeData.labels.${item} %></th><td><%- data.${item} %></td></tr>`;
1263
- });
1264
-
1265
- one += `</table>`;
469
+ const renderViewLayout = (ALL_FIELDS, tabs, sorting, properties, tabPrefix) => {
470
+ let out = "";
471
+ if (tabs.length) {
472
+ if (tabPrefix === "tabgo") {
473
+ out += `<ul class="nav nav-tabs" id="myTab" role="tablist">${Util.newLine}`;
474
+ tabs.forEach((tab, i) => {
475
+ const active = i === 0 ? "active" : "";
476
+ out += `${Util.tab}<li class="nav-item arr${i}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#tabgo${i}" type="button" role="tab" aria-controls="tabgo${i}" aria-selected="true">${tab}</button></li>${Util.newLine}`;
477
+ });
478
+ out += `</ul>${Util.newLine}${Util.tabs(2)}<div class="tab-content" id="myTabContent">${Util.newLine}`;
479
+ } else {
480
+ out += `<ul class="nav nav-tabs" id="myTab" role="tablist">`;
481
+ tabs.forEach((tab, i) => {
482
+ const active = i === 0 ? "active" : "";
483
+ out += ` <li class="nav-item arr${i}" role="presentation"><button class="nav-link ${active}" data-bs-toggle="tab" data-bs-target="#tabgo${i}" type="button" role="tab" aria-controls="tabgo${i}" aria-selected="true">${tab}</button></li>`;
484
+ });
485
+ out += `</ul><div class="tab-content" id="myTabContent">`;
1266
486
  }
1267
-
1268
- sorting.forEach(function (item) {
1269
- if (item == 1) {
1270
- out += one;
1271
- } else {
1272
- out += two;
1273
- }
487
+ tabs.forEach((_, i) => {
488
+ const arrName = `arr${i}`;
489
+ const obj = {
490
+ left: ALL_FIELDS.tabLeft[arrName] || [],
491
+ right: ALL_FIELDS.tabRight[arrName] || [],
492
+ oneColumn: ALL_FIELDS.tabOneColumn[arrName] || [],
493
+ properties,
494
+ tables: ALL_FIELDS.tables || [],
495
+ };
496
+ const contentTab = asArray(sorting).map((item) => formBuildDiv(item, obj)).join("");
497
+ const active = i === 0 ? "show active" : "";
498
+ out += `<div class="tab-pane fade ${active}" id="tabgo${i}" role="tabpanel" aria-labelledby="tabgo${i}"><p></p>${contentTab}</div>`;
1274
499
  });
1275
- return out;
1276
- }
500
+ out += `</div><p></p>`;
501
+ }
502
+ out += asArray(sorting).map((item) => formBuildDiv(item, {
503
+ left: ALL_FIELDS.left,
504
+ right: ALL_FIELDS.right,
505
+ oneColumn: ALL_FIELDS.oneColumn,
506
+ properties,
507
+ tables: ALL_FIELDS.tables || [],
508
+ })).join("");
509
+ out += viewCreatedBy();
510
+ out += viewApproval();
511
+ return out;
512
+ };
1277
513
 
1278
- const formBuild = (arr, properties, tables) => {
1279
- let out = "";
1280
- arr.forEach(function (item, index) {
1281
- if (typeof item == "string") {
1282
- //console.log(`item string ${item}`)
1283
- let isHidden = !properties[item].values.hidden
1284
- ? false
1285
- : properties[item].values.hidden;
1286
- if (!isHidden) {
1287
- if (properties[item].type == "custom") {
1288
- out += `${Util.tabs(3)}<%- ${properties[item].values.code} %>${
1289
- Util.newLine
1290
- }`;
1291
- } else {
1292
- out += `${Util.tabs(3)}<%- zForms.build["${item}"] %>${Util.newLine}`;
1293
- }
1294
- }
1295
- } else {
1296
- out += `${Util.newLine}${Util.tabs(3)}<div class="row">${Util.newLine}`;
1297
- const col_md = `col-md-${12 / item.length}`;
1298
- item.forEach(function (myitems) {
1299
- //console.log(properties[myitems]);
1300
- out += `${Util.tabs(4)}<div class="${col_md}">${Util.newLine}`;
1301
- myitems.forEach(function (itemX) {
1302
- if (properties[itemX].type == "custom") {
1303
- out += `${Util.tabs(3)}<%- ${properties[itemX].values.code} %>${
1304
- Util.newLine
1305
- }`;
1306
- } else {
1307
- out += `${Util.tabs(5)}<%- zForms.build["${itemX}"] %>${
1308
- Util.newLine
1309
- }`;
1310
- }
1311
- });
1312
- out += `${Util.tabs(4)}</div>${Util.newLine}`;
1313
- });
1314
- out += `${Util.tabs(3)}</div>${Util.newLine}`;
1315
- }
1316
- });
1317
- return out;
514
+ generatorApp.GENERATE_VIEW_WITH_CONTAINER = (MYMODEL, zFields) => {
515
+ const z = zFields || {};
516
+ const others = z.others || {};
517
+ const ALL_FIELDS = containerObject(others.LEFT, others.RIGHT, others.ONE_COLUMN, asArray(z.tabs));
518
+ ALL_FIELDS.tables = [];
519
+ return renderViewLayout(ALL_FIELDS, asArray(z.tabs), z.sorting, z.properties || {}, "tabgo");
1318
520
  };
1319
521
 
1320
- const formBuildDiv = (type = 1, obj = {}) => {
1321
- let out = "";
1322
- if (type == 1) {
1323
- out += `${Util.tab}<div class="row">${Util.newLine}${Util.tabs(
1324
- 2
1325
- )}<div class="col-md-12">${Util.newLine}`;
1326
- out += formBuild(obj.oneColumn, obj.properties, obj.tables);
1327
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1328
- out += `${Util.tab}</div>${Util.newLine}`;
1329
- } else {
1330
- out += `${Util.tab}<div class="row">${Util.newLine}`;
1331
- out += `${Util.tabs(2)}<div class="col-md-6">${Util.newLine}`;
1332
- out += formBuild(obj.left, obj.properties, obj.tables);
1333
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1334
- out += `${Util.tabs(2)}<div class="col-md-6">${Util.newLine}`;
1335
- out += formBuild(obj.right, obj.properties, obj.tables);
1336
- out += `${Util.tabs(2)}</div>${Util.newLine}`;
1337
- out += `${Util.tab}</div>${Util.newLine}`;
1338
- }
1339
- return out;
522
+ generatorApp.GENERATE_VIEW_CLASSIC = (MYMODEL, zFields) => {
523
+ const z = zFields || {};
524
+ const leftCols = splitFlatAndTabbed(z.left);
525
+ const rightCols = splitFlatAndTabbed(z.right);
526
+ const oneCols = splitFlatAndTabbed(z.one_column);
527
+ const tabs = asArray(z.tabs);
528
+ const ALL_FIELDS = {
529
+ left: leftCols.flat,
530
+ right: rightCols.flat,
531
+ oneColumn: oneCols.flat,
532
+ tabLeft: {},
533
+ tabRight: {},
534
+ tabOneColumn: {},
535
+ tables: [],
536
+ };
537
+ tabs.forEach((_, i) => {
538
+ const arrName = `arr${i}`;
539
+ ALL_FIELDS.tabLeft[arrName] = fieldsForTab(leftCols.tabbed, arrName);
540
+ ALL_FIELDS.tabRight[arrName] = fieldsForTab(rightCols.tabbed, arrName);
541
+ ALL_FIELDS.tabOneColumn[arrName] = fieldsForTab(oneCols.tabbed, arrName);
542
+ });
543
+ return renderViewLayout(ALL_FIELDS, tabs, z.sorting, z.properties || {}, "classic");
1340
544
  };
1341
545
 
1342
546
  module.exports = generatorApp;