zet-lib 1.2.58 → 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
  }
@@ -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,23 @@ 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="min-height: 150px">
890
+ <div class="row"><div class="col-md-12 modal-body-approval"></div></div>
891
+ </div>
892
+ </div>
893
+ </div>
880
894
  </div>`
881
895
  try {
882
- return modalFields + modalFields2
896
+ return modalFields + modalFields2 + modalFields3
883
897
  } catch (err) {
884
898
  console.log(err)
885
899
  }
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,85 @@ 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 text = req.body.text
1338
+ let datas = req.body.datas || []
1339
+ let roles = myCache.get('ROLES')[res.locals.roleId] || {}
1340
+ let myaccess = roles.approvals[table]
1341
+ let hasAccess = myaccess.hasOwnProperty(value) ? true : false
1342
+ let canUpdate = true
1343
+ let dataStatus = []
1344
+ if (text == '') {
1345
+ res.json(Util.flashError('please type a message'))
1346
+ return false
1347
+ }
1348
+ if (hasAccess) {
1349
+ if (datas.length > 0) {
1350
+ for (const data of datas) {
1351
+ let id = data.name.replace('ck[', '').replace(']', '')
1352
+ let result = await connection.result({
1353
+ select: 'id,approval_status,approval_history',
1354
+ table: table,
1355
+ where: {
1356
+ id: id,
1357
+ },
1358
+ })
1359
+ let approval_status = result.approval_status || null
1360
+ let approval_history = result.approval_history || []
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) {
1373
+ let lastStatus = +approval_history[approval_history.length - 1].status
1374
+ canUpdate = lastStatus > +value ? false : true
1375
+ let history = approval_history.filter((item) => item.status == value && item.user_id == res.locals.userId)
1376
+ if (history.length > 0) {
1377
+ canUpdate = false
1378
+ }
1379
+ }*/
1380
+ if (canUpdate) {
1381
+ approval_history.push({
1382
+ status: value,
1383
+ user_id: res.locals.userId,
1384
+ created_at: Util.now(),
1385
+ text: text,
1386
+ })
1387
+ let mydata = {
1388
+ approval_status: value,
1389
+ approval_history: Util.array_to_jsonb(approval_history),
1390
+ }
1391
+ await connection.update({
1392
+ table: table,
1393
+ where: {
1394
+ id: id,
1395
+ },
1396
+ data: mydata,
1397
+ })
1398
+ } else {
1399
+ dataStatus.push(`${id} -> Status has been delivered`)
1400
+ }
1401
+ }
1402
+ } else {
1403
+ json = Util.flashError('No Data')
1404
+ }
1405
+ } else {
1406
+ json = Util.flashError('No Access')
1407
+ }
1408
+ json.dataStatus = dataStatus
1409
+ res.json(json)
1410
+ })
1411
+
1333
1412
  router.get('/addlock-fields', async (req, res) => {
1334
1413
  let tables = await connection.query(connection.showTables)
1335
1414
  for (const table of tables) {
@@ -1374,4 +1453,56 @@ router.get('/addlock-models', async (req, res) => {
1374
1453
  res.send(text)
1375
1454
  })
1376
1455
 
1456
+ router.get('/addapprovals-data', async (req, res) => {
1457
+ let tables = await connection.query(connection.showTables)
1458
+ for (const table of tables) {
1459
+ let tablename = table.tablename
1460
+ let sql = `ALTER TABLE ${tablename} ADD COLUMN "approval_status" smallint DEFAULT NULL`
1461
+ let sql2 = `ALTER TABLE ${tablename} ADD COLUMN "approval_history" jsonb[] DEFAULT NULL `
1462
+ try {
1463
+ await connection.query(sql)
1464
+ } catch (e) {
1465
+ console.log(e)
1466
+ }
1467
+ try {
1468
+ await connection.query(sql2)
1469
+ } catch (e) {
1470
+ console.log(e)
1471
+ }
1472
+ }
1473
+ res.send(tables)
1474
+ })
1475
+
1476
+ router.get('/addapproval-models', async (req, res) => {
1477
+ let text = ''
1478
+ let results = await connection.results({
1479
+ table: 'zfields',
1480
+ })
1481
+ for (const result of results) {
1482
+ let labels = result.labels
1483
+ let arr = Object.keys(labels)
1484
+ if (!Util.in_array('approval_status', arr)) {
1485
+ text += result.id + ' tidak ada'
1486
+ //approval_status_id : "Approval Status",
1487
+ labels.approval_status = 'Approval Status'
1488
+ labels.approval_history = 'Approval History'
1489
+ try {
1490
+ await connection.update({
1491
+ table: 'zfields',
1492
+ data: {
1493
+ labels: JSON.stringify(labels),
1494
+ },
1495
+ where: {
1496
+ id: result.id,
1497
+ },
1498
+ })
1499
+ } catch (err) {
1500
+ console.log(err)
1501
+ }
1502
+ }
1503
+ }
1504
+
1505
+ res.send(text)
1506
+ })
1507
+
1377
1508
  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
@@ -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
@@ -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}) (${item.text})] `
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} (${item.text}) ${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'
@@ -17,8 +18,10 @@ class dataTable {
17
18
  this.relations
18
19
  this.routeName
19
20
  this.types = {}
20
- this.levels = {}
21
- this.visiblesKey = visibles.map((item) => item.key)
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
24
+ this.visiblesKey = this.visibles.map((item) => item.key)
22
25
  }
23
26
 
24
27
  // for filter html
@@ -92,6 +95,9 @@ class dataTable {
92
95
  if (this.levels.lock) {
93
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>`
94
97
  }
98
+ if (this.hasLevels) {
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>`
100
+ }
95
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>`
96
102
  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
103
  if (this.levels.export) {
@@ -120,13 +126,16 @@ class dataTable {
120
126
  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
127
  }
122
128
  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>`
129
+ 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
130
  }
125
131
  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>`
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>`
127
133
  }
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>`
134
+ if (this.hasLevels) {
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>`
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>`
138
+ 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
139
  if (this.levels.export) {
131
140
  html += `<div class="btn-group" role="group">
132
141
  <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 +191,53 @@ class dataTable {
182
191
  if (typeaheadScript) {
183
192
  script += `<script type="text/javascript">$(function () {${typeaheadScript}})</script>${Util.newLine}`
184
193
  }
194
+ if (this.hasLevels) {
195
+ //modal-body-approval
196
+ let APPROVAL_LEVELS = myCache.get('APPROVAL_LEVELS')
197
+ let approvalButtonHtml = ``
198
+ for (let item in this.level_approval) {
199
+ let imageapproval = 'brand-bunpo'
200
+ if (item == 12) {
201
+ imageapproval = 'rubber-stamp-off'
202
+ } else if (item == 0) {
203
+ imageapproval = 'list-check'
204
+ } else if (item == 11) {
205
+ imageapproval = 'rubber-stamp'
206
+ }
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
+
211
+ script += `<script type="text/javascript">$(function () {
212
+ $(".modal-body-approval").html('${approvalButtonHtml}');
213
+ $(".btn-approval-levels").on("click", function () {
214
+ ajaxPost('/zapproval-update/${this.MYMODEL.table}', {
215
+ text : $("#zapproval_message").val(),
216
+ value : $(this).attr('data-value'),
217
+ datas: $(".ck").serializeArray()
218
+ }, function (data) {
219
+ toastrForm(data);
220
+ if(data.status == 1) {
221
+ if(data.dataStatus.length > 0) {
222
+ data.dataStatus.map((item) => {
223
+ toastr.error(item);
224
+ });
225
+ setTimeout(function() {
226
+ if(data.status ==1) {
227
+ location.href='';
228
+ }
229
+ },4000);
230
+ } else {
231
+ if(data.status ==1) {
232
+ location.href='';
233
+ }
234
+ }
235
+ }
236
+ })
237
+ })
238
+ })</script>${Util.newLine}`
239
+ }
240
+
185
241
  script += `<script type="text/javascript">
186
242
  $(function () {
187
243
  $("#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.60",
4
4
  "description": "zet is a library that part of zet generator.",
5
5
  "engines": {
6
6
  "node": ">=18"