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 +17 -3
- package/lib/zAppRouter.js +132 -1
- package/lib/zCache.js +25 -4
- package/lib/zRoleRouter.js +130 -6
- package/lib/zRoute.js +30 -0
- package/lib/zdataTable.js +64 -8
- package/package.json +1 -1
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"
|
|
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
|
-
|
|
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
|
package/lib/zRoleRouter.js
CHANGED
|
@@ -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
|
-
|
|
312
|
-
|
|
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(
|
|
8
|
-
this.visibles =
|
|
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.
|
|
21
|
-
this.
|
|
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"
|
|
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"
|
|
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
|
-
|
|
129
|
-
|
|
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 () {
|