zet-lib 1.2.58 → 1.2.59

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 CHANGED
@@ -868,7 +868,7 @@ Form.modal = (obj, LANGUAGE = {}) => {
868
868
  <div class="modal-dialog">
869
869
  <div class="modal-content">
870
870
  <div class="modal-header">
871
- <h1 class="modal-title fs-5" id="exampleModalLabel">Lock/Unlock</h1>
871
+ <h1 class="modal-title fs-5">Lock/Unlock</h1>
872
872
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
873
873
  </div>
874
874
  <div class="modal-body">
@@ -877,9 +877,21 @@ Form.modal = (obj, LANGUAGE = {}) => {
877
877
  </div>
878
878
  </div>
879
879
  </div>
880
+ </div>`
881
+ let modalFields3 = `
882
+ <div class="modal fade" id="grid-approval" tabindex="-1" aria-labelledby="grid-approval-label" aria-hidden="true">
883
+ <div class="modal-dialog">
884
+ <div class="modal-content">
885
+ <div class="modal-header">
886
+ <h1 class="modal-title fs-5" >Approvals</h1>
887
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
888
+ </div>
889
+ <div class="modal-body" style="height: 140px"><div class="row"><div class="col-md-11 modal-body-approval"></div></div></div>
890
+ </div>
891
+ </div>
880
892
  </div>`
881
893
  try {
882
- return modalFields + modalFields2
894
+ return modalFields + modalFields2 + modalFields3
883
895
  } catch (err) {
884
896
  console.log(err)
885
897
  }
package/lib/zAppRouter.js CHANGED
@@ -1298,7 +1298,7 @@ router.get('/zdownload/zgenerator/:table', async (req, res) => {
1298
1298
 
1299
1299
  router.post('/zlock-unlock/:table', async (req, res) => {
1300
1300
  let json = Util.jsonSuccess('Success')
1301
- var table = req.params.table
1301
+ let table = req.params.table
1302
1302
  let cacheRoles = myCache.get('ROLES')
1303
1303
  let roleId = res.locals.roleId
1304
1304
  let myrole = cacheRoles[roleId]
@@ -1330,6 +1330,67 @@ router.post('/zlock-unlock/:table', async (req, res) => {
1330
1330
  res.json(json)
1331
1331
  })
1332
1332
 
1333
+ router.post('/zapproval-update/:table', async (req, res) => {
1334
+ let json = Util.jsonSuccess('Success')
1335
+ let table = req.params.table
1336
+ let value = req.body.value
1337
+ let datas = req.body.datas || []
1338
+ console.log(datas)
1339
+ let myaccess = res.locals.zuser.level_approval || []
1340
+ let hasAccess = myaccess.includes(value) ? true : false
1341
+ let canUpdate = true
1342
+ let dataStatus = []
1343
+ if (hasAccess) {
1344
+ if (datas.length > 0) {
1345
+ for (const data of datas) {
1346
+ let id = data.name.replace('ck[', '').replace(']', '')
1347
+ let result = await connection.result({
1348
+ select: 'id,approval_status,approval_history',
1349
+ table: table,
1350
+ where: {
1351
+ id: id,
1352
+ },
1353
+ })
1354
+ let approval_history = result.approval_history || []
1355
+ if (approval_history.length > 0) {
1356
+ let lastStatus = +approval_history[approval_history.length - 1].status
1357
+ canUpdate = lastStatus > +value ? false : true
1358
+ let history = approval_history.filter((item) => item.status == value && item.user_id == res.locals.userId)
1359
+ if (history.length > 0) {
1360
+ canUpdate = false
1361
+ }
1362
+ }
1363
+ if (canUpdate) {
1364
+ approval_history.push({
1365
+ status: value,
1366
+ user_id: res.locals.userId,
1367
+ created_at: Util.now(),
1368
+ })
1369
+ let mydata = {
1370
+ approval_status: value,
1371
+ approval_history: Util.array_to_jsonb(approval_history),
1372
+ }
1373
+ await connection.update({
1374
+ table: table,
1375
+ where: {
1376
+ id: id,
1377
+ },
1378
+ data: mydata,
1379
+ })
1380
+ } else {
1381
+ dataStatus.push(`${id} -> Status has been delivered`)
1382
+ }
1383
+ }
1384
+ } else {
1385
+ json = Util.flashError('No Data')
1386
+ }
1387
+ } else {
1388
+ json = Util.flashError('No Access')
1389
+ }
1390
+ json.dataStatus = dataStatus
1391
+ res.json(json)
1392
+ })
1393
+
1333
1394
  router.get('/addlock-fields', async (req, res) => {
1334
1395
  let tables = await connection.query(connection.showTables)
1335
1396
  for (const table of tables) {
@@ -1374,4 +1435,56 @@ router.get('/addlock-models', async (req, res) => {
1374
1435
  res.send(text)
1375
1436
  })
1376
1437
 
1438
+ router.get('/addapprovals-data', async (req, res) => {
1439
+ let tables = await connection.query(connection.showTables)
1440
+ for (const table of tables) {
1441
+ let tablename = table.tablename
1442
+ let sql = `ALTER TABLE ${tablename} ADD COLUMN "approval_status" smallint DEFAULT NULL`
1443
+ let sql2 = `ALTER TABLE ${tablename} ADD COLUMN "approval_history" jsonb[] DEFAULT NULL `
1444
+ try {
1445
+ await connection.query(sql)
1446
+ } catch (e) {
1447
+ console.log(e)
1448
+ }
1449
+ try {
1450
+ await connection.query(sql2)
1451
+ } catch (e) {
1452
+ console.log(e)
1453
+ }
1454
+ }
1455
+ res.send(tables)
1456
+ })
1457
+
1458
+ router.get('/addapproval-models', async (req, res) => {
1459
+ let text = ''
1460
+ let results = await connection.results({
1461
+ table: 'zfields',
1462
+ })
1463
+ for (const result of results) {
1464
+ let labels = result.labels
1465
+ let arr = Object.keys(labels)
1466
+ if (!Util.in_array('approval_status', arr)) {
1467
+ text += result.id + ' tidak ada'
1468
+ //approval_status_id : "Approval Status",
1469
+ labels.approval_status = 'Approval Status'
1470
+ labels.approval_history = 'Approval History'
1471
+ try {
1472
+ await connection.update({
1473
+ table: 'zfields',
1474
+ data: {
1475
+ labels: JSON.stringify(labels),
1476
+ },
1477
+ where: {
1478
+ id: result.id,
1479
+ },
1480
+ })
1481
+ } catch (err) {
1482
+ console.log(err)
1483
+ }
1484
+ }
1485
+ }
1486
+
1487
+ res.send(text)
1488
+ })
1489
+
1377
1490
  module.exports = router
package/lib/zCache.js CHANGED
@@ -19,6 +19,7 @@ zCache.KEYS = {
19
19
  ZFUNCTIONS: 'ZFUNCTIONS',
20
20
  VERSIONS: 'VERSIONS',
21
21
  MODELS_RELATIONS: 'MODELS_RELATIONS',
22
+ APPROVAL_LEVELS : 'APPROVAL_LEVELS'
22
23
  }
23
24
 
24
25
  zCache.STATICS = zCache.KEYS
@@ -85,6 +86,11 @@ const cache = async () => {
85
86
  } else {
86
87
  await zCache.ZFUNCTIONS()
87
88
  }
89
+ if (myCache.has('APPROVAL_LEVELS')) {
90
+ //i = i + 1;
91
+ } else {
92
+ await zCache.APPROVAL_LEVELS()
93
+ }
88
94
  //await zCache.CURRENCIES();
89
95
  //console.log(i)
90
96
  if (i < 5) {
@@ -105,6 +111,7 @@ zCache.renew = async () => {
105
111
  await zCache.MYMODELS()
106
112
  await zCache.MENU_SYSTEMS()
107
113
  await zCache.MODELS_RELATIONS()
114
+ await zCache.APPROVAL_LEVELS()
108
115
  }
109
116
 
110
117
  zCache.ROUTES = () => {
@@ -233,14 +240,14 @@ zCache.MENU_SYSTEMS = () => {
233
240
  text: 'LANGUAGE.users',
234
241
  href: 'zuser',
235
242
  },
236
- {
237
- text: 'LANGUAGE.company',
238
- href: 'zcompany',
239
- },
240
243
  {
241
244
  text: 'LANGUAGE.user_access',
242
245
  href: 'zuser_company',
243
246
  },
247
+ {
248
+ text: 'LANGUAGE.company',
249
+ href: 'zcompany',
250
+ },
244
251
  {
245
252
  text: 'LANGUAGE.access_role',
246
253
  href: 'zrole',
@@ -315,4 +322,18 @@ zCache.MODELS_RELATIONS = async () => {
315
322
  }
316
323
  }
317
324
 
325
+ zCache.APPROVAL_LEVELS = async() => {
326
+ if (myCache.has('APPROVAL_LEVELS')) {
327
+ return myCache.get('APPROVAL_LEVELS')
328
+ } else {
329
+ let results = await connection.results({
330
+ select:'id,name,color',
331
+ table:'zapproval_type'
332
+ })
333
+ let obj = Util.arrayToObject(results,"id");
334
+ myCache.set('APPROVAL_LEVELS', obj)
335
+ return obj
336
+ }
337
+ }
338
+
318
339
  module.exports = zCache
package/lib/zRoute.js CHANGED
@@ -868,6 +868,19 @@ zRoute.dataTableFilter = (MYMODEL, relations, filter) => {
868
868
  return dataTable
869
869
  }
870
870
 
871
+ zRoute.approval_history_data = (arr = []) => {
872
+ let myvalue = ''
873
+ let APPROVAL_LEVELS = myCache.get('APPROVAL_LEVELS')
874
+ let USERS = Util.arrayToObject(myCache.get('zuser_created_by_1'), 'id')
875
+ myvalue = ''
876
+ if (arr && arr.length > 0) {
877
+ arr.map((item) => {
878
+ myvalue += `[${APPROVAL_LEVELS[item.status].name} By:${USERS[item.user_id].zname}(${item.created_at})] `
879
+ })
880
+ }
881
+ return myvalue
882
+ }
883
+
871
884
  zRoute.dataTableData = (key, value, MYMODEL, relations, myid = '') => {
872
885
  relations = relations || {}
873
886
  var keyFields = key + 'Fields'
@@ -876,6 +889,8 @@ zRoute.dataTableData = (key, value, MYMODEL, relations, myid = '') => {
876
889
  var widgetName = MYMODEL.widgets[key] ? MYMODEL.widgets[key].name : ''
877
890
  if (key == 'lock') {
878
891
  myvalue = value == 1 ? 'Lock' : 'Unlock'
892
+ } else if (key == 'approval_history') {
893
+ myvalue = zRoute.approval_history_data(myvalue)
879
894
  } else {
880
895
  if (widgetName) {
881
896
  switch (widgetName) {
@@ -2509,6 +2524,21 @@ zRoute.viewFormsSync = async (req, res, MYMODEL, data = {}) => {
2509
2524
  }
2510
2525
  forms.build[key] = cForm.build(forms.obj[key])
2511
2526
  }
2527
+
2528
+ let approval_history_table = ``
2529
+ if (data.approval_status != null) {
2530
+ let APPROVAL_LEVELS = myCache.get('APPROVAL_LEVELS')
2531
+ let USERS = Util.arrayToObject(myCache.get('zuser_created_by_1'), 'id')
2532
+ approval_history_table += `<div class="dropdown"><button class="btn boxy dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Approval Status : ${APPROVAL_LEVELS[data.approval_status].name}</button>`
2533
+ approval_history_table += `<ul class="dropdown-menu" aria-labelledby="viewApproval">`
2534
+ let arr = data.approval_history || []
2535
+ arr.map((item, index) => {
2536
+ approval_history_table += `<li><a class="dropdown-item" href="#">${index + 1}. ${APPROVAL_LEVELS[item.status].name} ${USERS[item.user_id].zname} ${Util.timeSql(data.created_at)}</a></li>`
2537
+ })
2538
+ approval_history_table += `</ul></div>`
2539
+ }
2540
+
2541
+ forms.approval_history_table = approval_history_table
2512
2542
  return forms
2513
2543
  }
2514
2544
 
package/lib/zdataTable.js CHANGED
@@ -2,10 +2,11 @@
2
2
  * Created by sintret dev on 1/6/2022.
3
3
  */
4
4
  const Util = require('./Util')
5
+ const myCache = require('./cache')
5
6
 
6
7
  class dataTable {
7
- constructor(visibles) {
8
- this.visibles = visibles //array object
8
+ constructor(datas) {
9
+ this.visibles = datas.visiblesObj //array object
9
10
  this.setColumns = ''
10
11
  this.setTable = ''
11
12
  this.srcScript = '/modules/datatables.min.js'
@@ -18,7 +19,8 @@ class dataTable {
18
19
  this.routeName
19
20
  this.types = {}
20
21
  this.levels = {}
21
- this.visiblesKey = visibles.map((item) => item.key)
22
+ this.level_approval = datas.zuser && datas.zuser.level_approval ? datas.zuser.level_approval : []
23
+ this.visiblesKey = this.visibles.map((item) => item.key)
22
24
  }
23
25
 
24
26
  // for filter html
@@ -92,6 +94,9 @@ class dataTable {
92
94
  if (this.levels.lock) {
93
95
  html += `<button title="Lock/Unlock" style="background-color: #3B71CA; color:white" class="btn btn-danger buttons-lock buttons-html5 copy gridlock boxy-small dimens2x image-button" tabindex="0" style="color: " type="button"><img src="/assets/icons/cloud-lock.svg" class="icons-bg-white"> Lock/Unlock</span></span></button>`
94
96
  }
97
+ if (this.level_approval && this.level_approval.length) {
98
+ html += `<button title="Approval" style="background-color: #3B71CA; color:white" class="btn buttons-html5 boxy-small dimens2x image-button" data-bs-toggle="modal" data-bs-target="#grid-approval" type="button"><img src="/assets/icons/rubber-stamp.svg" class="icons-bg-white"> Approval</span></span></button>`
99
+ }
95
100
  html += `<button title="${LANGUAGE.settings}" class="btn buttons-excel buttons-html5 setting gridsettings boxy-small dimens2x image-button" tabindex="0" aria-controls="DataTables_Table_0" type="button" data-bs-toggle="modal" data-bs-target="#grid-modal"><img src="/assets/icons/settings.svg" class="icons-bg-black"> ${LANGUAGE.settings}</button>`
96
101
  html += `<button class="btn refresh gridreload boxy-small dimens2x image-button" title="${LANGUAGE.grid_refresh}" tabindex="0" aria-controls="DataTables_Table_0" type="button"><img src="/assets/icons/refresh.svg" class="icons-bg-black"></button>`
97
102
  if (this.levels.export) {
@@ -120,13 +125,16 @@ class dataTable {
120
125
  html += `<button title="${LANGUAGE.create_info}" class="btn create gridadd image-button boxy-small dimens2x" tabindex="0" aria-controls="DataTables_Table_0" type="button"><img src="/assets/icons/plus.svg" class="icons-bg-black"> ${LANGUAGE.create}</button>`
121
126
  }
122
127
  if (this.levels.import) {
123
- html += `<button title="${LANGUAGE.import_info}" class="btn buttons-copy buttons-html5 copy gridimport boxy-small dimens2x image-button" tabindex="0" type="button"><img src="/assets/icons/database-import.svg" class="icons-bg-black"> ${LANGUAGE.import}</span></span></button>`
128
+ html += `<button title="${LANGUAGE.import_info}" class="btn buttons-copy buttons-html5 copy gridimport boxy-small dimens2x image-button" type="button"><img src="/assets/icons/database-import.svg" class="icons-bg-black"> ${LANGUAGE.import}</span></span></button>`
124
129
  }
125
130
  if (this.levels.lock) {
126
- html += `<button title="Lock/Unlock" style="background-color: #332D2D; color:white" class="btn btn-danger buttons-lock buttons-html5 copy gridlock boxy-small dimens2x image-button" tabindex="0" data-bs-toggle="modal" data-bs-target="#grid-lock" type="button"><img src="/assets/icons/cloud-lock.svg" class="icons-bg-white"> Lock/Unlock</span></span></button>`
131
+ html += `<button title="Lock/Unlock" style="background-color: #332D2D; color:white" class="btn btn-danger buttons-lock buttons-html5 copy gridlock boxy-small dimens2x image-button" data-bs-toggle="modal" data-bs-target="#grid-lock" type="button"><img src="/assets/icons/cloud-lock.svg" class="icons-bg-white"> Lock/Unlock</span></span></button>`
127
132
  }
128
- html += `<button title="${LANGUAGE.settings}" class="btn buttons-excel buttons-html5 setting gridsettings boxy-small dimens2x image-button" tabindex="0" type="button" data-bs-toggle="modal" data-bs-target="#grid-modal"><img src="/assets/icons/settings.svg" class="icons-bg-black"> ${LANGUAGE.settings}</button>`
129
- html += `<button class="btn refresh gridreload boxy-small dimens2x image-button" title="${LANGUAGE.grid_refresh}" tabindex="0" aria-controls="DataTables_Table_0" type="button"><img src="/assets/icons/refresh.svg" class="icons-bg-black"></button>`
133
+ if (this.level_approval && this.level_approval.length) {
134
+ html += `<button title="Approval" style="background-color: #E4A11B; color:white" class="btn buttons-html5 boxy-small dimens2x image-button" data-bs-toggle="modal" data-bs-target="#grid-approval" type="button"><img src="/assets/icons/rubber-stamp.svg" class="icons-bg-white"> Approval</span></span></button>`
135
+ }
136
+ html += `<button title="${LANGUAGE.settings}" class="btn buttons-excel buttons-html5 setting gridsettings boxy-small dimens2x image-button" type="button" data-bs-toggle="modal" data-bs-target="#grid-modal"><img src="/assets/icons/settings.svg" class="icons-bg-black"> ${LANGUAGE.settings}</button>`
137
+ html += `<button class="btn refresh gridreload boxy-small dimens2x image-button" title="${LANGUAGE.grid_refresh}" aria-controls="DataTables_Table_0" type="button"><img src="/assets/icons/refresh.svg" class="icons-bg-black"></button>`
130
138
  if (this.levels.export) {
131
139
  html += `<div class="btn-group" role="group">
132
140
  <button id="dropdownExport" type="button" class="btn dropdown-toggle boxy-small dimens2x image-button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
@@ -182,6 +190,49 @@ class dataTable {
182
190
  if (typeaheadScript) {
183
191
  script += `<script type="text/javascript">$(function () {${typeaheadScript}})</script>${Util.newLine}`
184
192
  }
193
+ if (this.level_approval && this.level_approval.length) {
194
+ //modal-body-approval
195
+ let APPROVAL_LEVELS = myCache.get('APPROVAL_LEVELS')
196
+ let approvalButtonHtml = ``
197
+ this.level_approval.map((item) => {
198
+ let imageapproval = 'brand-bunpo'
199
+ if (item == 12) {
200
+ imageapproval = 'rubber-stamp-off'
201
+ } else if (item == 0) {
202
+ imageapproval = 'list-check'
203
+ } else if (item == 11) {
204
+ imageapproval = 'rubber-stamp'
205
+ }
206
+ approvalButtonHtml += ` <button title="${APPROVAL_LEVELS[item].name}" data-value="${item}" style="background-color: ${APPROVAL_LEVELS[item].color}; color:white" class="btn btn-approval-levels boxy-small dimens2x image-button" type="button"><img src="/assets/icons/${imageapproval}.svg" class="icons-bg-white"> ${APPROVAL_LEVELS[item].name}</button> `
207
+ })
208
+ script += `<script type="text/javascript">$(function () {
209
+ $(".modal-body-approval").html('${approvalButtonHtml}');
210
+ $(".btn-approval-levels").on("click", function () {
211
+ ajaxPost('/zapproval-update/${this.MYMODEL.table}', {
212
+ value : $(this).attr('data-value'),
213
+ datas: $(".ck").serializeArray()
214
+ }, function (data) {
215
+ toastrForm(data);
216
+ if(data.dataStatus.length > 0) {
217
+ data.dataStatus.map((item) => {
218
+ toastr.error(item);
219
+ });
220
+ setTimeout(function() {
221
+ if(data.status ==1) {
222
+ location.href='';
223
+ }
224
+ },4000);
225
+ } else {
226
+ if(data.status ==1) {
227
+ location.href='';
228
+ }
229
+ }
230
+
231
+ })
232
+ })
233
+ })</script>${Util.newLine}`
234
+ }
235
+
185
236
  script += `<script type="text/javascript">
186
237
  $(function () {
187
238
  $("#ck_all").on('click', function () {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zet-lib",
3
- "version": "1.2.58",
3
+ "version": "1.2.59",
4
4
  "description": "zet is a library that part of zet generator.",
5
5
  "engines": {
6
6
  "node": ">=18"