zet-lib 4.0.0 → 4.0.2

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/zReport.js CHANGED
@@ -3,7 +3,6 @@ const fs = require('fs-extra')
3
3
  const nodemailer = require('nodemailer')
4
4
  const qs = require('qs')
5
5
  const moment = require('moment')
6
- const XLSX = require('xlsx')
7
6
  const Excel = require('exceljs')
8
7
  const debug = require('./debug')
9
8
  const zRoute = require('./zRoute')
@@ -25,13 +24,43 @@ if (typeof global.dirRoot === 'undefined') {
25
24
  /*
26
25
  UI For edit excel File
27
26
  */
28
- zReport.reportData = (filename, data, sessions = {}) => {
29
- console.log(filename)
30
- const workbook = XLSX.readFile(filename)
31
- const Sheets = workbook.Sheets
32
- let sheet = Sheets[Object.keys(Sheets)[0]]
27
+ function colToLetter (col) {
28
+ let temp = ''
29
+ let n = col
30
+ while (n > 0) {
31
+ const r = (n - 1) % 26
32
+ temp = String.fromCharCode(65 + r) + temp
33
+ n = Math.floor((n - 1) / 26)
34
+ }
35
+ return temp
36
+ }
37
+
38
+ function cellToPrimitive (cell) {
39
+ // exceljs cell.text is safest for UI display
40
+ if (!cell) return ''
41
+ if (typeof cell.text === 'string' && cell.text !== '') return cell.text
42
+ const v = cell.value
43
+ if (v == null) return ''
44
+ if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return v
45
+ if (typeof v === 'object') {
46
+ if (Object.prototype.hasOwnProperty.call(v, 'result')) return v.result ?? ''
47
+ if (Object.prototype.hasOwnProperty.call(v, 'text')) return v.text ?? ''
48
+ }
49
+ return String(v)
50
+ }
51
+
52
+ zReport.reportData = async (filename, data, sessions = {}) => {
53
+ const workbook = new Excel.Workbook()
54
+ await workbook.xlsx.readFile(filename)
55
+ const worksheet = workbook.worksheets[0]
56
+ if (!worksheet) {
57
+ throw new Error('Excel worksheet not found')
58
+ }
33
59
  let excel = Util.excelSequence()
34
- let ref = sheet['!ref']
60
+ const dim = worksheet.dimensions
61
+ const right = dim ? dim.right : (worksheet.actualColumnCount || 1)
62
+ const bottom = dim ? dim.bottom : (worksheet.actualRowCount || 1)
63
+ const ref = `A1:${colToLetter(right)}${bottom}`
35
64
  let explode = ref.split(':')
36
65
  let lastchar = explode[1]
37
66
  let stringPattern = /[A-Z]+/i
@@ -48,23 +77,23 @@ zReport.reportData = (filename, data, sessions = {}) => {
48
77
  let excelQuery = data.excel_query || {}
49
78
  let dataForExcel = excelQuery.excel
50
79
  let dataCallback = data.callback || []
51
- let callback = {}
80
+ let callbacks = {}
52
81
  let objQuery = {}
53
82
  let results = []
54
83
 
55
84
  //set callback as object
56
85
  dataCallback.map((m) => {
57
- callback[m.name] = m.value
86
+ callbacks[m.name] = m.value
58
87
  })
59
88
 
60
89
  //console.log(JSON.stringify(sessions));
61
90
 
62
91
  //create UI Button in excel cell
63
92
  if (dataForExcel) {
64
- dataForExcel.forEach((datafor, index) => {
93
+ dataForExcel.forEach((datafor) => {
65
94
  let button = '',
66
95
  name = datafor.name,
67
- callback = datafor.callback || '',
96
+ callbackValue = datafor.callback || '',
68
97
  value = datafor.value || ''
69
98
  let split = value.split('.')
70
99
  let len = split.length
@@ -93,7 +122,7 @@ zReport.reportData = (filename, data, sessions = {}) => {
93
122
 
94
123
  let labels = value.indexOf('_SESSIONS_') > -1 ? value.replace('_SESSIONS_.', '') : tableKey
95
124
  button += `<li class="dragged"> <button class="btn btn-info btn-excel" type="button" title="${name.replace('[', '').replace(']', '')} : ${value}">${MYMODEL.labels[labels]}
96
- <input type="hidden" class="EXCEL" name="${name}" value='${value}_CALLBACK_SEPARATOR_${callback}'> <i class="fa fa-code call-me"></i> <i class="fa fa-trash trash-me"></i></button></li>`
125
+ <input type="hidden" class="EXCEL" name="${name}" value='${value}_CALLBACK_SEPARATOR_${callbackValue}'> <i class="fa fa-code call-me"></i> <i class="fa fa-trash trash-me"></i></button></li>`
97
126
  excelValue[name] = button
98
127
  })
99
128
  }
@@ -106,7 +135,8 @@ zReport.reportData = (filename, data, sessions = {}) => {
106
135
  for (var i = 0; i <= maxColumn; i++) {
107
136
  let str = excel[i] + x
108
137
  let strkey = excel[i] + '[' + x + ']'
109
- let defaultValue = Object.prototype.hasOwnProperty.call(sheet, str) ? sheet[str].v : ''
138
+ const cell = worksheet.getCell(str)
139
+ let defaultValue = cellToPrimitive(cell)
110
140
  let value = excelValue[strkey] || defaultValue
111
141
  table += `<td width="80px" id="${str}" title="${str}" class="mydragable" data-col="${excel[i]}" data-row="${x}">${value}</td>`
112
142
  arr.push(value)
package/lib/zRoute.js CHANGED
@@ -4,7 +4,6 @@
4
4
  */
5
5
  require("dotenv").config();
6
6
  const path = require("path");
7
- const excelToJson = require("convert-excel-to-json");
8
7
  const qs = require("qs");
9
8
  //for generate PDF
10
9
  const puppeteer = require("puppeteer");
@@ -4802,6 +4801,29 @@ zRoute.generateJS = (req, res, MYMODEL, relations, zForms = "", data = {}) => {
4802
4801
  let relationsWithKeys = relations ? relations[keys] : {};
4803
4802
  let dropdownMultis = [];
4804
4803
 
4804
+ scriptForm += `function sanitizeUndefinedAttributes($scope) {
4805
+ $scope = $scope || $(document);
4806
+ $scope.find("input, textarea, select").each(function () {
4807
+ const $el = $(this);
4808
+ const badString = (x) =>
4809
+ typeof x === "string" && (x.trim().toLowerCase() === "undefined" || x.trim().toLowerCase() === "null");
4810
+
4811
+ // Only act if the attribute EXISTS and is an actual "undefined"/"null" string.
4812
+ // Many elements legitimately have no "value" attribute (e.g. textarea uses textContent).
4813
+ const hasValueAttr = $el[0] && $el[0].hasAttribute && $el[0].hasAttribute("value");
4814
+ const attrValue = hasValueAttr ? $el.attr("value") : null;
4815
+ if (hasValueAttr && badString(attrValue)) {
4816
+ $el.removeAttr("value");
4817
+ if ($el.is("input,textarea")) $el.val("");
4818
+ }
4819
+
4820
+ const dataT = $el.attr("data-t");
4821
+ if (badString(dataT)) {
4822
+ $el.removeAttr("data-t");
4823
+ }
4824
+ });
4825
+ }${Util.newLine}`
4826
+
4805
4827
  for (let qq in MODEL_TABLE.widgets) {
4806
4828
  //check if have dropdown_multi
4807
4829
  if (MODEL_TABLE.widgets[qq].name == "dropdown_multi") {
@@ -4870,56 +4892,83 @@ $("#body-${keys}>tr").each(function (index, tr) {
4870
4892
 
4871
4893
  }); ${Util.newLine}};${Util.newLine}`;
4872
4894
 
4873
- scriptForm += ` $('#add${keys}').on('click',function(){
4895
+ scriptForm += `
4896
+ $('#add${keys}').on('click',function(){
4874
4897
  append${keys}(append${keys}Max, (data) => $('#body-${keys}').append(data));
4875
4898
  append${keys}Max++;
4876
4899
  ${keys}Handler();
4900
+ sanitizeUndefinedAttributes($("#body-${keys}"));
4877
4901
  }); ${Util.newLine}`;
4878
4902
  scriptForm += `function set${keys}value(index,myobj) {
4879
- for(var key in myobj){
4880
- if($(".${subname}_" + key).eq(index).attr("type") == "checkbox" && myobj[key] == 1){
4881
- $(".${subname}_" + key).eq(index).prop("checked", true);
4882
- $(".${subname}_" + key).eq(index).val(myobj[key] ? myobj[key] : '');
4883
- } else if($(".${subname}_" + key).eq(index).attr("type") == "file"){
4884
- var myimg = myobj[key] ? myobj[key] : '';
4885
- var pathName = "/uploads/${MYMODEL.table}/${keys}/";
4886
- if(myimg) {
4887
- var filename = filenamex = pathName+myimg;
4888
- if (!myimg.match(/\\.(jpg|jpeg|png|gif|svg|jiff|avif)$/i)) {
4889
- filename = "/img/file.png";
4890
- }
4891
- $(".${subname}_" + key).eq(index).closest("TD").find("img").attr("src",filename).addClass("boxy");
4892
- $(".${subname}_" + key).eq(index).closest("TD").append('<a href="'+filenamex+'" target="_blank" style="font-size: 12px">'+myimg+'</a>');
4893
- }
4894
- } else if($(".${subname}_" + key).eq(index).hasClass("dropdown-multi")){
4895
- var dropdownsData = '';
4896
- var mydropdowns = myobj[key] || [];
4897
- mydropdowns.map((item, i) => {
4898
- var text = ${dropdownMultis[0]}Object[item];
4899
- dropdownsData += "<span class='span"+key+"' > "+(i+1)+". <input type='hidden' name='${MYMODEL.table}[${keys}]["+index+"]["+key+"]["+i+"]' value='"+item+"' /> " + text +" <img class='tabler-icons icons-filter-danger pull-right' src='/assets/icons/trash-filled.svg' onclick='$(this).closest(\`span\`).remove();' title='Delete' /> <br></span>";
4900
-
4901
- });
4902
- $(".${subname}_" + key).eq(index).closest("TD").find("#dropdownboxparameter_income").html(dropdownsData);
4903
- } else {
4904
- $(".${subname}_" + key).eq(index).val(myobj[key] ? myobj[key] : '');
4905
- }
4906
- }
4907
-
4903
+ for(var key in myobj){
4904
+ const $el = $(".${subname}_" + key).eq(index);
4905
+ let v = myobj[key];
4906
+ if (
4907
+ v === undefined ||
4908
+ v === null ||
4909
+ (typeof v === "string" && (v.trim().toLowerCase() === "undefined" || v.trim().toLowerCase() === "null"))
4910
+ ) {
4911
+ v = "";
4912
+ }
4913
+ const setInputValue = (val) => {
4914
+ const next = val ?? "";
4915
+ $el.val(next);
4916
+ if (next === "") {
4917
+ $el.removeAttr("value");
4918
+ $el.removeAttr("data-t");
4919
+ } else {
4920
+ $el.attr("value", next);
4921
+ $el.attr("data-t", next);
4922
+ }
4923
+ };
4924
+
4925
+ if ($el.attr("type") == "checkbox") {
4926
+ const checked = v == 1 || v === true || v === "1" || v === "true";
4927
+ $el.prop("checked", checked);
4928
+ setInputValue(checked ? 1 : "");
4929
+ } else if ($(".${subname}_" + key).eq(index).attr("type") == "file") {
4930
+ var myimg = v ? v : '';
4931
+ var pathName = "/uploads/${MYMODEL.table}/${keys}/";
4932
+ if (myimg) {
4933
+ var filename = filenamex = pathName + myimg;
4934
+ if (!myimg.match(/\\.(jpg|jpeg|png|gif|svg|jiff|avif)$/i)) {
4935
+ filename = "/img/file.png";
4936
+ }
4937
+ $(".${subname}_" + key).eq(index).closest("TD").find("img").attr("src", filename).addClass("boxy");
4938
+ $(".${subname}_" + key).eq(index).closest("TD").append('<a href="' + filenamex + '" target="_blank" style="font-size: 12px">' + myimg + '</a>');
4939
+ }
4940
+ } else if ($(".${subname}_" + key).eq(index).hasClass("dropdown-multi")) {
4941
+ var dropdownsData = '';
4942
+ var mydropdowns = myobj[key] || [];
4943
+ mydropdowns.map((item, i) => {
4944
+ var text = ${dropdownMultis[0]}Object[item];
4945
+ dropdownsData += "<span class='span"+key+"' > "+(i+1)+". <input type='hidden' name='${MYMODEL.table}[${keys}]["+index+"]["+key+"]["+i+"]' value='"+item+"' /> " + text +" <img class='tabler-icons icons-filter-danger pull-right' src='/assets/icons/trash-filled.svg' onclick='$(this).closest(\`span\`).remove();' title='Delete' /> <br></span>";
4946
+ });
4947
+ $(".${subname}_" + key).eq(index).closest("TD").find("#dropdownboxparameter_income").html(dropdownsData);
4948
+ } else {
4949
+ setInputValue(v);
4908
4950
  }
4951
+
4952
+ }
4953
+ }
4909
4954
  `;
4910
4955
 
4911
4956
  scriptForm += `function build${keys}form(index, myobj) {
4912
4957
  append${keys}(index, (data) => {
4913
4958
  $("#body-${keys}").append(data);
4914
4959
  ${keys}Handler();
4960
+ sanitizeUndefinedAttributes($("#body-${keys}"));
4915
4961
  setTimeout(function () {
4916
4962
  set${keys}value(index,myobj);
4963
+ sanitizeUndefinedAttributes($("#body-${keys}"));
4917
4964
  },500);
4918
4965
  append${keys}Max = index + 1;
4919
4966
  });
4920
4967
  }
4921
4968
  `;
4922
4969
 
4970
+ scriptForm += `$(function () {sanitizeUndefinedAttributes($("#body-${keys}"));});`
4971
+
4923
4972
  break;
4924
4973
 
4925
4974
  case "ide_editor":
@@ -6621,4 +6670,4 @@ zRoute.tableBody = (
6621
6670
  }
6622
6671
  return html;
6623
6672
  };
6624
- module.exports = zRoute;
6673
+ module.exports = zRoute;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zet-lib",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "zet is a library that part of zet generator.",
5
5
  "engines": {
6
6
  "node": ">=18"
@@ -29,7 +29,6 @@
29
29
  "sideEffects": false,
30
30
  "dependencies": {
31
31
  "axios": "^1.15.0",
32
- "convert-excel-to-json": "^1.7.0",
33
32
  "dotenv": "^16.5.0",
34
33
  "dropbox": "^10.34.0",
35
34
  "ejs": "^3.1.10",
@@ -50,13 +49,14 @@
50
49
  "read-excel-file": "^5.8.0",
51
50
  "socket.io": "^4.8.3",
52
51
  "uglify-js": "^3.19.3",
53
- "uuid": "^9.0.1",
54
- "xlsx": "^0.18.5"
52
+ "uuid": "^9.0.1"
55
53
  },
56
54
  "optionalDependencies": {
57
- "pm2": "^6.0.0",
58
55
  "sharp": "^0.34.1"
59
56
  },
57
+ "devDependencies": {
58
+ "standard": "^17.1.2"
59
+ },
60
60
  "overrides": {
61
61
  "unzipper": "^0.12.3",
62
62
  "rimraf": "^6.1.2",