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.
@@ -2,774 +2,464 @@
2
2
  * Created by sintret dev on 10/1/2021.
3
3
  */
4
4
  const path = require("path");
5
+ const fs = require("fs-extra");
5
6
  const configGenerator = require("./config_generator");
6
7
  const Model = require("./Model");
7
- const fs = require("fs-extra");
8
- const connection = require('./connection');
9
- const Util = require('./Util');
10
- const zRoute = require('./zRoute');
8
+ const Util = require("./Util");
9
+ const zRoute = require("./zRoute");
11
10
 
12
11
  const me = {};
13
- let defaultValues = {};
14
-
15
- me.prepare = (MYMODEL) => {
16
- const left = MYMODEL.left || [];
17
- const right = MYMODEL.right || [];
18
- const properties = MYMODEL.properties || {};
19
- let details = MYMODEL.details || {};
20
- let labels = MYMODEL.labels || {};
21
-
22
- //remove custom type
23
- let customs = [];
24
- let visibles = [];
25
- let visiblesArr = [];
26
- let visiblesObj = {}
27
- for (let key in properties) {
28
- let propKey = properties[key].values
29
- if (
30
- Object.prototype.hasOwnProperty.call(
31
- properties[key].values,
32
- "defaultValue"
33
- ) &&
34
- properties[key].values.defaultValue
35
- ) {
36
- defaultValues[key] = properties[key].values.defaultValue;
37
- }
38
- if (properties[key].type == "custom") {
39
- customs.push(key);
40
- }
41
- if (propKey.visibles ==1) {
42
- visibles.push(key)
43
- visiblesArr.push({key:key, value: +propKey.no_visible});
44
- visiblesObj[key] = +propKey.no_visible
45
- }
46
- }
47
- if (customs.length) {
48
- customs.map((item) => {
49
- for (var key in MYMODEL.details) {
50
- details[key] = MYMODEL.details[key].filter((d) => !customs.includes(d));
51
- }
52
- delete labels[item];
53
- });
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 appRoot = () => Util.dirRoot || global.dirRoot || process.cwd();
16
+
17
+ const flattenVisibleItems = (list, visibles) => {
18
+ asArray(list).forEach((item) => {
19
+ if (typeof item === "object" && item) {
20
+ Object.keys(item).forEach((key) => {
21
+ visibles.push(...asArray(item[key]));
22
+ });
23
+ } else if (item) {
24
+ visibles.push(item);
54
25
  }
26
+ });
27
+ };
55
28
 
56
- const datas = {};
57
- const obj = {};
58
- obj.table = MYMODEL.table;
59
- obj.routeName = MYMODEL.route;
60
- obj.title = MYMODEL.name;
61
- obj.hasTabs =
62
- Object.prototype.hasOwnProperty.call(MYMODEL, "tabs") &&
63
- MYMODEL.tabs &&
64
- MYMODEL.tabs.length > 0
65
- ? true
66
- : false;
67
- obj.tabs = MYMODEL.tabs || [];
68
- obj.tabsDetail = details || {};
69
- obj.keys = Object.keys(labels).filter((item) => !customs.includes(item));
70
- obj.keysExcel = obj.keys;
71
- obj.labels = labels;
72
- obj.labels.no = "#";
73
- obj.labels.actionColumn = "Action";
74
- obj.fields = me.fields(MYMODEL);
75
- obj.options = {};
76
- obj.hasApproval =
77
- MYMODEL.hasOwnProperty("is_approval") && MYMODEL.is_approval ? true : false;
78
-
79
- for (let key in obj.fields) {
80
- obj.options[key] = obj.fields[key].search;
81
- datas[key] = defaultValues[key] == "null" ? "" : defaultValues[key] || "";
82
- }
29
+ const writeRuntimeFile = (kind, table, key, content) => {
30
+ if (!table || !key || content == null || content === "") return;
31
+ const dir = path.join(appRoot(), "public", "runtime", kind, table);
32
+ fs.ensureDirSync(dir);
33
+ fs.writeFileSync(path.join(dir, `${key}.txt`), String(content));
34
+ };
83
35
 
84
- obj.grids = {
85
- visibles: ["no"],
86
- invisibles: [],
87
- };
88
- //old visibles
89
- if(visibles.length == 0){
90
- left.forEach(function (item) {
91
- if (typeof item == "object") {
92
- for (const key in item) {
93
- visibles = [...visibles, ...item[key]];
94
- }
95
- } else {
96
- visibles.push(item);
97
- }
98
- });
99
- if (visibles.length < 4) {
100
- right.forEach(function (item) {
101
- if (typeof item == "object") {
102
- for (const key in item) {
103
- visibles = [...visibles, ...item[key]];
104
- }
105
- } else {
106
- visibles.push(item);
107
- }
108
- });
109
- }
110
- if (visibles.length == 0) {
111
- let num = 1;
112
- let nots = Util.nots;
113
- nots.push("no");
114
- for (let key in labels) {
115
- if (!Util.in_array(key, nots)) {
116
- if (num < 6) {
117
- visibles.push(key);
118
- }
119
- num++;
120
- }
121
- }
122
- }
123
- obj.grids.visibles = [
124
- ...["no"],
125
- ...visibles.filter((item, index) => {
126
- return index < 6;
127
- }),
128
- ...["actionColumn"],
129
- ];
130
-
131
- } else {
132
- //new visibles
133
- console.log(visiblesArr)
134
- let sortVisibles = Util.sortArray(visiblesArr, "value")
135
- visibles = sortVisibles.map((item) => item.key)
136
- console.log(visibles)
137
- obj.grids.visibles = [
138
- ...["no"],
139
- ...visibles,
140
- ...["actionColumn"],
141
- ];
142
- }
36
+ const modelType = (type) => (type && Model[type] ? Model[type] : null);
143
37
 
144
- obj.grids.invisibles = Object.keys(labels).filter((item) => {
145
- return !obj.grids.visibles.includes(item);
146
- });
38
+ const fieldDefaults = {
39
+ integer: { type: "int", category: "integer", length: 11, required: true, search: "=", key: "" },
40
+ datetime: { type: "datetime", category: "datetime", length: "", required: false, search: "ILIKE", key: "" },
41
+ lock: { type: "int", category: "integer", length: "1", required: false, search: "=", key: "" },
42
+ approval_status: { type: "select", category: "integer", length: "", required: false, search: "=", key: "" },
43
+ approval_history: { type: "json_array", category: "array", length: "2", required: false, search: "=", key: "" },
44
+ };
147
45
 
148
- obj.datas = datas;
46
+ const mergeField = (base, extra = {}) => Object.assign({}, fieldDefaults[base] || {}, extra);
149
47
 
150
- //define what are widgets
151
- //except text,textarea,
152
- //var nots = ['text','textarea'];
153
- const widgets = {};
154
- const labelsArray = Object.keys(obj.fields);
48
+ const selectFields = (values) => asArray(values && values.select).reduce((result, item) => {
49
+ if (!item) return result;
50
+ result[item.value] = item.label;
51
+ return result;
52
+ }, {});
155
53
 
156
- widgets["id"] = {
157
- name: "integer",
158
- hidden: false,
159
- };
160
- if (Util.in_array("lock", labelsArray)) {
161
- widgets["lock"] = {
162
- name: "switch",
163
- hidden: true,
164
- hasInputGroup: false,
165
- required: false,
166
- float: false,
167
- inline: false,
168
- readonly: false,
169
- fields: ["Unlock", "Locked"],
170
- };
171
- }
172
- if (Util.in_array("approval_status", labelsArray)) {
173
- widgets["approval_status"] = {
174
- name: "select",
175
- title: "Approval Status",
176
- placeholder: "Approval Status",
177
- type: "select",
178
- category: "integer",
179
- length: "",
180
- required: false,
181
- search: "=",
182
- key: "",
183
- hidden: false,
184
- hasInputGroup: false,
185
- float: false,
186
- inline: false,
187
- readonly: false,
188
- fields: {
189
- 1: "New",
190
- 2: "Check",
191
- 11: "Approve 1",
192
- 12: "Approve 2",
193
- 13: "Approve 3",
194
- 14: "Approve 4",
195
- 15: "Approve 5",
196
- 16: "Approve 6",
197
- 17: "Approve 7",
198
- 18: "Approve 8",
199
- 19: "Approve 9",
200
- 20: "Approve 10",
201
- 21: "Final Approve",
202
- 22: "Reject",
203
- },
204
- array: [
205
- { value: "1", label: "New" },
206
- { value: "2", label: "Check" },
207
- { value: "11", label: "Approve 1" },
208
- { value: "12", label: "Approve 2" },
209
- { value: "13", label: "Approve 3" },
210
- { value: "14", label: "Approve 4" },
211
- { value: "15", label: "Approve 5" },
212
- { value: "16", label: "Approve 6" },
213
- { value: "17", label: "Approve 7" },
214
- { value: "18", label: "Approve 8" },
215
- { value: "19", label: "Approve 9" },
216
- { value: "20", label: "Approve 10" },
217
- { value: "21", label: "Final Approve" },
218
- { value: "22", label: "Reject" },
219
- ],
220
- please_select: "",
221
- };
54
+ me.prepare = (MYMODEL) => {
55
+ const model = isPlainObject(MYMODEL) ? MYMODEL : {};
56
+ const left = asArray(model.left);
57
+ const right = asArray(model.right);
58
+ const properties = isPlainObject(model.properties) ? model.properties : {};
59
+ const labels = isPlainObject(model.labels) ? { ...model.labels } : {};
60
+ const details = isPlainObject(model.details) ? { ...model.details } : {};
61
+ const defaultValues = {};
62
+ const customs = [];
63
+ let visibles = [];
64
+ const visiblesArr = [];
65
+
66
+ Object.keys(properties).forEach((key) => {
67
+ const property = properties[key] || {};
68
+ const values = isPlainObject(property.values) ? property.values : {};
69
+ if (hasOwn(values, "defaultValue") && values.defaultValue) {
70
+ defaultValues[key] = values.defaultValue;
222
71
  }
223
- if (Util.in_array("approval_history", labelsArray)) {
224
- widgets["approval_history"] = {
225
- name: "json_array",
226
- hidden: false,
227
- hasInputGroup: false,
228
- required: false,
229
- float: false,
230
- inline: false,
231
- readonly: false,
232
- };
72
+ if (property.type === "custom") customs.push(key);
73
+ if (values.visibles == 1) {
74
+ visibles.push(key);
75
+ visiblesArr.push({ key, value: +values.no_visible });
233
76
  }
234
- if (Util.in_array("created_at", labelsArray)) {
235
- widgets["created_at"] = {
236
- name: "datetime",
237
- hidden: true,
238
- };
77
+ });
78
+
79
+ if (customs.length) {
80
+ Object.keys(details).forEach((key) => {
81
+ details[key] = asArray(model.details && model.details[key]).filter((item) => !customs.includes(item));
82
+ });
83
+ customs.forEach((item) => {
84
+ delete labels[item];
85
+ });
86
+ }
87
+
88
+ const obj = {
89
+ table: model.table,
90
+ routeName: model.route,
91
+ title: model.name,
92
+ hasTabs: asArray(model.tabs).length > 0,
93
+ tabs: asArray(model.tabs),
94
+ tabsDetail: details,
95
+ keys: Object.keys(labels).filter((item) => !customs.includes(item)),
96
+ labels,
97
+ fields: me.fields(model),
98
+ options: {},
99
+ hasApproval: !!model.is_approval,
100
+ grids: { visibles: ["no"], invisibles: [] },
101
+ };
102
+ obj.keysExcel = obj.keys;
103
+ obj.labels.no = "#";
104
+ obj.labels.actionColumn = "Action";
105
+
106
+ const datas = {};
107
+ Object.keys(obj.fields).forEach((key) => {
108
+ obj.options[key] = obj.fields[key].search;
109
+ datas[key] = defaultValues[key] === "null" ? "" : defaultValues[key] || "";
110
+ });
111
+ obj.datas = datas;
112
+
113
+ if (!visibles.length) {
114
+ flattenVisibleItems(left, visibles);
115
+ if (visibles.length < 4) flattenVisibleItems(right, visibles);
116
+ if (!visibles.length) {
117
+ const nots = asArray(Util.nots).concat(["no"]);
118
+ Object.keys(labels).forEach((key) => {
119
+ if (!Util.in_array(key, nots) && visibles.length < 5) visibles.push(key);
120
+ });
239
121
  }
240
- if (Util.in_array("updated_at", labelsArray)) {
241
- widgets["updated_at"] = {
242
- name: "datetime",
243
- hidden: true,
244
- };
122
+ obj.grids.visibles = ["no", ...visibles.filter((_, index) => index < 6), "actionColumn"];
123
+ } else {
124
+ visibles = Util.sortArray(visiblesArr, "value").map((item) => item.key);
125
+ obj.grids.visibles = ["no", ...visibles, "actionColumn"];
126
+ }
127
+ obj.grids.invisibles = Object.keys(labels).filter((item) => !obj.grids.visibles.includes(item));
128
+
129
+ const labelsArray = Object.keys(obj.fields);
130
+ const widgets = {
131
+ id: { name: "integer", hidden: false },
132
+ };
133
+
134
+ if (Util.in_array("lock", labelsArray)) {
135
+ widgets.lock = {
136
+ name: "switch",
137
+ hidden: true,
138
+ hasInputGroup: false,
139
+ required: false,
140
+ float: false,
141
+ inline: false,
142
+ readonly: false,
143
+ fields: ["Unlock", "Locked"],
144
+ };
145
+ }
146
+ if (Util.in_array("approval_status", labelsArray)) {
147
+ widgets.approval_status = {
148
+ name: "select",
149
+ title: "Approval Status",
150
+ placeholder: "Approval Status",
151
+ type: "select",
152
+ category: "integer",
153
+ length: "",
154
+ required: false,
155
+ search: "=",
156
+ key: "",
157
+ hidden: false,
158
+ hasInputGroup: false,
159
+ float: false,
160
+ inline: false,
161
+ readonly: false,
162
+ fields: {
163
+ 1: "New", 2: "Check", 11: "Approve 1", 12: "Approve 2", 13: "Approve 3",
164
+ 14: "Approve 4", 15: "Approve 5", 16: "Approve 6", 17: "Approve 7",
165
+ 18: "Approve 8", 19: "Approve 9", 20: "Approve 10", 21: "Final Approve", 22: "Reject",
166
+ },
167
+ array: [
168
+ { value: "1", label: "New" },
169
+ { value: "2", label: "Check" },
170
+ { value: "11", label: "Approve 1" },
171
+ { value: "12", label: "Approve 2" },
172
+ { value: "13", label: "Approve 3" },
173
+ { value: "14", label: "Approve 4" },
174
+ { value: "15", label: "Approve 5" },
175
+ { value: "16", label: "Approve 6" },
176
+ { value: "17", label: "Approve 7" },
177
+ { value: "18", label: "Approve 8" },
178
+ { value: "19", label: "Approve 9" },
179
+ { value: "20", label: "Approve 10" },
180
+ { value: "21", label: "Final Approve" },
181
+ { value: "22", label: "Reject" },
182
+ ],
183
+ please_select: "",
184
+ };
185
+ }
186
+ if (Util.in_array("approval_history", labelsArray)) {
187
+ widgets.approval_history = {
188
+ name: "json_array", hidden: false, hasInputGroup: false, required: false, float: false, inline: false, readonly: false,
189
+ };
190
+ }
191
+ if (Util.in_array("created_at", labelsArray)) widgets.created_at = { name: "datetime", hidden: true };
192
+ if (Util.in_array("updated_at", labelsArray)) widgets.updated_at = { name: "datetime", hidden: true };
193
+ if (Util.in_array("created_by", labelsArray)) {
194
+ widgets.created_by = { name: "relation", table: "zuser", fields: ["id", "fullname"], hidden: true };
195
+ }
196
+ if (Util.in_array("updated_by", labelsArray)) {
197
+ widgets.updated_by = { name: "relation", table: "zuser", fields: ["id", "fullname"], hidden: true };
198
+ }
199
+
200
+ Object.keys(properties).forEach((key) => {
201
+ const property = properties[key] || {};
202
+ const values = isPlainObject(property.values) ? property.values : {};
203
+ const type = property.type;
204
+ const widget = {
205
+ name: type,
206
+ hidden: values.hidden == "on",
207
+ hasInputGroup: false,
208
+ isAttributes: !!values.isAttributes,
209
+ onChange: !!(values.onChange && String(values.onChange).length > 4),
210
+ float: !!values.float,
211
+ inline: !!values.inline,
212
+ readonly: !!values.readonly,
213
+ };
214
+
215
+ if (values.inputGroupLeft) {
216
+ widget.inputGroupLeft = values.inputGroupLeft;
217
+ widget.hasInputGroup = true;
245
218
  }
246
- if (Util.in_array("created_by", labelsArray)) {
247
- widgets["created_by"] = {
248
- name: "relation",
249
- table: "zuser",
250
- fields: ["id", "fullname"],
251
- hidden: true,
252
- };
219
+ if (values.inputGroupRight) {
220
+ widget.inputGroupRight = values.inputGroupRight;
221
+ widget.hasInputGroup = true;
253
222
  }
254
- if (Util.in_array("updated_by", labelsArray)) {
255
- widgets["updated_by"] = {
256
- name: "relation",
257
- table: "zuser",
258
- fields: ["id", "fullname"],
259
- hidden: true,
260
- };
223
+ if (values.information) widget.information = JSON.stringify(values.information);
224
+ if (values.digitDecimal) widget.digitDecimal = values.digitDecimal;
225
+ if (values.thousandSeparator) widget.thousandSeparator = values.thousandSeparator;
226
+ if (values.decimalPlaces) widget.decimalPlaces = values.decimalPlaces;
227
+ if (values.defaultValue) widget.defaultValue = values.defaultValue;
228
+ if (hasOwn(values, "required")) widget.required = values.required;
229
+ if (hasOwn(values, "where")) widget.where = values.where || "";
230
+
231
+ switch (type) {
232
+ case "image":
233
+ widget.width = values.width || "300";
234
+ break;
235
+ case "datepicker":
236
+ widget.format = values.format || "YYYY-MM-DD";
237
+ break;
238
+ case "datetime":
239
+ widget.format = values.format || "YYYY-MM-DD HH:mm:ss";
240
+ break;
241
+ case "switch":
242
+ widget.fields = [values.notactive, values.active];
243
+ break;
244
+ case "table":
245
+ widget.table = values.table;
246
+ widget.hasCompanyId = true;
247
+ widget.search = values.search;
248
+ break;
249
+ case "multi_line_editor":
250
+ widget.table = values.table;
251
+ widget.fields = values.fields;
252
+ widget.description = values.description;
253
+ widget.hasCompanyId = true;
254
+ break;
255
+ case "select":
256
+ case "radio":
257
+ widget.fields = selectFields(values);
258
+ widget.array = asArray(values.select);
259
+ if (type === "select") widget.please_select = values.please_select;
260
+ break;
261
+ case "relation":
262
+ widget.table = values.table;
263
+ widget.fields = ["id", values.concat];
264
+ widget.isChain = values.isChain;
265
+ widget.isAttributes = !!values.isAttributes;
266
+ widget.isSearch = !!values.isSearch;
267
+ widget.chains = values.chains || [];
268
+ widget.hasCompanyId = true;
269
+ widget.please_select = values.please_select;
270
+ widget.order_by = values.order_by;
271
+ widget.import_field = values.import_field || "id";
272
+ widget.relation_info = !!values.relation_info;
273
+ if (widget.relation_info) writeRuntimeFile("info", model.table, key, values.relation_info);
274
+ if (widget.onChange) writeRuntimeFile("onchange", model.table, key, values.onChange);
275
+ break;
276
+ case "dragdrop":
277
+ widget.table = values.table;
278
+ widget.fields = ["id", values.concat];
279
+ widget.where = values.where || "";
280
+ widget.left = values.left || "";
281
+ widget.right = values.right || "";
282
+ widget.hasCompanyId = true;
283
+ widget.import_field = values.import_field || "id";
284
+ break;
285
+ case "typeahead":
286
+ case "dropdown_multi":
287
+ widget.table = values.table;
288
+ widget.fields = ["id", values.concat];
289
+ widget.hasCompanyId = true;
290
+ widget.order_by = values.order_by;
291
+ widget.import_field = values.import_field || "id";
292
+ if (type === "dropdown_multi") widget.hasChains = !!values.chains;
293
+ break;
294
+ case "dropdown_chain": {
295
+ const fieldValue = values.field || "";
296
+ widget.table = values.table;
297
+ widget.fields = ["id", values.concat];
298
+ widget.chains = fieldValue.indexOf(",") > -1 ? fieldValue.split(",") : [fieldValue];
299
+ widget.hasCompanyId = true;
300
+ break;
301
+ }
302
+ case "dropdown_checkbox": {
303
+ const fieldValue = values.array || "";
304
+ widget.fields = String(fieldValue).indexOf(",") > -1
305
+ ? String(fieldValue).split(",").map((item) => item.trim())
306
+ : [String(fieldValue).trim()];
307
+ break;
308
+ }
309
+ case "virtual":
310
+ widget.fields = values.sql || "";
311
+ break;
312
+ case "location":
313
+ widget.height = values.height || 250;
314
+ break;
315
+ case "custom":
316
+ widget.fields = values.code || "";
317
+ break;
318
+ case "ide_editor":
319
+ widget.language = values.languages || "";
320
+ widget.height = values.height || 400;
321
+ break;
322
+ case "html":
323
+ widget.code = !!values.code;
324
+ if (widget.code) writeRuntimeFile("html", model.table, key, values.code);
325
+ break;
326
+ case "money":
327
+ widget.symbol = values.symbol || "";
328
+ break;
329
+ default:
330
+ break;
261
331
  }
262
332
 
263
- for (const key in properties) {
264
- const property = properties[key];
265
- const hidden = !property.values.hidden
266
- ? false
267
- : property.values.hidden == "on"
268
- ? true
269
- : false;
270
- /* console.log("property start")
271
- console.log(key)
272
- console.log(JSON.stringify(property))
273
- console.log("property end")*/
274
- const type = property.type;
275
- widgets[key] = {
276
- name: type,
277
- hidden: hidden,
278
- };
279
-
280
- widgets[key].hasInputGroup = false;
281
- if (Object.prototype.hasOwnProperty.call(property.values, "inputGroupLeft") && property.values.inputGroupLeft) {
282
- widgets[key].inputGroupLeft = property.values.inputGroupLeft;
283
- widgets[key].hasInputGroup = true;
284
- }
285
- if (Object.prototype.hasOwnProperty.call(property.values,"inputGroupRight") && property.values.inputGroupRight) {
286
- widgets[key].inputGroupRight = property.values.inputGroupRight;
287
- widgets[key].hasInputGroup = true;
288
- }
289
- widgets[key].isAttributes = false;
290
- if (Object.prototype.hasOwnProperty.call(property.values,"isAttributes") && property.values.isAttributes) {
291
- widgets[key].isAttributes = true;
292
- }
293
- widgets[key].onChange = false;
294
- if (Object.prototype.hasOwnProperty.call(property.values,"onChange") && property.values.onChange.length > 4) {
295
- widgets[key].onChange = true;
296
- }
297
-
298
- if (property.values.information) {
299
- widgets[key].information = JSON.stringify(property.values.information);
300
- }
301
-
302
- if (property.values.digitDecimal) {
303
- widgets[key].digitDecimal = property.values.digitDecimal;
304
- }
305
-
306
- if (property.values.thousandSeparator) {
307
- widgets[key].thousandSeparator = property.values.thousandSeparator;
308
- }
309
-
310
- if (property.values.decimalPlaces) {
311
- widgets[key].decimalPlaces = property.values.decimalPlaces;
312
- }
313
-
314
- if (property.values.defaultValue) {
315
- widgets[key].defaultValue = property.values.defaultValue;
316
- }
317
-
318
- if (Object.prototype.hasOwnProperty.call(property.values, "required")) {
319
- widgets[key].required = property.values.required;
320
- }
321
-
322
- widgets[key].float = false;
323
- if (Object.prototype.hasOwnProperty.call(property.values, "float")) {
324
- widgets[key].float = property.values.float ? true : false;
325
- }
326
-
327
- widgets[key].inline = false;
328
- if (Object.prototype.hasOwnProperty.call(property.values, "inline")) {
329
- widgets[key].inline = property.values.inline ? true : false;
330
- }
331
-
332
- widgets[key].readonly = false;
333
- if (Object.prototype.hasOwnProperty.call(property.values, "readonly")) {
334
- widgets[key].readonly = property.values.readonly ? true : false;
335
- }
336
- if (Object.prototype.hasOwnProperty.call(property.values, "where")) {
337
- widgets[key].where = property.values.where || "";
338
- }
339
-
340
- switch (type) {
341
- case "image":
342
- widgets[key].width = property.values.width || "300";
343
- break;
344
- case "datepicker":
345
- widgets[key].format = !property.values.format
346
- ? "YYYY-MM-DD"
347
- : property.values.format;
348
- break;
349
- case "datetime":
350
- widgets[key].format = !property.values.format
351
- ? "YYYY-MM-DD HH:mm:ss"
352
- : property.values.format;
353
- break;
354
- case "switch":
355
- widgets[key].fields = [
356
- property.values.notactive,
357
- property.values.active,
358
- ];
359
- break;
360
- case "table":
361
- widgets[key].table = property.values.table;
362
- widgets[key].hasCompanyId = true;
363
- widgets[key].search = property.values.search;
364
- break;
365
- case "multi_line_editor":
366
- widgets[key].table = property.values.table;
367
- widgets[key].fields = property.values.fields;
368
- widgets[key].description = property.values.description;
369
- widgets[key].hasCompanyId = true;
370
- break;
371
- case "select":
372
- var values = property.values.select || [];
373
- widgets[key].fields = values.reduce((result, item) => {
374
- return { ...result, [item.value]: item.label };
375
- }, {});
376
- widgets[key].array = values;
377
- widgets[key].please_select = property.values.please_select;
378
- break;
379
- case "radio":
380
- var values = property.values.select || [];
381
- widgets[key].fields = values.reduce((result, item) => {
382
- return { ...result, [item.value]: item.label };
383
- }, {});
384
- widgets[key].array = values;
385
- break;
386
- case "relation":
387
- widgets[key].table = property.values.table;
388
- widgets[key].fields = ["id", property.values.concat];
389
- widgets[key].isChain = property.values.isChain;
390
- widgets[key].isAttributes = property.values.isAttributes ? true : false;
391
- widgets[key].isSearch = property.values.isSearch ? true : false;
392
- widgets[key].chains = property.values.chains || [];
393
- //widgets[key].chainsTable = property.values.chainsTable || {};
394
- widgets[key].hasCompanyId = true;
395
- widgets[key].please_select = property.values.please_select;
396
- widgets[key].order_by = property.values.order_by;
397
- widgets[key].import_field = property.values.import_field || "id";
398
- widgets[key].relation_info = property.values.relation_info ? true : false;
399
- if(widgets[key].relation_info) {
400
- //create file info to runtime
401
- let dirInfo = path.join(dirRoot, "public", "runtime", "info", MYMODEL.table);
402
- //Util.writeFile(path.join(dirRoot, "runtime", "info", MYMODEL.tab))
403
- if(!fs.existsSync(dirInfo)) {
404
- fs.mkdirSync(dirInfo, { recursive: true });
405
- }
406
- fs.writeFileSync(path.join(dirInfo, key + ".txt"), property.values.relation_info);
407
- }
408
- if(widgets[key].onChange) {
409
- //create file info to runtime
410
- let dirInfo = path.join(dirRoot, "public", "runtime", "onchange", MYMODEL.table);
411
- //Util.writeFile(path.join(dirRoot, "runtime", "info", MYMODEL.tab))
412
- if(!fs.existsSync(dirInfo)) {
413
- fs.mkdirSync(dirInfo, { recursive: true });
414
- }
415
- fs.writeFileSync(path.join(dirInfo, key + ".txt"), property.values.onChange);
416
- }
417
- break;
418
- case "dragdrop":
419
- widgets[key].table = property.values.table;
420
- widgets[key].fields = ["id", property.values.concat];
421
- widgets[key].where = property.values.where || "";
422
- widgets[key].left = property.values.left || "";
423
- widgets[key].right = property.values.right || "";
424
- widgets[key].hasCompanyId = true;
425
- widgets[key].import_field = property.values.import_field || "id";
426
- break;
427
- case "typeahead":
428
- widgets[key].table = property.values.table;
429
- widgets[key].fields = ["id", property.values.concat];
430
- widgets[key].hasCompanyId = true;
431
- widgets[key].order_by = property.values.order_by;
432
- widgets[key].import_field = property.values.import_field || "id";
433
- break;
434
- case "dropdown_multi":
435
- widgets[key].table = property.values.table;
436
- widgets[key].fields = ["id", property.values.concat];
437
- widgets[key].hasChains = property.values.chains ? true : false;
438
- widgets[key].hasCompanyId = true;
439
- widgets[key].order_by = property.values.order_by;
440
- widgets[key].import_field = property.values.import_field || "id";
441
- break;
442
- case "dropdown_chain":
443
- var fieldValue = property.values.field || "";
444
- widgets[key].table = property.values.table;
445
- widgets[key].fields = ["id", property.values.concat];
446
- widgets[key].chains =
447
- fieldValue.indexOf(",") > -1 ? fieldValue.split(",") : [fieldValue];
448
- widgets[key].hasCompanyId = true;
449
- break;
450
- case "dropdown_checkbox":
451
- var fieldValue = property.values.array || "";
452
- widgets[key].fields = fieldValue.indexOf(",")
453
- ? fieldValue.split(",").map((item) => {
454
- return item.trim();
455
- })
456
- : [fieldValue.trim()];
457
- break;
458
- case "virtual":
459
- var fieldValue = property.values.sql || "";
460
- widgets[key].fields = property.values.sql || "";
461
- break;
462
- case "location":
463
- widgets[key].height = property.values.height || 250;
464
- break;
465
- case "custom":
466
- widgets[key].fields = property.values.code || "";
467
- break;
468
- case "ide_editor":
469
- widgets[key].language = property.values.languages || "";
470
- widgets[key].height = !property.values.height
471
- ? 400
472
- : property.values.height;
473
- break;
474
- case "html":
475
- widgets[key].code = property.values.code ? true : false;
476
- if(widgets[key].code) {
477
- //create file info to runtime
478
- let dirInfo = path.join(dirRoot, "public", "runtime", "html", MYMODEL.table);
479
- //Util.writeFile(path.join(dirRoot, "runtime", "info", MYMODEL.tab))
480
- if(!fs.existsSync(dirInfo)) {
481
- fs.mkdirSync(dirInfo, { recursive: true });
482
- }
483
- fs.writeFileSync(path.join(dirInfo, key + ".txt"), property.values.code);
484
- }
485
- break;
486
-
487
- case "money":
488
- widgets[key].symbol = property.values.symbol || "";
489
- break;
490
-
491
- default:
492
- break;
493
- }
494
- }
495
- obj.widgets = widgets;
333
+ widgets[key] = widget;
334
+ });
496
335
 
497
- return obj;
336
+ obj.widgets = widgets;
337
+ return obj;
498
338
  };
499
339
 
500
- me.build = (json, index = 0) => {
501
- return zRoute.buildFileModel(json, index);
502
- };
340
+ me.build = (json, index = 0) => zRoute.buildFileModel(json, index);
503
341
 
504
342
  me.create = async (ZFIELDS) => {
505
- let jsonText = `module.exports = {${Util.newLine}`;
506
-
507
- //CHECK IF HAS multi_line_editor
508
- var properties = ZFIELDS.properties || {};
509
- var labels = ZFIELDS.labels || {};
510
- var multi_line_editors = [];
511
- for (var key in properties) {
512
- if (properties[key].type == "multi_line_editor") {
513
- multi_line_editors.push(key);
514
- }
515
- }
516
-
517
- //join into MYMODEL [JSON_MODEL]
518
- if (multi_line_editors.length) {
519
- // multi line editor skip
520
- /*for(var i = 0; i < multi_line_editors.length;i++) {
521
- var item = multi_line_editors[i];
522
- var table = properties[item].table;
523
- var ZFIELDS_OTHER = await connection.result({
524
- table:"zfields",
525
- where:{table:table}
526
- })
527
- console.log("ZFIELDS_OTHER")
528
- console.log(ZFIELDS_OTHER)
529
-
530
- var JSON_MODEL_OTHER = me.prepare(ZFIELDS_OTHER);
531
- }*/
532
- }
533
- const JSON_MODEL = me.prepare(ZFIELDS);
534
- jsonText += me.build(JSON_MODEL);
535
- jsonText += `}`;
536
- const filename = path.join(dirRoot, "models", ZFIELDS.table + ".js");
537
- fs.writeFile(filename, jsonText, function (err) {
538
- if (err) {
539
- return console.log(err.toString());
540
- }
541
- console.log("The file models of " + ZFIELDS.table + " is saved!");
542
- });
543
-
544
- return await me.build_sql(ZFIELDS);
343
+ if (!isPlainObject(ZFIELDS) || !ZFIELDS.table) throw new Error("ZFIELDS.table is required");
344
+ const JSON_MODEL = me.prepare(ZFIELDS);
345
+ const jsonText = `module.exports = {${Util.newLine}${me.build(JSON_MODEL)}}`;
346
+ const filename = path.join(appRoot(), "models", `${ZFIELDS.table}.js`);
347
+ await fs.outputFile(filename, jsonText, "utf-8");
348
+ return me.build_sql(ZFIELDS);
545
349
  };
546
350
 
547
- /*
548
- Create for API
549
- */
550
351
  me.createApi = async (columns, constraintList, ZFIELDS) => {
551
- let jsonText = `module.exports = {${Util.newLine}`;
552
-
553
- //CHECK IF HAS multi_line_editor
554
- const properties = ZFIELDS.properties || {};
555
- const labels = ZFIELDS.labels || {};
556
- const multi_line_editors = [];
557
- for (const key in properties) {
558
- if (properties[key].type == "multi_line_editor") {
559
- multi_line_editors.push(key);
560
- }
561
- }
562
- //join into MYMODEL [JSON_MODEL]
563
- const JSON_MODEL = me.prepare(ZFIELDS);
564
- jsonText += me.build(JSON_MODEL);
565
- jsonText += `}`;
566
- const filename = `${ZFIELDS.table}.js`;
567
- const datas = me.build_sql_api(columns, constraintList, ZFIELDS);
568
- datas.content = jsonText;
569
- datas.filename = filename;
570
- datas.modelObj = JSON_MODEL;
571
- return datas;
352
+ if (!isPlainObject(ZFIELDS) || !ZFIELDS.table) {
353
+ return { content: "", filename: "", modelObj: {}, sql: [], fk: [], alter: [], defaultValue: [], index: [], error: "ZFIELDS.table is required" };
354
+ }
355
+ const JSON_MODEL = me.prepare(ZFIELDS);
356
+ const datas = me.build_sql_api(columns, constraintList, ZFIELDS);
357
+ datas.content = `module.exports = {${Util.newLine}${me.build(JSON_MODEL)}}`;
358
+ datas.filename = `${ZFIELDS.table}.js`;
359
+ datas.modelObj = JSON_MODEL;
360
+ return datas;
572
361
  };
573
362
 
574
- me.build_sql_api = (columns, constraintList, MYMODEL) => {
575
- const labels = MYMODEL.labels || {};
576
- let properties = MYMODEL.properties || {};
577
- const fields = columns.reduce((result, item) => {
578
- return [...result, item.Field];
579
- }, []);
580
- const sql = [];
581
- let error = "";
582
- const datas = {
583
- error: error,
584
- };
363
+ me.build_sql = async (ZFIELDS) => me.build_sql_api([], [], ZFIELDS);
585
364
 
586
- for (let key in labels) {
587
- if (!Util.in_array(key, fields)) {
588
- let property = properties[key];
589
- if (property) {
590
- let sqlObject = Model[property.type].sql(key, MYMODEL, property.values);
591
- if (sqlObject.column) {
592
- try {
593
- sql.push(sqlObject.column);
594
- } catch (err) {
595
- error += err.toString();
596
- }
597
- }
598
- }
599
- }
365
+ me.build_sql_api = (columns, constraintList, MYMODEL) => {
366
+ const model = isPlainObject(MYMODEL) ? MYMODEL : {};
367
+ const labels = isPlainObject(model.labels) ? model.labels : {};
368
+ const properties = isPlainObject(model.properties) ? model.properties : {};
369
+ const fields = asArray(columns).map((item) => item && item.Field).filter(Boolean);
370
+ const constraintObject = Util.arrayToObject(asArray(constraintList), "conname") || {};
371
+ const notAlters = ["virtual", "custom", "html"];
372
+ const datas = { error: "", sql: [], fk: [], alter: [], defaultValue: [], index: [] };
373
+
374
+ Object.keys(labels).forEach((key) => {
375
+ if (Util.in_array(key, fields)) return;
376
+ const property = properties[key];
377
+ const typeApi = property && modelType(property.type);
378
+ if (!typeApi || typeof typeApi.sql !== "function") return;
379
+ try {
380
+ const sqlObject = typeApi.sql(key, model, property.values || {});
381
+ if (sqlObject && sqlObject.column) datas.sql.push(sqlObject.column);
382
+ } catch (err) {
383
+ datas.error += err.toString();
600
384
  }
601
- const constraintObject = Util.arrayToObject(constraintList, "conname");
602
- const alter = [];
603
- const index = [];
604
- const defaultValue = [];
605
- const fk = [];
606
- const notAlters = ["virtual", "custom","html"];
607
- for (const key in properties) {
608
- const property = properties[key];
609
- if (!notAlters.includes(property.type)) {
610
- //required
611
- const required = properties[key].values.required ? true : false;
612
- if (required) {
613
- alter.push(
614
- `ALTER TABLE "${MYMODEL.table}" ALTER COLUMN "${key}" SET NOT NULL; `
615
- );
616
- } else {
617
- alter.push(
618
- `ALTER TABLE "${MYMODEL.table}" ALTER COLUMN "${key}" DROP NOT NULL; `
619
- );
620
- }
621
- const sqlObject = Model[property.type].sql(key, MYMODEL, property.values);
622
- //unique
623
- const unique = properties[key].values.unique ? true : false;
624
- const idx = `unique_${MYMODEL.table}_${key}`;
625
- if (sqlObject.index) {
626
- if (!constraintObject.hasOwnProperty(idx)) {
627
- //await connection.query(sqlObject.index);
628
- index.push(sqlObject.index);
629
- }
630
- } else {
631
- if (constraintObject.hasOwnProperty(idx)) {
632
- //await connection.query(`DROP INDEX ${idx}; `);
633
- index.push(`DROP INDEX ${idx}; `);
634
- }
635
- }
636
- if(property.type == "money"){
637
- //ALTER TABLE nama_tabel
638
- // ALTER COLUMN nama_kolom TYPE NUMERIC(15,2);
639
- let digitDecimal = properties[key].values.digitDecimal || 0;
640
- alter.push(
641
- `ALTER TABLE "${MYMODEL.table}" ALTER COLUMN "${key}" TYPE NUMERIC(15,${digitDecimal});; `
642
- );
643
- }
644
- //relations foreign key
645
- const fkx = `fk_${MYMODEL.table}_${key}`;
646
- if (sqlObject.foreignKey) {
647
- if (!constraintObject.hasOwnProperty(fkx)) {
648
- //await connection.query(sqlObject.foreignKey);
649
- fk.push(sqlObject.foreignKey);
650
- }
651
- }
652
- //default value
653
- if (sqlObject.defaultValue) {
654
- //await connection.query(sqlObject.defaultValue);
655
- defaultValue.push(sqlObject.defaultValue);
656
- }
657
- }
385
+ });
386
+
387
+ Object.keys(properties).forEach((key) => {
388
+ const property = properties[key] || {};
389
+ const typeApi = modelType(property.type);
390
+ if (!typeApi || notAlters.includes(property.type)) return;
391
+ const values = isPlainObject(property.values) ? property.values : {};
392
+ const table = model.table || "";
393
+ datas.alter.push(
394
+ values.required
395
+ ? `ALTER TABLE "${table}" ALTER COLUMN "${key}" SET NOT NULL; `
396
+ : `ALTER TABLE "${table}" ALTER COLUMN "${key}" DROP NOT NULL; `
397
+ );
398
+
399
+ let sqlObject = {};
400
+ try {
401
+ sqlObject = typeApi.sql(key, model, values) || {};
402
+ } catch (err) {
403
+ datas.error += err.toString();
404
+ return;
658
405
  }
659
406
 
660
- datas.sql = sql;
661
- datas.fk = fk;
662
- datas.alter = alter;
663
- datas.defaultValue = defaultValue;
664
- datas.index = index;
665
- return datas;
666
- };
667
-
668
- me.fields = (MYMODEL) => {
669
- const obj = {};
670
- const properties = MYMODEL.properties || {};
671
- const labels = MYMODEL.labels || {};
672
- for (const key in labels) {
673
- obj[key] = {
674
- name: key,
675
- title: labels[key],
676
- placeholder: labels[key],
677
- };
678
- if (key == "id") {
679
- Object.assign(obj[key], me.integer({ key: "PRI" }));
680
- } else if (key == "company_id") {
681
- Object.assign(obj[key], me.integer({ key: "MUL" }));
682
- } else if (key == "lock") {
683
- Object.assign(obj[key], me.lock());
684
- } else if (key == "approval_status") {
685
- Object.assign(obj[key], me.approval_status());
686
- } else if (key == "approval_history") {
687
- Object.assign(obj[key], me.approval_history());
688
- } else if (Util.in_array(key, configGenerator.createdUpdatedAt)) {
689
- Object.assign(obj[key], me.datetime());
690
- } else if (Util.in_array(key, configGenerator.createdUpdatedBy)) {
691
- Object.assign(obj[key], me.integer());
692
- } else {
693
- if (properties.hasOwnProperty(key)) {
694
- var property = properties[key];
695
- var type = property.type;
696
- //console.log(type)
697
- obj[key].type = Model[type].columnType(property.values);
698
- obj[key].category = Model[type].category;
699
- obj[key].length = !property.length ? "" : property.length;
700
- obj[key].required = property.values.required ? true : false;
701
- obj[key].search = obj[key].category == "integer" ? "=" : "ILIKE";
702
- obj[key].key = "";
703
- }
704
- }
407
+ const idx = `unique_${table}_${key}`;
408
+ if (sqlObject.index) {
409
+ if (!hasOwn(constraintObject, idx)) datas.index.push(sqlObject.index);
410
+ } else if (hasOwn(constraintObject, idx)) {
411
+ datas.index.push(`DROP INDEX ${idx}; `);
705
412
  }
706
413
 
707
- return obj;
708
- };
709
-
710
- me.integer = (obj = {}) => {
711
- var defaultObj = {
712
- type: "int",
713
- category: "integer",
714
- length: 11,
715
- required: true,
716
- search: "=",
717
- key: "",
718
- };
719
-
720
- return Object.assign(defaultObj, obj);
721
- };
722
-
723
- me.datetime = (obj = {}) => {
724
- var defaultObj = {
725
- type: "datetime",
726
- category: "datetime",
727
- length: "",
728
- required: false,
729
- search: "ILIKE",
730
- key: "",
731
- };
732
-
733
- return Object.assign(defaultObj, obj);
734
- };
414
+ if (property.type === "money") {
415
+ const digitDecimal = values.digitDecimal || 0;
416
+ datas.alter.push(`ALTER TABLE "${table}" ALTER COLUMN "${key}" TYPE NUMERIC(15,${digitDecimal});; `);
417
+ }
735
418
 
736
- me.lock = (obj = {}) => {
737
- var defaultObj = {
738
- type: "int",
739
- category: "integer",
740
- length: "1",
741
- required: false,
742
- search: "=",
743
- key: "",
744
- };
419
+ const fkx = `fk_${table}_${key}`;
420
+ if (sqlObject.foreignKey && !hasOwn(constraintObject, fkx)) datas.fk.push(sqlObject.foreignKey);
421
+ if (sqlObject.defaultValue) datas.defaultValue.push(sqlObject.defaultValue);
422
+ });
745
423
 
746
- return Object.assign(defaultObj, obj);
424
+ return datas;
747
425
  };
748
426
 
749
- me.approval_status = (obj = {}) => {
750
- var defaultObj = {
751
- type: "select",
752
- category: "integer",
753
- length: "",
754
- required: false,
755
- search: "=",
756
- key: "",
757
- };
427
+ me.fields = (MYMODEL) => {
428
+ const obj = {};
429
+ const model = isPlainObject(MYMODEL) ? MYMODEL : {};
430
+ const properties = isPlainObject(model.properties) ? model.properties : {};
431
+ const labels = isPlainObject(model.labels) ? model.labels : {};
432
+
433
+ Object.keys(labels).forEach((key) => {
434
+ obj[key] = { name: key, title: labels[key], placeholder: labels[key] };
435
+ if (key === "id") Object.assign(obj[key], me.integer({ key: "PRI" }));
436
+ else if (key === "company_id") Object.assign(obj[key], me.integer({ key: "MUL" }));
437
+ else if (key === "lock") Object.assign(obj[key], me.lock());
438
+ else if (key === "approval_status") Object.assign(obj[key], me.approval_status());
439
+ else if (key === "approval_history") Object.assign(obj[key], me.approval_history());
440
+ else if (Util.in_array(key, configGenerator.createdUpdatedAt)) Object.assign(obj[key], me.datetime());
441
+ else if (Util.in_array(key, configGenerator.createdUpdatedBy)) Object.assign(obj[key], me.integer());
442
+ else if (hasOwn(properties, key)) {
443
+ const property = properties[key] || {};
444
+ const typeApi = modelType(property.type);
445
+ if (!typeApi) return;
446
+ const values = isPlainObject(property.values) ? property.values : {};
447
+ obj[key].type = typeApi.columnType(values);
448
+ obj[key].category = typeApi.category;
449
+ obj[key].length = property.length || "";
450
+ obj[key].required = !!values.required;
451
+ obj[key].search = obj[key].category === "integer" ? "=" : "ILIKE";
452
+ obj[key].key = "";
453
+ }
454
+ });
758
455
 
759
- return Object.assign(defaultObj, obj);
456
+ return obj;
760
457
  };
761
458
 
762
- me.approval_history = (obj = {}) => {
763
- var defaultObj = {
764
- type: "json_array",
765
- category: "array",
766
- length: "2",
767
- required: false,
768
- search: "=",
769
- key: "",
770
- };
771
-
772
- return Object.assign(defaultObj, obj);
773
- };
459
+ me.integer = (obj = {}) => mergeField("integer", obj);
460
+ me.datetime = (obj = {}) => mergeField("datetime", obj);
461
+ me.lock = (obj = {}) => mergeField("lock", obj);
462
+ me.approval_status = (obj = {}) => mergeField("approval_status", obj);
463
+ me.approval_history = (obj = {}) => mergeField("approval_history", obj);
774
464
 
775
465
  module.exports = me;