zet-lib 3.0.7 → 3.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/Form.js +12 -0
- package/lib/Model.js +173 -0
- package/lib/Util.js +5 -3
- package/lib/generatorApi.js +27 -27
- package/lib/generatorModel.js +16 -5
- package/lib/moduleLib.js +57 -57
- package/lib/views/generatorjs.ejs +2 -2
- package/lib/zRoute.js +73 -1
- package/package.json +1 -1
package/lib/Form.js
CHANGED
|
@@ -214,6 +214,10 @@ Form.field = (obj) => {
|
|
|
214
214
|
displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="text" class="form-control number ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`;
|
|
215
215
|
break;
|
|
216
216
|
|
|
217
|
+
case "money":
|
|
218
|
+
displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="text" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`;
|
|
219
|
+
break;
|
|
220
|
+
|
|
217
221
|
case "integer":
|
|
218
222
|
displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="number" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`;
|
|
219
223
|
break;
|
|
@@ -545,6 +549,10 @@ Form.field = (obj) => {
|
|
|
545
549
|
displayForm = obj.html;
|
|
546
550
|
break;
|
|
547
551
|
|
|
552
|
+
case "html":
|
|
553
|
+
displayForm = obj.code;
|
|
554
|
+
break;
|
|
555
|
+
|
|
548
556
|
case "location":
|
|
549
557
|
displayForm = `${prepend}<input type="text" class="form-control ${
|
|
550
558
|
obj.class
|
|
@@ -1028,6 +1036,10 @@ Form.build = (obj) => {
|
|
|
1028
1036
|
}
|
|
1029
1037
|
}
|
|
1030
1038
|
}
|
|
1039
|
+
|
|
1040
|
+
if(obj.type == "html") {
|
|
1041
|
+
html = obj.code;
|
|
1042
|
+
}
|
|
1031
1043
|
return html;
|
|
1032
1044
|
};
|
|
1033
1045
|
|
package/lib/Model.js
CHANGED
|
@@ -84,6 +84,7 @@ Model.keys = {
|
|
|
84
84
|
text: "Text",
|
|
85
85
|
textarea: "Textarea",
|
|
86
86
|
checkbox: "Checkbox",
|
|
87
|
+
money: "Money",
|
|
87
88
|
number: "Amount",
|
|
88
89
|
integer: "Integer",
|
|
89
90
|
select: "Select (static) ",
|
|
@@ -119,6 +120,7 @@ Model.keys = {
|
|
|
119
120
|
ltree: "LTree",
|
|
120
121
|
virtual: "Virtual Field (readonly)",
|
|
121
122
|
custom: "Custom",
|
|
123
|
+
html: "HTML Tags (code)",
|
|
122
124
|
};
|
|
123
125
|
|
|
124
126
|
Model.dropzone = {
|
|
@@ -888,6 +890,147 @@ Model.password = {
|
|
|
888
890
|
category: "text",
|
|
889
891
|
};
|
|
890
892
|
|
|
893
|
+
Model.money = {
|
|
894
|
+
properties: [
|
|
895
|
+
"required",
|
|
896
|
+
"unique",
|
|
897
|
+
"tabindex",
|
|
898
|
+
"min",
|
|
899
|
+
"max",
|
|
900
|
+
"hidden",
|
|
901
|
+
"defaultValue",
|
|
902
|
+
"inputGroupLeft",
|
|
903
|
+
"inputGroupRight",
|
|
904
|
+
"digitDecimal",
|
|
905
|
+
"decimalPlaces",
|
|
906
|
+
"thousandSeparator",
|
|
907
|
+
"symbol",
|
|
908
|
+
"information",
|
|
909
|
+
],
|
|
910
|
+
attributes: ["min", "max"],
|
|
911
|
+
labels: {
|
|
912
|
+
required: "Required",
|
|
913
|
+
unique: "Unique",
|
|
914
|
+
tabindex: "Tab Index",
|
|
915
|
+
min: "Min",
|
|
916
|
+
max: "Max",
|
|
917
|
+
hidden: "Hidden",
|
|
918
|
+
defaultValue: "Default Value",
|
|
919
|
+
inputGroupLeft: "Input Group Left",
|
|
920
|
+
inputGroupRight: "Input Group Right",
|
|
921
|
+
digitDecimal:"Digit Decimal",
|
|
922
|
+
decimalPlaces:"Decimal Places",
|
|
923
|
+
thousandSeparator:"Use 1000 Separator",
|
|
924
|
+
symbol:"Currency Symbol",
|
|
925
|
+
information: "Additional Information",
|
|
926
|
+
},
|
|
927
|
+
defaultValues: {
|
|
928
|
+
required: false,
|
|
929
|
+
unique: false,
|
|
930
|
+
tabindex: 1,
|
|
931
|
+
min: 0,
|
|
932
|
+
max: 0,
|
|
933
|
+
hidden: false,
|
|
934
|
+
defaultValue: null,
|
|
935
|
+
inputGroupLeft: "",
|
|
936
|
+
inputGroupRight: "",
|
|
937
|
+
digitDecimal: 0,
|
|
938
|
+
decimalPlaces:",",
|
|
939
|
+
thousandSeparator:".",
|
|
940
|
+
symbol:"",
|
|
941
|
+
information: "",
|
|
942
|
+
},
|
|
943
|
+
typies: {
|
|
944
|
+
required: {
|
|
945
|
+
tag: "input",
|
|
946
|
+
type: "checkbox",
|
|
947
|
+
},
|
|
948
|
+
tabindex: {
|
|
949
|
+
tag: "input",
|
|
950
|
+
type: "number",
|
|
951
|
+
},
|
|
952
|
+
unique: {
|
|
953
|
+
tag: "input",
|
|
954
|
+
type: "checkbox",
|
|
955
|
+
},
|
|
956
|
+
min: {
|
|
957
|
+
tag: "input",
|
|
958
|
+
type: "number",
|
|
959
|
+
},
|
|
960
|
+
max: {
|
|
961
|
+
tag: "input",
|
|
962
|
+
type: "number",
|
|
963
|
+
},
|
|
964
|
+
hidden: {
|
|
965
|
+
tag: "input",
|
|
966
|
+
type: "checkbox",
|
|
967
|
+
},
|
|
968
|
+
defaultValue: {
|
|
969
|
+
tag: "input",
|
|
970
|
+
type: "number",
|
|
971
|
+
},
|
|
972
|
+
inputGroupLeft: {
|
|
973
|
+
tag: "input",
|
|
974
|
+
type: "text",
|
|
975
|
+
},
|
|
976
|
+
inputGroupRight: {
|
|
977
|
+
tag: "input",
|
|
978
|
+
type: "text",
|
|
979
|
+
},
|
|
980
|
+
digitDecimal: {
|
|
981
|
+
tag: "input",
|
|
982
|
+
type: "number",
|
|
983
|
+
},
|
|
984
|
+
decimalPlaces: {
|
|
985
|
+
tag: "input",
|
|
986
|
+
type: "text",
|
|
987
|
+
},
|
|
988
|
+
thousandSeparator: {
|
|
989
|
+
tag: "input",
|
|
990
|
+
type: "text",
|
|
991
|
+
},
|
|
992
|
+
symbol: {
|
|
993
|
+
tag: "input",
|
|
994
|
+
type: "text",
|
|
995
|
+
},
|
|
996
|
+
information: {
|
|
997
|
+
tag: "textarea",
|
|
998
|
+
type: "",
|
|
999
|
+
class: "",
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
comment: (obj = {}) => {
|
|
1003
|
+
return `money`;
|
|
1004
|
+
},
|
|
1005
|
+
sql: (key, MYMODEL, obj = {}) => {
|
|
1006
|
+
const required = !obj.required ? false : true;
|
|
1007
|
+
const digitDecimal = obj.digitDecimal || 0;
|
|
1008
|
+
let defaultValue = "";
|
|
1009
|
+
if (!obj.defaultValue) {
|
|
1010
|
+
defaultValue = ``;
|
|
1011
|
+
} else if (obj.defaultValue == "null") {
|
|
1012
|
+
defaultValue = `ALTER TABLE "${MYMODEL.table}" ALTER COLUMN "${key}" SET DEFAULT NULL;`;
|
|
1013
|
+
} else {
|
|
1014
|
+
defaultValue = `ALTER TABLE "${MYMODEL.table}" ALTER COLUMN "${key}" SET DEFAULT ${obj.defaultValue};`;
|
|
1015
|
+
}
|
|
1016
|
+
const indexing = !obj.unique
|
|
1017
|
+
? ""
|
|
1018
|
+
: ` ALTER TABLE "${MYMODEL.table}" ADD CONSTRAINT unique_${MYMODEL.table}_${key} UNIQUE (${key});`;
|
|
1019
|
+
|
|
1020
|
+
const addTable = `ALTER TABLE "${MYMODEL.table}" ADD COLUMN "${key}" NUMERIC(15, ${digitDecimal});`;
|
|
1021
|
+
return {
|
|
1022
|
+
defaultValue: defaultValue,
|
|
1023
|
+
column: addTable,
|
|
1024
|
+
index: indexing,
|
|
1025
|
+
foreignKey: "",
|
|
1026
|
+
};
|
|
1027
|
+
},
|
|
1028
|
+
columnType: (obj = {}) => {
|
|
1029
|
+
return `money`;
|
|
1030
|
+
},
|
|
1031
|
+
category: "money",
|
|
1032
|
+
};
|
|
1033
|
+
|
|
891
1034
|
Model.number = {
|
|
892
1035
|
properties: [
|
|
893
1036
|
"required",
|
|
@@ -3155,6 +3298,36 @@ Model.custom = {
|
|
|
3155
3298
|
category: "custom",
|
|
3156
3299
|
};
|
|
3157
3300
|
|
|
3301
|
+
Model.html = {
|
|
3302
|
+
properties: ["code"],
|
|
3303
|
+
labels: {
|
|
3304
|
+
code: "Code",
|
|
3305
|
+
},
|
|
3306
|
+
defaultValues: {
|
|
3307
|
+
code: "<h1>Hello World</h1>",
|
|
3308
|
+
},
|
|
3309
|
+
typies: {
|
|
3310
|
+
code: {
|
|
3311
|
+
tag: "textarea",
|
|
3312
|
+
type: "",
|
|
3313
|
+
},
|
|
3314
|
+
},
|
|
3315
|
+
comment: (obj = {}) => {
|
|
3316
|
+
return ``;
|
|
3317
|
+
},
|
|
3318
|
+
sql: (key, MYMODEL, obj = {}) => {
|
|
3319
|
+
return {
|
|
3320
|
+
index: "",
|
|
3321
|
+
foreignKey: "",
|
|
3322
|
+
};
|
|
3323
|
+
},
|
|
3324
|
+
columnType: (obj = {}) => {
|
|
3325
|
+
return ``;
|
|
3326
|
+
},
|
|
3327
|
+
category: "custom",
|
|
3328
|
+
};
|
|
3329
|
+
|
|
3330
|
+
|
|
3158
3331
|
Model.hardcodeGrid = `const data = await zRoute.listData(req, res, MYMODEL, zRole);
|
|
3159
3332
|
${Util.tab}res.json(data);`;
|
|
3160
3333
|
|
package/lib/Util.js
CHANGED
|
@@ -660,16 +660,18 @@ Util.toNumber = function (num) {
|
|
|
660
660
|
Util.formatNumber = function (num, thousandSeparator = ".") {
|
|
661
661
|
try {
|
|
662
662
|
const strValue = String(num);
|
|
663
|
-
// Split into integer and decimal parts
|
|
664
|
-
const parts = strValue.split("
|
|
663
|
+
// Split into integer and decimal parts (input usually has "." as decimal separator)
|
|
664
|
+
const parts = strValue.split(".");
|
|
665
665
|
// Format integer part with thousand separators
|
|
666
666
|
const integerPart = parts[0].replace(
|
|
667
667
|
/\B(?=(\d{3})+(?!\d))/g,
|
|
668
668
|
thousandSeparator
|
|
669
669
|
);
|
|
670
|
+
// Determine decimal separator: if thousandSeparator is ".", use ","; otherwise use "."
|
|
671
|
+
let decimalSeparator = thousandSeparator === "." ? "," : ".";
|
|
670
672
|
// If there's a decimal part, add it back
|
|
671
673
|
if (parts.length > 1) {
|
|
672
|
-
return `${integerPart}
|
|
674
|
+
return `${integerPart}${decimalSeparator}${parts[1]}`;
|
|
673
675
|
}
|
|
674
676
|
return integerPart;
|
|
675
677
|
} catch (e) {
|
package/lib/generatorApi.js
CHANGED
|
@@ -370,8 +370,8 @@ function containerObject(left,right,oneColumn,tabs = []) {
|
|
|
370
370
|
Api.modalWithContainer = async (body) => {
|
|
371
371
|
try {
|
|
372
372
|
//let body = req.body;
|
|
373
|
-
/* console.log(body)
|
|
374
|
-
|
|
373
|
+
/* console.log(body)
|
|
374
|
+
console.log("Container....")*/
|
|
375
375
|
let table = body.table || "";
|
|
376
376
|
let html = '';
|
|
377
377
|
let fields = [];
|
|
@@ -613,16 +613,16 @@ Api.modalClassic = async (body) => {
|
|
|
613
613
|
});
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
616
|
+
/* console.log(arrName);
|
|
617
|
+
console.log("tableft");
|
|
618
|
+
console.log(JSON.stringify(tabLeft));
|
|
619
|
+
console.log("tableft end");
|
|
620
|
+
console.log("tabright");
|
|
621
|
+
console.log(JSON.stringify(tabRight));
|
|
622
|
+
console.log("tabright");
|
|
623
|
+
console.log("tabonecolumn");
|
|
624
|
+
console.log(JSON.stringify(tabOneColum));
|
|
625
|
+
console.log("tabonecolumn end");*/
|
|
626
626
|
|
|
627
627
|
|
|
628
628
|
if (tabLeft.length) {
|
|
@@ -673,16 +673,16 @@ Api.modalClassic = async (body) => {
|
|
|
673
673
|
}
|
|
674
674
|
}
|
|
675
675
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
676
|
+
/* var rows = [];
|
|
677
|
+
if (Util.isEmptyObject(datas.details)) {
|
|
678
|
+
rows = await fieldsTable(table, rowsFields);
|
|
679
|
+
} else {
|
|
680
|
+
var d = datas.details;
|
|
681
|
+
var notabs = d.hasOwnProperty('notabs') ? d.notabs : [];
|
|
682
|
+
for (var i = 0; i < notabs.length; i++) {
|
|
683
|
+
rows.push({name: notabs[i], label: datas.labels[notabs[i]]})
|
|
684
|
+
}
|
|
685
|
+
}*/
|
|
686
686
|
|
|
687
687
|
//caption left or right
|
|
688
688
|
if (datas.left.length) {
|
|
@@ -971,10 +971,10 @@ Api.create_field = (body) => {
|
|
|
971
971
|
}
|
|
972
972
|
}
|
|
973
973
|
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
974
|
+
/* console.log(JSON.stringify(left))
|
|
975
|
+
console.log(JSON.stringify(right))
|
|
976
|
+
console.log(JSON.stringify(oneColumn))
|
|
977
|
+
console.log(position);*/
|
|
978
978
|
|
|
979
979
|
let othersLength = Object.keys(others).length;
|
|
980
980
|
if(othersLength) {
|
|
@@ -1128,7 +1128,7 @@ const createTable = (postData, isIgnore) => {
|
|
|
1128
1128
|
let name = postData.name;
|
|
1129
1129
|
name = name.trim();
|
|
1130
1130
|
let forbidden = ['group','copy','command','from','select','distinct','where','year','month','day','ignore','previous','next',
|
|
1131
|
-
|
|
1131
|
+
'start','end','set','setof','show','size','row','rows','return','order'];
|
|
1132
1132
|
if(forbidden.includes(name)) {
|
|
1133
1133
|
json = Util.flashError("Module Name is Forbidden, try using other module name..", "route");
|
|
1134
1134
|
return json;
|
package/lib/generatorModel.js
CHANGED
|
@@ -449,6 +449,13 @@ me.prepare = (MYMODEL) => {
|
|
|
449
449
|
? 400
|
|
450
450
|
: property.values.height;
|
|
451
451
|
break;
|
|
452
|
+
case "html":
|
|
453
|
+
widgets[key].code = property.values.code || "";
|
|
454
|
+
break;
|
|
455
|
+
|
|
456
|
+
case "money":
|
|
457
|
+
widgets[key].symbol = property.values.symbol || "";
|
|
458
|
+
break;
|
|
452
459
|
|
|
453
460
|
default:
|
|
454
461
|
break;
|
|
@@ -560,16 +567,12 @@ me.build_sql_api = (columns, constraintList, MYMODEL) => {
|
|
|
560
567
|
}
|
|
561
568
|
}
|
|
562
569
|
}
|
|
563
|
-
|
|
564
|
-
//var constraintList = await connection.query(connection.constraintList(MYMODEL.table));
|
|
565
|
-
//make a object instead of array
|
|
566
570
|
const constraintObject = Util.arrayToObject(constraintList, "conname");
|
|
567
|
-
|
|
568
571
|
const alter = [];
|
|
569
572
|
const index = [];
|
|
570
573
|
const defaultValue = [];
|
|
571
574
|
const fk = [];
|
|
572
|
-
const notAlters = ["virtual", "custom"];
|
|
575
|
+
const notAlters = ["virtual", "custom","html"];
|
|
573
576
|
for (const key in properties) {
|
|
574
577
|
const property = properties[key];
|
|
575
578
|
if (!notAlters.includes(property.type)) {
|
|
@@ -599,6 +602,14 @@ me.build_sql_api = (columns, constraintList, MYMODEL) => {
|
|
|
599
602
|
index.push(`DROP INDEX ${idx}; `);
|
|
600
603
|
}
|
|
601
604
|
}
|
|
605
|
+
if(property.type == "money"){
|
|
606
|
+
//ALTER TABLE nama_tabel
|
|
607
|
+
// ALTER COLUMN nama_kolom TYPE NUMERIC(15,2);
|
|
608
|
+
let digitDecimal = properties[key].values.digitDecimal || 0;
|
|
609
|
+
alter.push(
|
|
610
|
+
`ALTER TABLE "${MYMODEL.table}" ALTER COLUMN "${key}" TYPE NUMERIC(15,${digitDecimal});; `
|
|
611
|
+
);
|
|
612
|
+
}
|
|
602
613
|
//relations foreign key
|
|
603
614
|
const fkx = `fk_${MYMODEL.table}_${key}`;
|
|
604
615
|
if (sqlObject.foreignKey) {
|
package/lib/moduleLib.js
CHANGED
|
@@ -53,9 +53,9 @@ m.datepicker = function (req, res, elem) {
|
|
|
53
53
|
/* head += '<link href="/css/bootstrap-datepicker.css" rel="stylesheet">';
|
|
54
54
|
end += '<script src="/js/bootstrap-datepicker.min.js"></script>';*/
|
|
55
55
|
head +=
|
|
56
|
-
|
|
56
|
+
'<link href="/modules/bootstrap-datepicker/bootstrap-datepicker.min.css" rel="stylesheet">';
|
|
57
57
|
end +=
|
|
58
|
-
|
|
58
|
+
'<script src="/modules/bootstrap-datepicker/bootstrap-datepicker.min.js"></script>';
|
|
59
59
|
script = `$.fn.datepicker.defaults.format = "yyyy-mm-dd";$.fn.datepicker.defaults.todayHighlight = true;$("body").on("click", "${elem}", function(){$(this).datepicker();$(this).datepicker("show");});`;
|
|
60
60
|
|
|
61
61
|
return {
|
|
@@ -74,7 +74,7 @@ m.selectize = function (req, res, elem) {
|
|
|
74
74
|
let end = ``;
|
|
75
75
|
elem = elem || ".selectize";
|
|
76
76
|
head +=
|
|
77
|
-
|
|
77
|
+
'<link href="/modules/selectizejs/css/selectize.bootstrap5.css" rel="stylesheet">';
|
|
78
78
|
end += '<script src="/modules/selectizejs/js/selectize.min.js"></script>';
|
|
79
79
|
|
|
80
80
|
script += `$(() => {
|
|
@@ -339,11 +339,11 @@ m.datetimepicker = function (req, res, elem) {
|
|
|
339
339
|
let end = ``;
|
|
340
340
|
elem = elem || ".datetimepicker";
|
|
341
341
|
head +=
|
|
342
|
-
|
|
342
|
+
'<link href="/css/bootstrap-datetimepicker.min.css" rel="stylesheet" />';
|
|
343
343
|
end +=
|
|
344
|
-
|
|
344
|
+
'<script type="text/javascript" src="/js/moment-with-locales.min.js" ></script>';
|
|
345
345
|
end +=
|
|
346
|
-
|
|
346
|
+
'<script type="text/javascript" src="/js/bootstrap-datetimepicker.min.js" ></script>';
|
|
347
347
|
script += `$(function () { $("${elem}").datetimepicker({format:'YYYY-MM-DD hh:mm:ss'}); });`;
|
|
348
348
|
script += `setTimeout(function () { $("body").click();},1000);`;
|
|
349
349
|
script += `$("body").on("click", function(){$("${elem}").datetimepicker({format:'YYYY-MM-DD hh:mm:ss'});});`;
|
|
@@ -362,14 +362,14 @@ m.ckeditor = function (req, res, elem) {
|
|
|
362
362
|
let end = ``;
|
|
363
363
|
elem = elem || ".editor";
|
|
364
364
|
end +=
|
|
365
|
-
|
|
366
|
-
|
|
365
|
+
'<script src="/modules/ckeditor5-build-classic/ckeditor.js"></script>' +
|
|
366
|
+
newLine;
|
|
367
367
|
end += "<script>";
|
|
368
368
|
end +=
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
369
|
+
'ClassicEditor.create( document.querySelector( "' +
|
|
370
|
+
elem +
|
|
371
|
+
'" ) ).catch( error => {console.error( error );} );' +
|
|
372
|
+
newLine;
|
|
373
373
|
end += "</script>";
|
|
374
374
|
return {
|
|
375
375
|
head: head,
|
|
@@ -385,8 +385,8 @@ m.tinymce = function (req, res, elem) {
|
|
|
385
385
|
let end = ``;
|
|
386
386
|
elem = elem || ".tinymce";
|
|
387
387
|
end +=
|
|
388
|
-
|
|
389
|
-
|
|
388
|
+
'<script src="https://cdn.tiny.cloud/1/b7054u42l8lw67ch5oh9qutnvbyu8exzryg4edy0gg2snhtr/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>' +
|
|
389
|
+
newLine;
|
|
390
390
|
script += ` tinymce.init({
|
|
391
391
|
selector: '${elem}',
|
|
392
392
|
plugins: 'anchor autolink charmap codesample emoticons image link lists media searchreplace table visualblocks wordcount',
|
|
@@ -407,11 +407,11 @@ m.froala = function (req, res, elem) {
|
|
|
407
407
|
elem = elem || ".editor";
|
|
408
408
|
|
|
409
409
|
head +=
|
|
410
|
-
|
|
410
|
+
'<link href="https://cdn.jsdelivr.net/npm/froala-editor@2.9.0/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />';
|
|
411
411
|
head +=
|
|
412
|
-
|
|
412
|
+
'<link href="https://cdn.jsdelivr.net/npm/froala-editor@2.9.0/css/froala_style.min.css" rel="stylesheet" type="text/css" />';
|
|
413
413
|
end +=
|
|
414
|
-
|
|
414
|
+
'<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/froala-editor@2.9.0/js/froala_editor.pkgd.min.js"></script>';
|
|
415
415
|
script += `$(function() {$("${elem}").froalaEditor({height: 200})});`;
|
|
416
416
|
|
|
417
417
|
return {
|
|
@@ -449,13 +449,13 @@ m.editor = (req, res, elem = "") => {
|
|
|
449
449
|
let end = ``;
|
|
450
450
|
|
|
451
451
|
head +=
|
|
452
|
-
|
|
452
|
+
'<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.4.2/css/all.min.css" integrity="sha512-NicFTMUg/LwBeG8C7VG+gC4YiiRtQACl98QdkmfsLy37RzXdkaUAuPyVMND0olPP4Jn8M/ctesGSB2pgUBDRIw==" crossorigin="anonymous" referrerpolicy="no-referrer" />';
|
|
453
453
|
head +=
|
|
454
|
-
|
|
454
|
+
'<link href="https://cdn.jsdelivr.net/npm/froala-editor@2.9.0/css/froala_editor.pkgd.min.css" rel="stylesheet" type="text/css" />';
|
|
455
455
|
head +=
|
|
456
|
-
|
|
456
|
+
'<link href="https://cdn.jsdelivr.net/npm/froala-editor@2.9.0/css/froala_style.min.css" rel="stylesheet" type="text/css" />';
|
|
457
457
|
end +=
|
|
458
|
-
|
|
458
|
+
'<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/froala-editor@2.9.0/js/froala_editor.pkgd.min.js"></script>';
|
|
459
459
|
script += `$(function() {$("${elem}").froalaEditor({height: 200})});`;
|
|
460
460
|
|
|
461
461
|
return {
|
|
@@ -472,11 +472,11 @@ m.switch = function (req, res, elem, array) {
|
|
|
472
472
|
let end = ``;
|
|
473
473
|
|
|
474
474
|
head +=
|
|
475
|
-
|
|
476
|
-
|
|
475
|
+
'<link href="/modules/bootstrap-switch/bootstrap-switch.css" rel="stylesheet" type="text/css" />' +
|
|
476
|
+
newLine;
|
|
477
477
|
end +=
|
|
478
|
-
|
|
479
|
-
|
|
478
|
+
'<script type="text/javascript" src="/modules/bootstrap-switch/bootstrap-switch.js"></script>' +
|
|
479
|
+
newLine;
|
|
480
480
|
|
|
481
481
|
let labels = "";
|
|
482
482
|
if (Array.isArray(array)) {
|
|
@@ -496,11 +496,11 @@ m.switchOld = function (req, res, elem, array) {
|
|
|
496
496
|
let end = ``;
|
|
497
497
|
elem = elem || ".switch";
|
|
498
498
|
head +=
|
|
499
|
-
|
|
500
|
-
|
|
499
|
+
'<link href="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/css/bootstrap4-toggle.min.css" rel="stylesheet">' +
|
|
500
|
+
newLine;
|
|
501
501
|
end +=
|
|
502
|
-
|
|
503
|
-
|
|
502
|
+
'<script src="https://cdn.jsdelivr.net/gh/gitbrent/bootstrap4-toggle@3.6.1/js/bootstrap4-toggle.min.js"></script>' +
|
|
503
|
+
newLine;
|
|
504
504
|
|
|
505
505
|
let labels = "";
|
|
506
506
|
if (Array.isArray(array)) {
|
|
@@ -521,11 +521,11 @@ m.clockpicker = function (req, res, elem) {
|
|
|
521
521
|
let end = ``;
|
|
522
522
|
elem = elem || ".clockpicker";
|
|
523
523
|
head +=
|
|
524
|
-
|
|
525
|
-
|
|
524
|
+
'<link href="/modules/jquery-clockpicker.min.css" rel="stylesheet" type="text/css" />' +
|
|
525
|
+
newLine;
|
|
526
526
|
end +=
|
|
527
|
-
|
|
528
|
-
|
|
527
|
+
'<script type="text/javascript" src="/modules/bootstrap-clockpicker.min.js"></script>' +
|
|
528
|
+
newLine;
|
|
529
529
|
script += `$("body").on("click", "${elem}", function(){$(this).clockpicker({donetext: "Done"});});`;
|
|
530
530
|
//end += '$("' + elem + '").clockpicker({donetext: "Done"});' + newLine;
|
|
531
531
|
return {
|
|
@@ -542,7 +542,7 @@ m.number = (req, res, elem) => {
|
|
|
542
542
|
elem = elem || ".number";
|
|
543
543
|
|
|
544
544
|
end +=
|
|
545
|
-
|
|
545
|
+
'<script type="text/javascript" src="/js/jquery-currency.js"></script>';
|
|
546
546
|
script += `$(function () { $(".number").formatCurrencyLive({symbol:"",roundToDecimalPlace :0,digitGroupSymbol :"."}); });`;
|
|
547
547
|
script += `setTimeout(function () { $("body").click();},1000);`;
|
|
548
548
|
script += `$("body").on("click", function(){$(".number").formatCurrencyLive({symbol:"",roundToDecimalPlace :0,digitGroupSymbol :"."});});`;
|
|
@@ -560,8 +560,8 @@ m.typeahead = (req, res, table, elem) => {
|
|
|
560
560
|
let end = ``;
|
|
561
561
|
elem = elem || ".typeahead";
|
|
562
562
|
end +=
|
|
563
|
-
|
|
564
|
-
|
|
563
|
+
'<script type="text/javascript" src="/modules/typeahead/typeahead.js"></script>' +
|
|
564
|
+
newLine;
|
|
565
565
|
|
|
566
566
|
let elemData = elem.replace(".", "").replace("#", "");
|
|
567
567
|
let element = elem.replace("Typeahead", "");
|
|
@@ -607,8 +607,8 @@ m.typeaheadFile = (req, res, elem, data) => {
|
|
|
607
607
|
data = data || [];
|
|
608
608
|
elem = elem || ".typeahead";
|
|
609
609
|
end +=
|
|
610
|
-
|
|
611
|
-
|
|
610
|
+
'<script type="text/javascript" src="/modules/typeahead/typeahead.js"></script>' +
|
|
611
|
+
newLine;
|
|
612
612
|
|
|
613
613
|
let elemData = elem.replace(".", "");
|
|
614
614
|
elemData = elemData.replace("#", "");
|
|
@@ -661,7 +661,7 @@ m.dropboxview = (req, res) => {
|
|
|
661
661
|
let head = ``;
|
|
662
662
|
let end = ``;
|
|
663
663
|
script +=
|
|
664
|
-
|
|
664
|
+
`let dropbox_image = {}
|
|
665
665
|
$(()=>{
|
|
666
666
|
$(".zdropbox-view").each(function (index, item) {
|
|
667
667
|
let dropboxLength = $(".zdropbox-view").length || 0;
|
|
@@ -729,9 +729,9 @@ m.addScript = (req, res, contentScript, at = "end", type = "script") => {
|
|
|
729
729
|
if (contentScript) {
|
|
730
730
|
let generateId = "app_" + Util.generate(6);
|
|
731
731
|
let tagOpen =
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
732
|
+
type == "script"
|
|
733
|
+
? `<script id="${generateId}">`
|
|
734
|
+
: '<style type="text/css">';
|
|
735
735
|
let tagClose = type == "script" ? "</script>" : "</style>";
|
|
736
736
|
let content = at == "end" ? res.locals.moduleEnd : res.locals.moduleHead;
|
|
737
737
|
content += tagOpen + newLine;
|
|
@@ -746,8 +746,8 @@ m.addScript = (req, res, contentScript, at = "end", type = "script") => {
|
|
|
746
746
|
|
|
747
747
|
m.addModule = (req, res, content, isModuleHead = false) => {
|
|
748
748
|
let moduleContent = isModuleHead
|
|
749
|
-
|
|
750
|
-
|
|
749
|
+
? res.locals.moduleHead
|
|
750
|
+
: res.locals.moduleEnd;
|
|
751
751
|
moduleContent += content;
|
|
752
752
|
if (isModuleHead) {
|
|
753
753
|
res.locals.moduleHead = moduleContent;
|
|
@@ -762,8 +762,8 @@ m.highchart = async (req, res, obj) => {
|
|
|
762
762
|
let end = res.locals.moduleEnd;
|
|
763
763
|
if (end.indexOf("highcharts") < 0) {
|
|
764
764
|
end +=
|
|
765
|
-
|
|
766
|
-
|
|
765
|
+
'<script src="https://code.highcharts.com/highcharts.js"></script>' +
|
|
766
|
+
newLine;
|
|
767
767
|
}
|
|
768
768
|
|
|
769
769
|
if (!Util.isEmptyObject(obj)) {
|
|
@@ -821,16 +821,16 @@ m.highlight = (req, res, elem) => {
|
|
|
821
821
|
let end = res.locals.moduleEnd;
|
|
822
822
|
if (head.indexOf("highlight") < 0) {
|
|
823
823
|
head +=
|
|
824
|
-
|
|
825
|
-
|
|
824
|
+
'<link rel="stylesheet" href="/modules/highlight/default.min.css"> ' +
|
|
825
|
+
newLine;
|
|
826
826
|
end +=
|
|
827
|
-
|
|
827
|
+
'<script src="/modules/highlight/highlight.min.js"></script>' + newLine;
|
|
828
828
|
}
|
|
829
829
|
end +=
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
830
|
+
'<script>$(function(){ document.querySelectorAll("' +
|
|
831
|
+
elem +
|
|
832
|
+
'").forEach((block) => {hljs.highlightBlock(block);}); })</script>' +
|
|
833
|
+
newLine;
|
|
834
834
|
res.locals.moduleHead = head;
|
|
835
835
|
res.locals.moduleEnd = end;
|
|
836
836
|
};
|
|
@@ -842,11 +842,11 @@ m.selectpicker = function (req, res, elem) {
|
|
|
842
842
|
let end = res.locals.moduleEnd;
|
|
843
843
|
if (head.indexOf("bootstrap-select") < 0) {
|
|
844
844
|
head +=
|
|
845
|
-
|
|
846
|
-
|
|
845
|
+
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.14/dist/css/bootstrap-select.min.css">' +
|
|
846
|
+
newLine;
|
|
847
847
|
end +=
|
|
848
|
-
|
|
849
|
-
|
|
848
|
+
'<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.13.14/dist/js/bootstrap-select.min.js"></script>' +
|
|
849
|
+
newLine;
|
|
850
850
|
end += `<script>$(function () {$('${elem}').selectpicker();});</script>${newLine}`;
|
|
851
851
|
}
|
|
852
852
|
res.locals.moduleHead = head;
|
|
@@ -139,8 +139,8 @@
|
|
|
139
139
|
dropdownRelations('dropdown_multi_table', 'dropdown_multi_name', '', $('#dropdown_multi_table').data('value'), $('#dropdown_multi_name').data('value'))
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
$("#
|
|
143
|
-
$("#
|
|
142
|
+
$("#money_decimalPlaces").css("font-size","2rem");
|
|
143
|
+
$("#money_thousandSeparator").css("font-size","2rem");
|
|
144
144
|
}
|
|
145
145
|
)
|
|
146
146
|
$('#modal_setting').modal('show')
|
package/lib/zRoute.js
CHANGED
|
@@ -329,6 +329,42 @@ zRoute.post = (req, res, MYMODEL, routeName, body) => {
|
|
|
329
329
|
post[routeName][key] = val ? val : val === 0 ? 0 : null;
|
|
330
330
|
break;
|
|
331
331
|
|
|
332
|
+
case "money":
|
|
333
|
+
if (typeof val == "string" && val.trim() !== "") {
|
|
334
|
+
// Get widget configuration
|
|
335
|
+
const widgetConfig = widgets[key] || {};
|
|
336
|
+
const symbol = widgetConfig.symbol || "";
|
|
337
|
+
const thousandSeparator = widgetConfig.thousandSeparator || ",";
|
|
338
|
+
const decimalPlaces = widgetConfig.decimalPlaces || ".";
|
|
339
|
+
|
|
340
|
+
// Remove symbol if present
|
|
341
|
+
let cleanedVal = val.trim();
|
|
342
|
+
if (symbol && cleanedVal.startsWith(symbol)) {
|
|
343
|
+
cleanedVal = cleanedVal.substring(symbol.length).trim();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Remove thousand separators
|
|
347
|
+
if (thousandSeparator) {
|
|
348
|
+
// Escape special regex characters
|
|
349
|
+
const escapedThousandSep = thousandSeparator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
350
|
+
cleanedVal = cleanedVal.replace(new RegExp(escapedThousandSep, 'g'), '');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Replace decimal separator with standard dot
|
|
354
|
+
if (decimalPlaces && decimalPlaces !== ".") {
|
|
355
|
+
// Escape special regex characters
|
|
356
|
+
const escapedDecimalSep = decimalPlaces.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
357
|
+
cleanedVal = cleanedVal.replace(escapedDecimalSep, '.');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Convert to number
|
|
361
|
+
const numVal = parseFloat(cleanedVal);
|
|
362
|
+
post[routeName][key] = isNaN(numVal) ? null : numVal;
|
|
363
|
+
} else {
|
|
364
|
+
post[routeName][key] = val ? val : val === 0 ? 0 : null;
|
|
365
|
+
}
|
|
366
|
+
break;
|
|
367
|
+
|
|
332
368
|
case "json_array":
|
|
333
369
|
myval = null;
|
|
334
370
|
if (val) {
|
|
@@ -400,6 +436,9 @@ zRoute.attributeData = async (res, MYMODEL, obj) => {
|
|
|
400
436
|
if (MYMODEL.widgets[key].name == "custom") {
|
|
401
437
|
customs.push(key);
|
|
402
438
|
}
|
|
439
|
+
if (MYMODEL.widgets[key].name == "html") {
|
|
440
|
+
customs.push(key);
|
|
441
|
+
}
|
|
403
442
|
}
|
|
404
443
|
if (customs.length) {
|
|
405
444
|
visibles = visibles.filter((item) => !customs.includes(item));
|
|
@@ -1269,6 +1308,10 @@ zRoute.dataTableData = (
|
|
|
1269
1308
|
myvalue = Util.formatNumber(value);
|
|
1270
1309
|
break;
|
|
1271
1310
|
|
|
1311
|
+
case "money":
|
|
1312
|
+
myvalue = `${MYMODEL.widgets[key].symbol} ${Util.formatNumber(value, MYMODEL.widgets[key].thousandSeparator)}`;
|
|
1313
|
+
break;
|
|
1314
|
+
|
|
1272
1315
|
case "integer":
|
|
1273
1316
|
myvalue = value + "";
|
|
1274
1317
|
break;
|
|
@@ -3103,6 +3146,10 @@ zRoute.forms = (
|
|
|
3103
3146
|
case "tags":
|
|
3104
3147
|
obj.type = "tags";
|
|
3105
3148
|
break;
|
|
3149
|
+
case "html":
|
|
3150
|
+
obj.type = "html";
|
|
3151
|
+
obj.code = widgets[key].code || ""
|
|
3152
|
+
break;
|
|
3106
3153
|
case "checkbox":
|
|
3107
3154
|
obj.type = "checkbox";
|
|
3108
3155
|
break;
|
|
@@ -3716,7 +3763,10 @@ zRoute.viewForm = (
|
|
|
3716
3763
|
obj[key].value = data[key] || "";
|
|
3717
3764
|
break;
|
|
3718
3765
|
case "number":
|
|
3719
|
-
obj[key].value = data[key] ? Util.formatNumber(data[key], "
|
|
3766
|
+
obj[key].value = data[key] ? Util.formatNumber(data[key], ".") : "";
|
|
3767
|
+
break;
|
|
3768
|
+
case "money":
|
|
3769
|
+
obj[key].value = data[key] ? `${widgets[key].symbol} ${Util.formatNumber(data[key], ".")}` : "";
|
|
3720
3770
|
break;
|
|
3721
3771
|
case "typeahead":
|
|
3722
3772
|
obj[key].type = "text";
|
|
@@ -4120,6 +4170,7 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
|
|
|
4120
4170
|
let hasAttributes = [];
|
|
4121
4171
|
let joinsFields = [];
|
|
4122
4172
|
let selectize = [];
|
|
4173
|
+
let moneys = [];
|
|
4123
4174
|
if (MYMODEL.joins) {
|
|
4124
4175
|
joinsFields = MYMODEL.joins.list;
|
|
4125
4176
|
}
|
|
@@ -4129,6 +4180,9 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
|
|
|
4129
4180
|
hasDatePicker = true;
|
|
4130
4181
|
} else if (widgets[key].name == "number") {
|
|
4131
4182
|
hasNumber = true;
|
|
4183
|
+
} else if (widgets[key].name == "money") {
|
|
4184
|
+
hasNumber = true;
|
|
4185
|
+
moneys.push(key);
|
|
4132
4186
|
} else if (widgets[key].name == "clockpicker") {
|
|
4133
4187
|
hasClockPicker = true;
|
|
4134
4188
|
} else if (widgets[key].name == "editor") {
|
|
@@ -4220,6 +4274,24 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
|
|
|
4220
4274
|
scriptForm += numberObj.script;
|
|
4221
4275
|
headObj.number = numberObj.head;
|
|
4222
4276
|
endObj.number = numberObj.end;
|
|
4277
|
+
if(moneys.length > 0) {
|
|
4278
|
+
let moneyScript = ``
|
|
4279
|
+
moneys.map((money) => {
|
|
4280
|
+
moneyScript += `$('#${money}').formatCurrency({
|
|
4281
|
+
symbol: '${widgets[money].symbol || "" }',
|
|
4282
|
+
decimalSymbol: '${widgets[money].decimalPlaces || "," }',
|
|
4283
|
+
digitGroupSymbol: '${widgets[money].thousandSeparator || "." }',
|
|
4284
|
+
roundToDecimalPlace: ${widgets[money].digitDecimal || 0}
|
|
4285
|
+
});`
|
|
4286
|
+
moneyScript += `$('#${money}').formatCurrencyLive({
|
|
4287
|
+
symbol: '${widgets[money].symbol || "" }',
|
|
4288
|
+
decimalSymbol: '${widgets[money].decimalPlaces || "," }',
|
|
4289
|
+
digitGroupSymbol: '${widgets[money].thousandSeparator || "." }',
|
|
4290
|
+
roundToDecimalPlace: ${widgets[money].digitDecimal || 0}
|
|
4291
|
+
});`
|
|
4292
|
+
})
|
|
4293
|
+
scriptForm += ` $(function() {${moneyScript}});`;
|
|
4294
|
+
}
|
|
4223
4295
|
}
|
|
4224
4296
|
if (hasClockPicker) {
|
|
4225
4297
|
let clockpickerObj = moduleLib.clockpicker(req, res);
|