zet-lib 1.2.59 → 1.2.60

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
@@ -762,7 +762,7 @@ Form.build = (obj) => {
762
762
  let view_only = Object.prototype.hasOwnProperty.call(obj, 'view_only') ? obj.view_only : false
763
763
  if (!view_only) {
764
764
  if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'name')) {
765
- if (obj.attributes.name == 'relation') {
765
+ if (obj.attributes.name == 'relation' || obj.attributes.name == 'typeahead' || obj.attributes.name == 'dropdown_multi') {
766
766
  relation = `<a target="_blank" href="/${obj.attributes.table}"> > </a>`
767
767
  }
768
768
  }
@@ -886,7 +886,9 @@ Form.modal = (obj, LANGUAGE = {}) => {
886
886
  <h1 class="modal-title fs-5" >Approvals</h1>
887
887
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
888
888
  </div>
889
- <div class="modal-body" style="height: 140px"><div class="row"><div class="col-md-11 modal-body-approval"></div></div></div>
889
+ <div class="modal-body" style="min-height: 150px">
890
+ <div class="row"><div class="col-md-12 modal-body-approval"></div></div>
891
+ </div>
890
892
  </div>
891
893
  </div>
892
894
  </div>`
package/lib/zAppRouter.js CHANGED
@@ -1334,12 +1334,17 @@ router.post('/zapproval-update/:table', async (req, res) => {
1334
1334
  let json = Util.jsonSuccess('Success')
1335
1335
  let table = req.params.table
1336
1336
  let value = req.body.value
1337
+ let text = req.body.text
1337
1338
  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
1339
+ let roles = myCache.get('ROLES')[res.locals.roleId] || {}
1340
+ let myaccess = roles.approvals[table]
1341
+ let hasAccess = myaccess.hasOwnProperty(value) ? true : false
1341
1342
  let canUpdate = true
1342
1343
  let dataStatus = []
1344
+ if (text == '') {
1345
+ res.json(Util.flashError('please type a message'))
1346
+ return false
1347
+ }
1343
1348
  if (hasAccess) {
1344
1349
  if (datas.length > 0) {
1345
1350
  for (const data of datas) {
@@ -1351,20 +1356,33 @@ router.post('/zapproval-update/:table', async (req, res) => {
1351
1356
  id: id,
1352
1357
  },
1353
1358
  })
1359
+ let approval_status = result.approval_status || null
1354
1360
  let approval_history = result.approval_history || []
1355
- if (approval_history.length > 0) {
1361
+ if (approval_status == null) {
1362
+ canUpdate = true
1363
+ } else if (approval_status == 12) {
1364
+ canUpdate = true
1365
+ } else {
1366
+ if (+value > +approval_status) {
1367
+ canUpdate = true
1368
+ } else {
1369
+ canUpdate = false
1370
+ }
1371
+ }
1372
+ /*if (approval_history.length > 0) {
1356
1373
  let lastStatus = +approval_history[approval_history.length - 1].status
1357
1374
  canUpdate = lastStatus > +value ? false : true
1358
1375
  let history = approval_history.filter((item) => item.status == value && item.user_id == res.locals.userId)
1359
1376
  if (history.length > 0) {
1360
1377
  canUpdate = false
1361
1378
  }
1362
- }
1379
+ }*/
1363
1380
  if (canUpdate) {
1364
1381
  approval_history.push({
1365
1382
  status: value,
1366
1383
  user_id: res.locals.userId,
1367
1384
  created_at: Util.now(),
1385
+ text: text,
1368
1386
  })
1369
1387
  let mydata = {
1370
1388
  approval_status: value,
@@ -185,6 +185,44 @@ router.post('/tab-access', async (req, res) => {
185
185
  res.send(html)
186
186
  })
187
187
 
188
+ router.post('/approval-access', async (req, res) => {
189
+ let json = Util.jsonSuccess()
190
+ let html = ''
191
+ const checkedFn = (obj, name) => {
192
+ return obj.hasOwnProperty(name) && obj[name] ? 'checked' : ''
193
+ }
194
+ try {
195
+ const table = req.body.table
196
+ const id = req.body.id
197
+ let tabRole = await connection.result({
198
+ table: 'zrole',
199
+ where: {
200
+ id: id,
201
+ },
202
+ })
203
+ let myapprovals = tabRole.approvals || {}
204
+ let myapprovalsRole = myapprovals[table] || {}
205
+ let results = await connection.results({
206
+ table: 'zapproval_type',
207
+ order_by: ['id asc'],
208
+ })
209
+ html += `<form id="approvalform">`
210
+ html += `<table class="table table-hover"><thead><tr><th>Name </th><th>Level <input type="checkbox" onclick="tabApprovals(this)" id="checkapprovals" /></th></tr></thead><tbody></tbody>`
211
+ results.map((item) => {
212
+ html += `<tr>
213
+ <td>${item.name}</td>
214
+ <td><input type="checkbox" class="checkapproval" name="approval_${item.id}" ${checkedFn(myapprovalsRole, item.id)} /></td>
215
+
216
+ </tr>`
217
+ })
218
+ html += `</tbody></table>`
219
+ html += `</form>`
220
+ } catch (e) {
221
+ json = Util.flashError(e.toString())
222
+ }
223
+ res.send(html)
224
+ })
225
+
188
226
  router.post('/post-access', async (req, res) => {
189
227
  let json = Util.jsonSuccess()
190
228
  let table = req.body.table || ''
@@ -239,6 +277,50 @@ router.post('/post-access', async (req, res) => {
239
277
  res.json(json)
240
278
  })
241
279
 
280
+ router.post('/post-approval', async (req, res) => {
281
+ let json = Util.jsonSuccess()
282
+ let table = req.body.table || ''
283
+ if (table == '') {
284
+ res.json(Util.flashError('Table is empty!'))
285
+ return false
286
+ }
287
+ let datas = req.body.datas || []
288
+ console.log(datas)
289
+ let id = req.body.id
290
+ if (datas.length == 0) {
291
+ res.json(Util.flashError('Data is empty!'))
292
+ return false
293
+ }
294
+ let myapprovals = {}
295
+ try {
296
+ let result = await connection.result({
297
+ table: 'zrole',
298
+ where: {
299
+ id: id,
300
+ },
301
+ })
302
+ myapprovals = result.approvals || {}
303
+ let obj = {}
304
+ datas.map((item) => {
305
+ let id = item.name.replace('approval_', '')
306
+ obj[id] = true
307
+ })
308
+ myapprovals[table] = obj
309
+ await connection.update({
310
+ table: 'zrole',
311
+ data: {
312
+ approvals: JSON.stringify(myapprovals),
313
+ },
314
+ where: {
315
+ id: id,
316
+ },
317
+ })
318
+ } catch (err) {
319
+ json = Util.jsonError(err + '')
320
+ }
321
+ res.json(json)
322
+ })
323
+
242
324
  router.delete('/delete/:id', async (req, res) => {
243
325
  let json = Util.jsonSuccess()
244
326
  let id = parseInt(req.params.id)
@@ -300,6 +382,7 @@ const body = `<div class="">
300
382
  <% for(var i = 0;i < actions.length;i++) { %>
301
383
  <th><%= actions[i] %> <input onclick='checkthis("<%= actions[i] %>")' type="checkbox" id="all<%= actions[i] %>"></th>
302
384
  <% } %>
385
+ <th>Approve Level</th>
303
386
  <th>Tabs</th>
304
387
  </tr>
305
388
  </thead>
@@ -308,8 +391,10 @@ const body = `<div class="">
308
391
  <tr>
309
392
  <td>
310
393
  <% var ename = routes[i];
311
- var handleTag = "handleAccess('"+routes[i]+"')";
312
- var spanRole = tabs.includes(routes[i]) ? '<span class="handle-access icon-small icons-light" onclick="'+handleTag+'" data-bs-toggle="modal" data-bs-target="#tabaccess" ><img class="icons-bg-blue gridview icon-image" src="/assets/icons/lock-access.svg"></span>' : '' %>
394
+ const handleTag = "handleAccess('"+routes[i]+"')";
395
+ const handleApproval = "handleApproval('"+routes[i]+"')";
396
+ const spanApproval = '<span class="handle-access icon-small icons-light" onclick="'+handleApproval+'" data-bs-toggle="modal" data-bs-target="#modalapproval" ><img class="icons-bg-blue gridview icon-image" src="/assets/icons/lock-access.svg"></span>';
397
+ const spanRole = tabs.includes(routes[i]) ? '<span class="handle-access icon-small icons-light" onclick="'+handleTag+'" data-bs-toggle="modal" data-bs-target="#tabaccess" ><img class="icons-bg-blue gridview icon-image" src="/assets/icons/lock-access.svg"></span>' : '' %>
313
398
  <a href="/<%- ename %>" target="_blank"><%- ename %></a>
314
399
  </td>
315
400
  <% for(var x = 0;x < actions.length;x++) { %>
@@ -317,6 +402,7 @@ const body = `<div class="">
317
402
  <% if(json && json.hasOwnProperty(ename) && json[ename].indexOf(actions[x]) >= 0) { %> <%= 'checked="checked"' %> <% } %> title="Role for <%= routes[i] %> <%= actions[x] %>" type="checkbox">
318
403
  </td>
319
404
  <% } %>
405
+ <td><%- spanApproval %></td>
320
406
  <td><%- spanRole %></td>
321
407
  </tr>
322
408
  <% } %>
@@ -376,9 +462,7 @@ const body = `<div class="">
376
462
  <div class="modal-header"><h5 class="modal-title" id="tabaccesstitle">Tab Access <span id="titleaccess"></span></h5>
377
463
  <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
378
464
  </div>
379
- <div class="modal-body body-access">
380
-
381
- </div>
465
+ <div class="modal-body body-access"></div>
382
466
  <div class="modal-footer">
383
467
  <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
384
468
  <button type="button" class="btn btn-primary btn-save-tab">Save changes</button>
@@ -386,6 +470,20 @@ const body = `<div class="">
386
470
  </div>
387
471
  </div>
388
472
  </div>
473
+ <div class="modal fade" id="modalapproval" tabindex="-1" aria-labelledby="tabapprovalModalLabel" aria-hidden="true">
474
+ <div class="modal-dialog">
475
+ <div class="modal-content">
476
+ <div class="modal-header"><h5 class="modal-title">Approval Level <span id="approvalname"></span> </h5>
477
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
478
+ </div>
479
+ <div class="modal-body body-approval"></div>
480
+ <div class="modal-footer">
481
+ <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
482
+ <button type="button" class="btn btn-primary btn-save-approval">Save changes</button>
483
+ </div>
484
+ </div>
485
+ </div>
486
+ </div>
389
487
 
390
488
 
391
489
  `
@@ -405,6 +503,14 @@ const js = `<script>
405
503
  $("input." + elm).prop("checked", false);
406
504
  }
407
505
  }
506
+ function tabApprovals(that) {
507
+ let elm = 'checkapproval';
508
+ if ($(that).is(":checked")) {
509
+ $("input." + elm).prop("checked", true);
510
+ } else {
511
+ $("input." + elm).prop("checked", false);
512
+ }
513
+ }
408
514
  $("#roleName").on('change', function () {
409
515
  location.href = "/zrole?id=" + $(this).val();
410
516
  });
@@ -452,7 +558,13 @@ const js = `<script>
452
558
  })
453
559
  }
454
560
  }
455
-
561
+ function handleApproval(table) {
562
+ $(".btn-save-approval").attr("data-table", table);
563
+ $("#approvalname").html(table);
564
+ ajaxPost('/zrole/approval-access',{table:table, id: "<%- id %>"}, ((data) => {
565
+ $(".body-approval").html(data);
566
+ }))
567
+ }
456
568
  function handleAccess(table) {
457
569
  $(".btn-save-tab").attr("data-table", table);
458
570
  ajaxPost('/zrole/tab-access',{table:table, id: "<%- id %>"}, ((data) => {
@@ -471,6 +583,18 @@ const js = `<script>
471
583
  $(".btn-close").click();
472
584
  }))
473
585
  })
586
+
587
+ $(".btn-save-approval").on("click",(e) => {
588
+ let queryform = $("#approvalform").serializeArray();
589
+ ajaxPost('/zrole/post-approval', {
590
+ datas: queryform,
591
+ id: "<%- id %>",
592
+ table : e.target.getAttribute('data-table')
593
+ },((data) => {
594
+ toastrForm(data);
595
+ $(".btn-close").click();
596
+ }))
597
+ })
474
598
  </script>
475
599
  `
476
600
 
package/lib/zRoute.js CHANGED
@@ -875,7 +875,7 @@ zRoute.approval_history_data = (arr = []) => {
875
875
  myvalue = ''
876
876
  if (arr && arr.length > 0) {
877
877
  arr.map((item) => {
878
- myvalue += `[${APPROVAL_LEVELS[item.status].name} By:${USERS[item.user_id].zname}(${item.created_at})] `
878
+ myvalue += `[${APPROVAL_LEVELS[item.status].name} By:${USERS[item.user_id].zname}(${item.created_at}) (${item.text})] `
879
879
  })
880
880
  }
881
881
  return myvalue
@@ -2533,7 +2533,7 @@ zRoute.viewFormsSync = async (req, res, MYMODEL, data = {}) => {
2533
2533
  approval_history_table += `<ul class="dropdown-menu" aria-labelledby="viewApproval">`
2534
2534
  let arr = data.approval_history || []
2535
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>`
2536
+ approval_history_table += `<li><a class="dropdown-item" href="#">${index + 1}. ${APPROVAL_LEVELS[item.status].name} (${item.text}) ${USERS[item.user_id].zname} ${Util.timeSql(data.created_at)}</a></li>`
2537
2537
  })
2538
2538
  approval_history_table += `</ul></div>`
2539
2539
  }
package/lib/zdataTable.js CHANGED
@@ -18,8 +18,9 @@ class dataTable {
18
18
  this.relations
19
19
  this.routeName
20
20
  this.types = {}
21
- this.levels = {}
22
- this.level_approval = datas.zuser && datas.zuser.level_approval ? datas.zuser.level_approval : []
21
+ this.roles = myCache.get('ROLES')[datas.zuser.role_id] || {}
22
+ this.level_approval = this.roles.approvals && this.roles.approvals[datas.routeName] ? this.roles.approvals[datas.routeName] : {}
23
+ this.hasLevels = Object.keys(this.level_approval).length == 0 ? false : true
23
24
  this.visiblesKey = this.visibles.map((item) => item.key)
24
25
  }
25
26
 
@@ -94,7 +95,7 @@ class dataTable {
94
95
  if (this.levels.lock) {
95
96
  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>`
96
97
  }
97
- if (this.level_approval && this.level_approval.length) {
98
+ if (this.hasLevels) {
98
99
  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
100
  }
100
101
  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>`
@@ -130,7 +131,7 @@ class dataTable {
130
131
  if (this.levels.lock) {
131
132
  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>`
132
133
  }
133
- if (this.level_approval && this.level_approval.length) {
134
+ if (this.hasLevels) {
134
135
  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
  }
136
137
  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>`
@@ -190,11 +191,11 @@ class dataTable {
190
191
  if (typeaheadScript) {
191
192
  script += `<script type="text/javascript">$(function () {${typeaheadScript}})</script>${Util.newLine}`
192
193
  }
193
- if (this.level_approval && this.level_approval.length) {
194
+ if (this.hasLevels) {
194
195
  //modal-body-approval
195
196
  let APPROVAL_LEVELS = myCache.get('APPROVAL_LEVELS')
196
197
  let approvalButtonHtml = ``
197
- this.level_approval.map((item) => {
198
+ for (let item in this.level_approval) {
198
199
  let imageapproval = 'brand-bunpo'
199
200
  if (item == 12) {
200
201
  imageapproval = 'rubber-stamp-off'
@@ -203,17 +204,21 @@ class dataTable {
203
204
  } else if (item == 11) {
204
205
  imageapproval = 'rubber-stamp'
205
206
  }
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
- })
207
+ 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 mb-3" type="button"><img src="/assets/icons/${imageapproval}.svg" class="icons-bg-white"> ${APPROVAL_LEVELS[item].name}</button> `
208
+ }
209
+ approvalButtonHtml += `<div class="row"><div class="col-md-10"><textarea class="form-control boxy purple-border" id="zapproval_message" placeholder="tulis alasan..." rows="2"></textarea></div><div class="col-md-1"></div></div>`
210
+
208
211
  script += `<script type="text/javascript">$(function () {
209
212
  $(".modal-body-approval").html('${approvalButtonHtml}');
210
213
  $(".btn-approval-levels").on("click", function () {
211
214
  ajaxPost('/zapproval-update/${this.MYMODEL.table}', {
215
+ text : $("#zapproval_message").val(),
212
216
  value : $(this).attr('data-value'),
213
217
  datas: $(".ck").serializeArray()
214
218
  }, function (data) {
215
219
  toastrForm(data);
216
- if(data.dataStatus.length > 0) {
220
+ if(data.status == 1) {
221
+ if(data.dataStatus.length > 0) {
217
222
  data.dataStatus.map((item) => {
218
223
  toastr.error(item);
219
224
  });
@@ -227,7 +232,7 @@ class dataTable {
227
232
  location.href='';
228
233
  }
229
234
  }
230
-
235
+ }
231
236
  })
232
237
  })
233
238
  })</script>${Util.newLine}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zet-lib",
3
- "version": "1.2.59",
3
+ "version": "1.2.60",
4
4
  "description": "zet is a library that part of zet generator.",
5
5
  "engines": {
6
6
  "node": ">=18"