zet-lib 1.3.38 → 1.3.40

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
@@ -1,1019 +1,1019 @@
1
- /**
2
- * Universal class Form UI HTML
3
- * Created by sintret dev on 8/23/2021.
4
- */
5
-
6
- const Util = require('./Util')
7
-
8
- const Form = {}
9
- const addProperties = (obj, defaultObj = {}) => {
10
- let html = ''
11
- for (var key in obj) {
12
- var value = defaultObj.hasOwnProperty(key) ? defaultObj[key] + obj[key] : obj[key]
13
- html += ` ${key}="${obj[key]}" `
14
- }
15
- return html
16
- }
17
-
18
- Form.options = {
19
- button: {
20
- id: 'form-submit',
21
- type: 'button',
22
- class: 'btn btn-success boxy',
23
- label: `<img src="/assets/icons/send.svg" class="icons-bg-white" > Submit`,
24
- },
25
- field: {},
26
- }
27
-
28
- Form.label = (field, label, required, htmlOptions = '') => {
29
- required = required || false
30
- const mark = required ? '*' : ''
31
- return `<label for="${field}">${label} ${mark} ${htmlOptions}</label>`
32
- }
33
-
34
- Form.textarea = (obj) => {
35
- obj.type = 'textarea'
36
- return Form.field(obj)
37
- }
38
-
39
- Form.input = (obj) => {
40
- obj.type = 'input'
41
- return Form.field(obj)
42
- }
43
-
44
- Form.addProperty = (property, options = []) => {
45
- ///We expect options to be a non-empty Array
46
- if (!options.length) return
47
- var optionsString = options.join(' ')
48
- return ` ${property}="${optionsString}" `
49
- }
50
-
51
- Form.field = (obj) => {
52
- //options and default options
53
- let options = obj.options || {}
54
- let htmlOptions = ''
55
- for (let key in options) {
56
- let val = options[key]
57
- val = Util.replaceAll(val, '"', '')
58
- if (obj.hasOwnProperty(key)) {
59
- obj[key] = options[key]
60
- } else {
61
- htmlOptions += ` ${key}=${val} `
62
- }
63
- }
64
- let type = obj.type || 'text',
65
- id = obj.isTableModule ? '' : Form.addProperty('id', [obj.id]),
66
- name = obj.name ? ` name="${obj.name}" ` : '',
67
- title = obj.title || '',
68
- prepend = obj.prepend || '',
69
- append = obj.append || '',
70
- placeholder = Form.addProperty('placeholder', [obj.placeholder]),
71
- tabindex = Form.addProperty('tabindex', [obj.tabindex]),
72
- value = obj.value == undefined ? '' : obj.value,
73
- classview = obj.class ? ` class="${obj.class}" ` : ` class=" " `,
74
- disabled = obj.disabled ? ` disabled="disabled" ` : '',
75
- data = obj.data,
76
- required = obj.required == true ? ` required ` : '',
77
- table = !obj.table ? '' : obj.table,
78
- frameworkcss = !obj.frameworkcss ? 'bootstrap5' : obj.frameworkcss,
79
- form_css = !obj.form_css ? 'bootstrap' : obj.form_css,
80
- attributes = !obj.attributes ? {} : obj.attributes,
81
- style = !obj.style ? '' : ` style=${obj.style} `,
82
- additional_attributes = !obj.additional_attributes ? '' : obj.additional_attributes,
83
- information = !obj.information ? '' : `<div id="information-${obj.id}" class="form-text">${Util.replaceAll(obj.information.substring(1, obj.information.length - 1), '\r\n', '<br>')}</div>`
84
- //replaceAll("\r\n","<br>")
85
- let attributeDate = ''
86
- if (obj.hasOwnProperty.attributeData) {
87
- for (let key in obj.attributeData) {
88
- attributeDate += ` data-${key}="${obj.attributeData[key]}" `
89
- }
90
- }
91
- let hasInputGroup = false
92
- let inputGroupLeft = '',
93
- inputGroupRight = '',
94
- inputGroupDivLeft = ''
95
- if (attributes.hasOwnProperty('hasInputGroup') && attributes.hasInputGroup) {
96
- hasInputGroup = true
97
- prepend = `<div class="input-group mb-3">`
98
- append = `</div>`
99
- if (attributes.hasOwnProperty('inputGroupLeft') && attributes.inputGroupLeft) {
100
- inputGroupLeft = `<span class="input-group-text">${attributes.inputGroupLeft}</span>`
101
- }
102
- if (attributes.hasOwnProperty('inputGroupRight') && attributes.inputGroupRight) {
103
- inputGroupRight = `<span class="input-group-text">${attributes.inputGroupRight}</span>`
104
- }
105
- }
106
- let displayForm = ''
107
- let readonly = obj.readonly ? `readonly` : ``
108
- let boxyclass = '',
109
- checked = '',
110
- selects = ''
111
- switch (type) {
112
- case 'text':
113
- displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" ${disabled} ${readonly} autofocus="" ${tabindex} ${additional_attributes} type="${type}" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${style} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
114
- break
115
-
116
- case 'checkbox':
117
- checked = value == 1 ? 'checked' : ''
118
- displayForm = `${prepend}<input autocomplete="off" autofocus="" ${tabindex} ${disabled} ${readonly} ${additional_attributes} ${style} type="checkbox" class="form-check-input ${obj.class}" ${id} ${name} ${checked} ${htmlOptions}>${information}${append}`
119
- break
120
-
121
- case 'tags':
122
- classview = ` class="form-control tags ${obj.class ? obj.class : ''} " `
123
- let datahtml = ''
124
- if (value) {
125
- let dataValue = []
126
- if (typeof value == 'string') {
127
- dataValue = JSON.parse(value) || []
128
- } else {
129
- dataValue = value || []
130
- }
131
- dataValue.forEach(function (item) {
132
- datahtml += `<option value="${item}" selected="selected">${item}</option>`
133
- })
134
- }
135
- displayForm = `${prepend}<select ${classview} ${id} ${name} ${additional_attributes} ${placeholder} multiple data-allow-new="true">${datahtml}</select>${information}${append}`
136
- break
137
-
138
- case 'range':
139
- let min = !obj.min ? 0 : obj.min
140
- let max = !obj.max ? 100 : obj.max
141
- displayForm = `${prepend}${inputGroupLeft}<input onmouseover="titlerange(this)" onchange="titlerange(this)" autocomplete="off" autofocus="" ${tabindex} type="${type}" class="form-range ${obj.class}" step="1" ${id} ${name} ${placeholder} ${style} ${required} value="${value}" data-t="${value}" min="${min}" max="${max}" ${htmlOptions}>${inputGroupRight}${information}${append}`
142
- break
143
-
144
- case 'hidden':
145
- displayForm = `${prepend}<input autocomplete="off" autofocus="" ${tabindex} type="${type}" ${additional_attributes} ${style} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${append}`
146
- break
147
-
148
- case 'textarea':
149
- displayForm = `${prepend}${inputGroupLeft}<textarea ${tabindex} ${disabled} class="form-control ${obj.class}" ${id} ${name} ${additional_attributes} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${value}</textarea>${inputGroupRight}${information}${append}`
150
- break
151
-
152
- case 'image':
153
- boxyclass = value ? 'boxy' : ''
154
- let stringvalue = value ? value.substring(13) : ''
155
- let trashicon = stringvalue ? `<img class="tabler-icons icons-filter-danger" src="/assets/icons/trash-filled.svg" onclick="removeimage(this)">` : ''
156
- displayForm = `${prepend}<input ${tabindex} type="file" accept="image/*" onchange="loadFile(this,'${obj.id}' )" data-width="${obj.width}" class="form-control ${obj.class || ''}" ${id} ${name} ${placeholder} value="${value}" ${htmlOptions}>
157
- <div id="body${obj.id}" class="isfile" data-id="${obj.id}" data-table="${obj.routeName}" data-width="${obj.width}" data-name="${obj.title}" data-filename="${value}" data-required="${obj.required}"> <img class="mb-3" width="${obj.width}" id="file${obj.id}" /><br><a class="text-success" target="_blank" href="/uploads/${
158
- obj.routeName
159
- }/${value}"> ${stringvalue}</a> ${trashicon}</div>${append}`
160
- break
161
-
162
- case 'file':
163
- boxyclass = value ? 'boxy' : ''
164
- let stringvaluefile = value ? value.substring(13) : ''
165
- let trashiconfile = stringvaluefile ? `<img class="tabler-icons icons-filter-danger" src="/assets/icons/trash-filled.svg" onclick="removeimage(this)">` : ''
166
- displayForm = `${prepend}<input ${tabindex} type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint,text/plain, application/pdf,.css,.js,.jpg,.png,.gif" onchange="loadFile(this,'${obj.id}' )" class="form-control ${
167
- obj.class || ''
168
- }" ${id} ${name} ${placeholder} value="${value}" ${htmlOptions}>
169
- <div id="body${obj.id}" class="isfile" data-id="${obj.id}" data-name="${obj.title}" data-table="${obj.routeName}" data-filename="${value}" data-required="${obj.required}"> <img class="mb-3" id="file${obj.id}" /><a class="text-success" target="_blank" href="/uploads/${
170
- obj.routeName
171
- }/${value}"> ${stringvaluefile}</a>${trashiconfile}</div>${information}${append}`
172
- break
173
-
174
- case 'email':
175
- displayForm = `${prepend}<input autocomplete="off" autofocus="" ${readonly} ${disabled} ${additional_attributes} ${tabindex} ${style} type="email" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${information}${append}`
176
- break
177
-
178
- case 'number':
179
- displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="text" class="form-control number ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
180
- break
181
-
182
- case 'integer':
183
- displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="number" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
184
- break
185
-
186
- case 'datepicker':
187
- displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="text" class="form-control datepicker ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
188
- break
189
-
190
- case 'datetimepicker':
191
- displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} type="text" ${style} class="form-control datetimepicker ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
192
- break
193
-
194
- case 'password':
195
- displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="password" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}><span toggle="#password" class="bx bi-eye field-icon toggle-password"></span>${inputGroupRight}${information}${append}`
196
- break
197
-
198
- case 'switch':
199
- checked = value == 1 ? ' checked ' : ''
200
- displayForm = `${prepend}<p><input ${tabindex} type="checkbox" class="form-control ${obj.class}" ${readonly} ${style} ${id} ${additional_attributes} ${name} ${checked} ></p>${information}${append}`
201
- break
202
-
203
- case 'lexical':
204
- displayForm = `${prepend}<div ${id}>${information}${append}`
205
- break
206
-
207
- case 'checkbox':
208
- checked = value == 1 ? ' checked ' : ''
209
- displayForm = `${prepend}<input ${tabindex} type="${type}" class="form-control ${obj.class}" ${readonly} ${style} ${id} ${additional_attributes} ${name} ${checked} >${information}${append}`
210
- break
211
-
212
- case 'dropdown_checkbox':
213
- let checkboxes = ''
214
- let val = []
215
- if (typeof value == 'object') {
216
- val = value
217
- } else if (typeof value == 'string') {
218
- if (value) {
219
- val = JSON.parse(value)
220
- }
221
- }
222
- data.forEach(function (item) {
223
- const checked = Util.in_array(item, val) ? ' checked ' : ''
224
- checkboxes += `<div class="checkbox">
225
- <label class="">
226
- <input type="checkbox" name="${obj.name}[${item}]" ${checked} value="${item}">
227
- ${item}
228
- </label>
229
- </div>`
230
- })
231
- displayForm = `${prepend}<div class="form-check">${checkboxes}</div>${information}${append}`
232
- break
233
-
234
- case 'select':
235
- var please_select = obj.please_select
236
- if (please_select != undefined) {
237
- if (please_select != '') {
238
- selects += `<option value="">${please_select}</option>`
239
- }
240
- }
241
- if (obj.hasOwnProperty('array')) {
242
- var items = obj.array || []
243
- if (items.length) {
244
- items.forEach(function (item) {
245
- if (item.label) {
246
- const selected = item.value == value ? ' selected ' : ''
247
- selects += `<option value="${item.value}" ${selected}>${item.label}</option>`
248
- }
249
- })
250
- } else {
251
- if (Array.isArray(data)) {
252
- data.map((item) => {
253
- if (item.zname) {
254
- var selected = item.id == value ? ' selected ' : ''
255
- selects += `<option value="${item.id}" ${selected}>${item.zname}</option>`
256
- }
257
- })
258
- } else {
259
- for (var keys in data) {
260
- if (data[keys]) {
261
- var selected = keys == value ? ' selected ' : ''
262
- selects += `<option value="${keys}" ${selected}>${data[keys]}</option>`
263
- }
264
- }
265
- }
266
- }
267
- } else {
268
- if (Array.isArray(data)) {
269
- data.map((item) => {
270
- if (item.zname) {
271
- const selected = item.id == value ? ' selected ' : ''
272
- selects += `<option value="${item.id}" ${selected}>${item.zname}</option>`
273
- }
274
- })
275
- } else {
276
- for (let keys in data) {
277
- if (data[keys]) {
278
- let selected = keys == value ? ' selected ' : ''
279
- selects += `<option value="${keys}" ${selected}>${data[keys]}</option>`
280
- }
281
- }
282
- }
283
- }
284
- if (form_css == 'material_design') {
285
- classview = Form.addProperty('class', ['selectpicker', obj.class])
286
- }
287
- displayForm = `${prepend}<select ${tabindex} ${style} ${additional_attributes} ${disabled} ${readonly} class="form-control form-select ${obj.class}" ${id} ${name} ${placeholder} ${required} ${htmlOptions} >${selects}</select>${information}${append}`
288
- break
289
-
290
- case 'radio':
291
- let radios = ''
292
- let arr = obj.array || []
293
- arr.map((item, index) => {
294
- //var selected = item.value == value ? ' selected ' : '';
295
- const checked = item.value == value ? ' checked ' : ''
296
- radios += `<div class="form-check">
297
- <input class="form-check-input ${obj.class}" type="radio" name="${obj.name}" ${additional_attributes} value="${item.value}" id="${obj.id}${index}" ${checked}>
298
- <label class="form-check-label" for="${obj.id}${index}">
299
- ${item.label}
300
- </label>
301
- </div>`
302
- })
303
- displayForm = `${prepend} ${radios} ${information}${append}`
304
- break
305
-
306
- case 'select_user':
307
- selects = ''
308
- data.map((item) => {
309
- const selected = item.value == value ? ' selected ' : ''
310
- selects += `<option value="${item.id}" ${selected}>${item.fullname}</option>`
311
- })
312
-
313
- if (form_css == 'material_design') {
314
- classview = Form.addProperty('class', ['selectpicker', obj.class])
315
- }
316
- displayForm = `${prepend}<select ${tabindex} class="form-control form-select ${obj.class}" ${id} ${name} ${placeholder} ${required} ${htmlOptions} >${selects}</select>${information}${append}`
317
- break
318
-
319
- case 'chain':
320
- selects = ''
321
- // for array item.value and item.text
322
- // proptery is value and text
323
- data.map((item) => {
324
- var selected = item.id == value ? ' selected ' : ''
325
- selects += `<option value="${item.id}" ${selected}>${item.zname}</option>`
326
- })
327
- if (form_css == 'material_design') {
328
- classview = Form.addProperty('class', ['selectpicker', obj.class])
329
- }
330
- displayForm = `${prepend}<select ${tabindex} class="form-control form-select ${obj.class}" ${id} ${name} ${placeholder} ${required} ${htmlOptions} >${selects}</select>${information}${append}`
331
- break
332
-
333
- case 'multi':
334
- selects = ''
335
- if (data) {
336
- data.map((item) => {
337
- selects += `<option value="${item.id}">${item.zname}</option>`
338
- })
339
- }
340
-
341
- var spanmulti = ''
342
- if (value) {
343
- let arr = []
344
- arr = typeof value == 'string' ? JSON.parse(value) : value
345
- if (Array.isArray(arr)) {
346
- arr.forEach(function (item, index) {
347
- spanmulti += `<span class='span${obj.id}'>${index + 1}. <input type='hidden' name='${obj.name}[]' value='${item}' />${obj.multi[item]}<img class='tabler-icons icons-filter-danger pull-right' src='/assets/icons/trash-filled.svg' onclick='$(this).closest("span").remove();' title='${LANGUAGE['delete']}' /><br></span>`
348
- })
349
- }
350
- }
351
- if (form_css == 'material_design') {
352
- classview = Form.addProperty('class', ['selectpicker', obj.class])
353
- }
354
-
355
- let g = `<div class="input-group ">
356
- <span class="input-group-text" id="dropdownadd${id}" class="dropdownadd" data-id="${id}" style="cursor: pointer" title="Add Data">+</span>
357
- </div>
358
- <div id="dropdownbox${id}" class="boxy">
359
- <span class="span${id}">
360
- </span>
361
- </div>`
362
- return `<div class="input-group">
363
- <select ${tabindex} class="form-control ${obj.class} dropdown-multi" name='${obj.name}' ${id} ${placeholder} ${htmlOptions} >${selects}</select>
364
- <span id="dropdownadd${obj.id}" class="input-group-text dropdownadd" data-id="${obj.id}" style="cursor: pointer;" title=" ${LANGUAGE['form_add_data']} ">+</span>
365
- </div>
366
- <div id="dropdownbox${obj.id}" class="boxy mb-3">${spanmulti}</div>`
367
- break
368
-
369
- case 'typeahead':
370
- let typeahead_value = Util.replaceAll(obj.typeaheadvalue, '"', `'`)
371
- displayForm = `${prepend}<div class="input-group">
372
- <input ${tabindex} type="text" class="form-control ${obj.class}" id="${obj.id}Typeahead" autocomplete="off" data-provide="typeahead" id="${obj.id}Typeahead" placeholder="Please type a word" value="${typeahead_value}" >
373
- <input type="hidden" ${id} ${name} ${placeholder} ${classview} ${required} value="${value}">
374
- <span id="${obj.id}Clear" class="input-group-addon input-group-text dropdownadd" title="Clear" style="cursor: pointer;" title=" Add Data "><img src="/assets/icons/ban.svg" class="icons-bg-black" ></span>
375
- </div>${information}${append}`
376
- break
377
-
378
- case 'table':
379
- let html = ''
380
- /*console.log(`table : ${JSON.stringify(obj.data)}`)
381
- console.log(JSON.stringify(obj.data))
382
- console.log(JSON.stringify(obj.properties));*/
383
- for (let key in obj.data) {
384
- if (obj.properties[key].hidden) {
385
- html += `<th></th>`
386
- } else {
387
- html += `<th>${obj.data[key]}</th>`
388
- }
389
- }
390
- let btnAdd = ''
391
- if (!obj.isAddButton && !obj.viewOnly) {
392
- btnAdd = `<th class="float-end"><img id="add${obj.id}" src="/assets/icons/plus.svg" class="icons-bg-white boxy-small btn-plus" ></th>`
393
- }
394
- obj.btnAdd = btnAdd
395
- obj.html = html
396
- obj.title = title
397
- obj.table = table
398
- obj.value = value
399
- let datavalue = ''
400
- if (obj.value) {
401
- datavalue = JSON.stringify(obj.value)
402
- datavalue = Util.replaceAll(datavalue, "'", '`')
403
- }
404
- obj.prepend = prepend
405
- obj.body = `<div class="table-responsive">
406
- <table id="table${obj.id}" class="table table-hover table-sm">
407
- <thead>
408
- <tr>
409
- ${html}
410
- ${obj.btnAdd}
411
- </tr>
412
- </thead>
413
- <tbody id="body-${obj.id}" data-value='${datavalue}'>${obj.bodyTable}</tbody>
414
- </table></div>`
415
- displayForm = Form.card(frameworkcss, obj)
416
- break
417
-
418
- case 'multi_line_editor':
419
- value = obj.value ? obj.value : {}
420
- let description = obj.description || ''
421
- for (var key in obj.fields) {
422
- let val = !value[key] ? obj.fields[key] : value[key]
423
- description = Util.replaceAll(description, `[[[${key}]]]`, `<span class="text-danger text-toggle" id="a_${key}" data-id="${key}" style="text-decoration: underline; cursor: pointer">${val}</span> <input type="hidden" name="${obj.name}[${key}]" class="editor-value" id="${key}" data-id="${key}" value="${val}" >`)
424
- }
425
- displayForm = `${prepend}<div class="boxy">${description}</div>${information}${append}`
426
- break
427
-
428
- case 'ide_editor':
429
- displayForm = `<div class="ide_editor" id="editor_${obj.id}"></div>`
430
- displayForm += `<textarea hidden ${classview} ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4"></textarea>${information}${append}`
431
- break
432
-
433
- case 'json':
434
- displayForm += `<textarea ${additional_attributes} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${JSON.stringify(obj.value)}</textarea>${information}${append}`
435
- break
436
-
437
- case 'json_array':
438
- displayForm += `<textarea ${additional_attributes} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${JSON.stringify(obj.value)}</textarea>${information}${append}`
439
- break
440
-
441
- case 'dragdrop':
442
- //dataObject
443
- let leftButtons = ``
444
- let rightButtons = ``
445
- let all = Object.keys(obj.dataObject)
446
- all.map((item, index) => {
447
- if (!value.includes(item)) {
448
- rightButtons += `<li><button class="btn btn-danger boxy" type="button">${obj.dataObject[item]}<input type="hidden" name='trashx' value="${item}"></button></li>`
449
- }
450
- })
451
- value = value || []
452
- value.map((item, index) => {
453
- leftButtons += `<li><button class="btn btn-primary boxy" type="button">${obj.dataObject[item]}<input type="hidden" name='${obj.name}[]' value="${item}"></button></li>`
454
- })
455
-
456
- displayForm += `<div id="dragdrop_${obj.id}" class="row contentfields">
457
- <div class="col-md-6">
458
- <h5>${obj.attributes.left}</h5>
459
- <ol class="mydragable${obj.id} divboxlittle" data-type="left" data-name="${obj.name}[]">${leftButtons}</ol>
460
- </div>
461
- <div class="col-md-6">
462
- <h5>${obj.attributes.right}</h5>
463
- <ol class="mydragable${obj.id} divboxlittle" data-type="right" data-name="trashx">
464
- ${rightButtons}
465
- </ol>
466
- </div>
467
- </div>`
468
- break
469
-
470
- case 'array':
471
- displayForm += `<textarea ${additional_attributes} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${JSON.stringify(obj.value)}</textarea>${information}${append}`
472
- break
473
-
474
- case 'virtual':
475
- displayForm = `${prepend}<input ${additional_attributes} autocomplete="off" autofocus="" ${tabindex} ${style} type="text" ${classview} readonly ${id} ${placeholder} ${required} value="${value}" ${htmlOptions}>${information}${append}`
476
- break
477
-
478
- //additionals for form view in view
479
- case 'plaintext':
480
- displayForm = `<span class="">${obj.value || ''}</span>`
481
- break
482
-
483
- case 'div':
484
- displayForm = `<div id="${obj.id}" class="${obj.class}">${obj.value}</div>`
485
- break
486
-
487
- case 'data_table':
488
- displayForm = obj.html
489
- break
490
-
491
- case 'location':
492
- displayForm = `${prepend}<input type="text" class="form-control ${obj.class}" id="search_map_location" placeholder="type a place" ${required} value="" ${htmlOptions}>${information}${append}
493
- <textarea ${id} ${name} style="display: none" ${readonly} rows="2">${JSON.stringify(obj.value)}</textarea>
494
- <div id="map_${obj.id}" style="background-color:#C3C3C3;width: 100%;height: ${obj.height}px"></div>`
495
- break
496
-
497
- case 'dropzone':
498
- displayForm = `${prepend}<div ${tabindex} ${style} type="text" ${classview} ${id} ${htmlOptions}><label for="files" class="dropzone-container">
499
- <div class="dz-message" data-dz-message><div class="file-icon"><span class="icon-small icons-primary"><img class="icons-bg-white icon-image-large" src="/assets/icons/file-plus.svg"></span></div>
500
- <div class="text-center pt-3 px-5">
501
- <p class="w-80 h5 text-dark fw-bold">Drag your documents, photos or videos here to start uploading.</p>
502
- </div></div>
503
- </label></div>${information}${append}`
504
- break
505
-
506
- case 'dropzoneview':
507
- let countFiles = obj.value && obj.value.length ? obj.value.length + ' Files' : ''
508
- let bodydropzoneview =
509
- countFiles == '' ? '' : `<div class="card-header">${countFiles} <div class="float-end"><span class="icon-small icons-light" title="Download"><img onclick="location.href= '/zdownloads-dropzone/${obj.routeName}/${obj.key}/${obj.dataId}'" class="icons-bg-black gridview icon-image" src="/assets/icons/download.svg"></span></div> </div>`
510
- displayForm = `<div class="card">
511
- ${bodydropzoneview}
512
- <div class="card-body">`
513
- if (obj.value && obj.value.length > 0) {
514
- obj.value.map((item) => {
515
- let extFile = Util.fileExtension(item)
516
- let filename = `/uploads/${obj.table}/${obj.key}/${item}`
517
- if (extFile.type == 'image') {
518
- displayForm += `<img src="${filename}" class="boxy zoom mx-2 my-2" width="200px">`
519
- } else {
520
- displayForm += '<br>' + Util.fileView(`/uploads/${obj.table}/${obj.key}/`, item, { withIcon: true }) + '<br>'
521
- }
522
- })
523
- }
524
- displayForm += `</div></div>`
525
-
526
- break
527
- default:
528
- displayForm = `${prepend}${inputGroupLeft}<input ${disabled} autocomplete="nope" autofocus="" ${readonly} ${tabindex} type="${type}" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
529
- break
530
- }
531
-
532
- return displayForm
533
- }
534
-
535
- Form.group = (name, label, field) => {
536
- return `<div class="form-group div${name} mb-3">${label}${field}</div>`
537
- }
538
-
539
- Form.button = (optionsExtends = {}) => {
540
- let options = Form.options.button
541
- let htmlOptions = ''
542
- for (let key in optionsExtends) {
543
- let val = optionsExtends[key]
544
- val = Util.replaceAll(val, '"', '')
545
- if (options.hasOwnProperty(key)) {
546
- options[key] = optionsExtends[key]
547
- } else {
548
- htmlOptions += ` ${key}=${val} `
549
- }
550
- }
551
- return `<button id="${options.id}" type="${options.type}" class="${options.class}" ${htmlOptions}>${options.label}</button>`
552
- }
553
-
554
- Form.buttonGroup = (buttons = []) => {
555
- let html = `<div class="btn-group" role="group" aria-label="...">`
556
- html += buttons.join(' ')
557
- html += `</div>`
558
- return html
559
- }
560
-
561
- Form.submit = (optionsExtends = {}) => {
562
- let options = {
563
- id: 'form-submit',
564
- type: 'submit',
565
- class: 'btn btn btn-success boxy image-button ',
566
- label: `<img src="/assets/icons/send.svg" class="icons-bg-white" > <span>${LANGUAGE['submit']}</span>`,
567
- }
568
- let settings = { ...options, ...optionsExtends }
569
- return Form.button(settings)
570
- }
571
-
572
- Form.pullRight = (frameworkcss) => {
573
- if (frameworkcss == 'bootstrap3') {
574
- return 'pull-right'
575
- } else if (frameworkcss == 'bootstrap4') {
576
- return 'float-right'
577
- } else {
578
- return 'float-end'
579
- }
580
- }
581
-
582
- Form.breadcrumb = (type, arr) => {
583
- let html = `<nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E&#34;);" aria-label="breadcrumb"><ol class="breadcrumb float-end">`
584
- arr.map((item) => {
585
- if (item.active == true) {
586
- html += `<li class="breadcrumb-item active" aria-current="page">${item.text}</li>`
587
- } else {
588
- html += `<li class="breadcrumb-item"><a href="${item.href}">${item.text}</a></li>`
589
- }
590
- })
591
- html += `</ol></nav>`
592
- return html
593
- }
594
-
595
- Form.breadcrumbs = (arr) => {
596
- let html = `<nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E&#34;);" aria-label="breadcrumb"><ol class="breadcrumb float-end">`
597
- arr.map((item) => {
598
- if (item.active == true) {
599
- html += `<li class="breadcrumb-item active" aria-current="page">${item.text}</li>`
600
- } else {
601
- html += `<li class="breadcrumb-item"><a href="${item.href}">${item.text}</a></li>`
602
- }
603
- })
604
- html += `</ol></nav>`
605
- return html
606
- }
607
-
608
- Form.breadcrumbIndex = () => {
609
- return Form.breadcrumbs([
610
- { text: LANGUAGE['home'], href: '/dashboard' },
611
- { text: LANGUAGE['grid_list'], active: true },
612
- ])
613
- }
614
-
615
- Form.breadcrumbCreate = (routeName) => {
616
- return Form.breadcrumbs([
617
- { text: LANGUAGE['home'], href: '/dashboard' },
618
- { text: LANGUAGE['grid_list'], href: '/' + routeName },
619
- { text: LANGUAGE['create'], active: true },
620
- ])
621
- }
622
-
623
- Form.breadcrumbUpdate = (routeName, id) => {
624
- return Form.breadcrumbs([
625
- { text: LANGUAGE['home'], href: '/dashboard' },
626
- { text: LANGUAGE['grid_list'], href: '/' + routeName },
627
- { text: LANGUAGE['create'], href: '/' + routeName + '/create' },
628
- { text: LANGUAGE['view'], href: '/' + routeName + '/view/' + id },
629
- { text: LANGUAGE['update'], active: true },
630
- ])
631
- }
632
-
633
- Form.breadcrumbView = (routeName) => {
634
- return Form.breadcrumbs([
635
- { text: LANGUAGE['home'], href: '/dashboard' },
636
- { text: LANGUAGE['grid_list'], href: '/' + routeName },
637
- { text: LANGUAGE['view'], active: true },
638
- ])
639
- }
640
-
641
- Form.breadcrumbImport = (routeName) => {
642
- return Form.breadcrumbs([
643
- { text: LANGUAGE['home'], href: '/dashboard' },
644
- { text: LANGUAGE['grid_list'], href: '/' + routeName },
645
- { text: LANGUAGE['create'], href: '/' + routeName + '/create' },
646
- { text: LANGUAGE['form_import'], active: true },
647
- ])
648
- }
649
-
650
- Form.breadcrumbApproval = (routeName, id) => {
651
- return Form.breadcrumbs([
652
- { text: LANGUAGE['home'], href: '/dashboard' },
653
- { text: LANGUAGE['grid_list'], href: '/' + routeName },
654
- { text: LANGUAGE['update'], href: '/' + routeName + '/update/' + id },
655
- { text: LANGUAGE['create'], href: '/' + routeName + '/create' },
656
- { text: 'Approval', active: true },
657
- ])
658
- }
659
-
660
- Form.grid = (type, obj) => {
661
- return gridBootstrap5(obj)
662
- }
663
-
664
- /*
665
- tab property
666
- label,active,content,headerOptions
667
- */
668
- Form.tab = (type, obj) => {
669
- return tabBootstrap5(obj)
670
- }
671
-
672
- Form.card = (type, obj) => {
673
- return card45(obj)
674
- }
675
-
676
- //card 4 & 5 bootstrap
677
- const card45 = (obj) => {
678
- let html = obj.prepend
679
- let objHeader = obj.headerOptions || {}
680
- let headerOptions = obj.headerOptions ? addProperties(obj.headerOptions, { class: 'card' }) : addProperties({ class: 'card' })
681
- let img = obj.img ? `<img ${addProperties(obj.img)} >` : ''
682
- let title = `<div class="card-header"><h5 class="card-title">${obj.title}</h5></div>`
683
- let footer = (obj.footer = obj.footer ? `<div class="card-footer">${obj.footer}</div>` : ``)
684
- let append = !obj.append ? '' : obj.append
685
- html += `<div ${headerOptions}>
686
- ${img}
687
- ${title}
688
- <div class="card-body">
689
- ${obj.body}
690
- </div>
691
- ${footer}
692
- </div>`
693
-
694
- html += append
695
- return html
696
- }
697
-
698
- const cardBootstrap5 = (obj) => {
699
- return `${obj.prepend}<div class="card div${obj.id}">
700
- <div class="card-content">
701
- <div class="card-body">
702
- <div class="card-title">${obj.title}</div>
703
- <div class="table-responsive">
704
- <table id="table${obj.id}" class="table">
705
- <thead>
706
- <tr>
707
- ${obj.html}
708
- ${obj.btnAdd}
709
- </tr>
710
- </thead>
711
- <tbody id="body-${obj.id}" data-value='${obj.value}'>${obj.table}</tbody>
712
- </table>
713
- </div>
714
- </div>
715
- </div>
716
- </div>`
717
- }
718
-
719
- const gridBootstrap5 = (obj) => {
720
- let levels = obj.levels
721
- let routeName = obj.routeName
722
- let advanceSearch = !obj.advanceSearch ? '' : obj.advanceSearch
723
- let createBtn = '',
724
- exportBtn = '',
725
- importBtn = '',
726
- superBtn = '',
727
- exportBtnGroup = '',
728
- selectPagesize = ''
729
- if (levels.create) {
730
- createBtn = `<button type="button" id="create_btn" class="btn btn-success btn-xs"><i class="fa fa-plus white-icon"></i></button>`
731
- }
732
- if (levels.export) {
733
- exportBtn = `<button type="button" id="backupExcel" class="btn btn-info btn-xs" title="${obj.LANGUAGE['download_excel']}"><i class="fas fa-file-excel"></i></button>`
734
-
735
- exportBtnGroup = `<div class="btn-group" role="group">
736
- <button id="dropdownExport" type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
737
- ${obj.LANGUAGE['grid_export_data']}
738
- </button>
739
- <div class="dropdown-menu" aria-labelledby="dropdownExport">
740
- <a class="dropdown-item export-xls" href="#"><i class="text-success fa fa-file-excel-o"></i> Excel </a>
741
- <a class="dropdown-item export-pdf" href="#"><i class="text-danger fa fa-file-pdf-o"></i> PDF </a>
742
- </div>
743
- </div>`
744
- }
745
- if (levels.import) {
746
- importBtn = `<button type="button" id="importExcel" class="btn btn-warning btn-xs" title="<%- LANGUAGE['data_import'] %>"><i class="fas fa-file-import"></i></button>`
747
- }
748
- selectPagesize = `<div class="dropdown-menu" aria-labelledby="dropdownPagination">`
749
- let pageSize = obj.gridFilters.pageSize || 20
750
-
751
- for (var i = 0; i < obj.paginationApp.length; i++) {
752
- var actived = pageSize == obj.paginationApp[i] ? ' active ' : ''
753
- selectPagesize += `<a data-value="${obj.paginationApp[i]}" class="dropdown-item pageSizeGrid ${actived}" id="pagination${obj.paginationApp[i]}" href="#" >${obj.paginationApp[i]}</a>`
754
- }
755
- selectPagesize += `</div>`
756
-
757
- let toolbarDefault = `<div class="float">
758
- <div class="btn-group float-end" role="group" aria-label="Button group with nested dropdown">
759
- ${createBtn}
760
- ${exportBtn}
761
- ${importBtn}
762
- <button type="button" class="btn btn-secondary btn-xs" title="${LANGUAGE['grid_personalize_labeling']}" data-bs-toggle="modal" data-bs-target="#grid-labels" ><i class="fa fa-font"></i></button>
763
- <button type="button" class="btn btn-info btn-xs" title="${LANGUAGE['grid_personalize_setting']}" data-bs-toggle="modal" data-bs-target="#grid-modal"><i class="fa fa-cog"></i></button>
764
- <button type="button" id="reloadgrid" class="btn btn-default btn-xs" title="${LANGUAGE['grid_refresh']}"><i class="fas fa-redo"></i></button>
765
- <div class="btn-group" role="group">
766
- <button id="dropdownPagination" type="button" class="btn btn-info dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
767
- Pagination ${pageSize}
768
- </button>
769
- ${selectPagesize}
770
- </div>
771
-
772
- <div class="btn-group" role="group">
773
- <button id="dropdownExport" type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
774
- ${obj.LANGUAGE['grid_export_data']}
775
- </button>
776
- <div class="dropdown-menu" aria-labelledby="dropdownExport">
777
- <a class="dropdown-item export-xls" href="#"><i class="text-success fa fa-file-excel-o"></i> Excel </a>
778
- <a class="dropdown-item export-pdf" href="#"><i class="text-danger fa fa-file-pdf-o"></i> PDF </a>
779
- </div>
780
- </div>
781
-
782
- </div></div>`
783
- let toolbar = obj.toolbar ? obj.toolbar : toolbarDefault
784
- let html = ''
785
- html += `<div class="card">
786
- <div class="card-body">
787
- <div class="float-end">
788
- <div class="summary"></div>
789
- </div>
790
- <div class="card-title"><i class="fa fa-book"></i> ${obj.header}</div>
791
- <div class="row">
792
- ${toolbar}
793
- <div style="padding-top: 7px;"><a href="#" class="open_advancesearch"> Advance Search</a></div>
794
- ${advanceSearch}
795
- </div>
796
-
797
- <input type="hidden" id="pageSize" value="${pageSize}">
798
- <div class="table-responsive pt-3 row">
799
- <div id="jsGrid" class="table-responsive"></div>
800
- </div>
801
- </div>
802
- </div>`
803
- return html
804
- }
805
-
806
- const tabBootstrap5 = (arr = []) => {
807
- let html = ''
808
- html += `<ul class="nav nav-tabs" id="myTab" role="tablist">${Util.newLine}`
809
- arr.forEach(function (item, index) {
810
- var active = '',
811
- selected = 'false'
812
- if (item.active) {
813
- active = 'active'
814
- selected = 'true'
815
- }
816
- html += `${Util.tab}
817
- <li class="nav-item" role="presentation" >
818
- <button class="nav-link ${active}" id="tab${index}" data-bs-toggle="tab" data-bs-target="#arr${index}" type="button" role="tab" aria-controls="arrtab${index}" aria-selected="true">${item.label}</button>
819
- </li>${Util.newLine}`
820
- })
821
- html += `</ul>`
822
- return {
823
- html: html,
824
- class: 'tab-pane fade',
825
- active: 'show active',
826
- }
827
- }
828
-
829
- Form.build = (obj) => {
830
- let html = ''
831
- let required = !obj.required ? '' : `<span class="required-mark">*</span>`
832
- let labelOptions = !obj.labelOptions ? '' : obj.labelOptions
833
- let relation = ''
834
- //form float
835
- let float = false
836
- let inline = false
837
- let attributes = Object.prototype.hasOwnProperty.call(obj, 'attributes') ? obj.attributes : {}
838
- let view_only = Object.prototype.hasOwnProperty.call(obj, 'view_only') ? obj.view_only : false
839
- if (!view_only) {
840
- if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'name')) {
841
- if (obj.attributes.name == 'relation' || obj.attributes.name == 'typeahead' || obj.attributes.name == 'dropdown_multi') {
842
- relation = `<a target="_blank" href="/${obj.attributes.table}"> > </a>`
843
- }
844
- }
845
- }
846
-
847
- if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'float')) {
848
- float = obj.attributes.float || false
849
- }
850
- if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'inline')) {
851
- inline = obj.attributes.inline || false
852
- }
853
-
854
- if (float) {
855
- //obj.class = "nice-float"
856
- if (obj.type == 'checkbox') {
857
- html += `<div class="form-switch mx-auto div${obj.id} mb-3">${Form.field(obj)}<label class="form-check-label" for="">${obj.id} ${required}</label></div>`
858
- } else {
859
- html += `<div class="form-floating mx-auto mb-3 mt-3 div${obj.id} mb-3">${Form.field(obj)}<label for="${obj.id}">${obj.title} ${required} ${relation}</label></div>`
860
- }
861
- } else {
862
- if (inline) {
863
- if (obj.type == 'checkbox') {
864
- html += ` <div class="mb-3 row"><label for="${obj.id}" class="col form-check-label">${obj.title} ${labelOptions} ${required} ${relation}</label><div class="col-8">${Form.field(obj)}</div></div>`
865
- } else {
866
- html += ` <div class="mb-3 row"><label for="${obj.id}" class="col col-form-label">${obj.title} ${labelOptions} ${required} ${relation}</label><div class="col-8">${Form.field(obj)}</div></div>`
867
- }
868
- } else {
869
- if (obj.type == 'checkbox') {
870
- html += `<div class="form-check div${obj.id} mb-3">${Form.field(obj)}<label class="form-check-label" for="${obj.id}">${obj.title} ${labelOptions} ${required}</label></div>`
871
- } else {
872
- html += `<div class="form-group div${obj.id} mb-3"><label for="${obj.id}">${obj.title} ${labelOptions} ${required} ${relation}</label>${Form.field(obj)}</div>`
873
- }
874
- }
875
- }
876
- return html
877
- }
878
-
879
- Form.modal = (obj, LANGUAGE = {}) => {
880
- let attributeData = obj.attributeData,
881
- visibles = obj.visibles || [],
882
- invisibles = obj.invisibles || [],
883
- visiblesHtml = '',
884
- invisiblesHtml = '',
885
- labelsHtml = ''
886
- visibles.map((item) => {
887
- visiblesHtml += `<li data-name="${item}" draggable="true" class="image-li" role="option" aria-grabbed="false"><img src="/assets/icons/eye.svg" class="icons-bg-black"> ${attributeData.labels[item]}</li>`
888
- })
889
- invisibles.map((item) => {
890
- invisiblesHtml += `<li data-name="${item}" draggable="true" class="image-li" role="option" aria-grabbed="false"><img src="/assets/icons/eye-off.svg" class="icons-bg-black"> ${attributeData.labels[item]}</li>`
891
- })
892
- let no = 1
893
- for (let key in attributeData.labels) {
894
- labelsHtml += `<tr><td>${no}</td><td>${key}</td><td>${attributeData.labels[key]}</td><td><input maxlength="25" type="text" class="form-control" required name="${obj.routeName}[${key}]" value="${attributeData.labels[key]}"></td></tr>`
895
- no++
896
- }
897
- const modalFields = Form.modalBuild({
898
- id: 'grid-modal',
899
- size: 'modal-xl',
900
- header: `<h5 id="dynagrid-1-grid-modal-label" class="modal-title">
901
- <i class="fa fa-cog"></i> ${LANGUAGE.grid_settings || 'Settings Grid'}
902
- </h5>`,
903
- body: `<div class="container">
904
- <form id="form-grid" class="form-vertical kv-form-bs4" action="/${obj.routeName}/grid" method="post">
905
- <input type="hidden" name="_csrf" value="">
906
- <div class="dynagrid-column-label">
907
- ${LANGUAGE.grid_configure || 'Configure Order and Display of Grid Columns'}
908
- </div>
909
- <div class="row">
910
- <div class="col-sm-5">
911
- <ul id="gridleft" class="sortable-visible sortable list kv-connected cursor-move gridsortable" aria-dropeffect="move">
912
- <li data-name="" class="alert alert-info dynagrid-sortable-header disabled">
913
- ${LANGUAGE.grid_visible || 'Visible Columns'}
914
- </li>
915
- ${visiblesHtml}
916
- </ul>
917
- </div>
918
- <div class="col-sm-2 text-center">
919
- <div class="dynagrid-sortable-separator"><i class="fas fa-arrows-alt-h"></i></div>
920
- </div>
921
- <div class="col-sm-5">
922
- <ul id="gridright"
923
- class="sortable-hidden sortable list kv-connected cursor-move gridsortable" aria-dropeffect="move">
924
- <li data-name="" class="alert alert-info dynagrid-sortable-header disabled">${LANGUAGE.grid_invisible || 'Hidden / Fixed Columns'}
925
- </li>
926
- ${invisiblesHtml}
927
- </ul>
928
- </div>
929
- </div>
930
- <input type="hidden" id="serialize_left" name="serialize_left" value=''/>
931
- <input type="hidden" id="serialize_right" name="serialize_right" value=''/>
932
- </form>
933
- </div> <!-- .dynagrid-config-form -->`,
934
- footer: `<select id="zgrid_default_type" class="form-control select-sm" style="width:100px"><option value="1">Standart</option><option value="2">Fixed Header</option><option value="3">Footer Total</option><option value="4">No Wrap</option><option value="5">Fixed Header & No Wrap</option><option value="6">Footer Total & No Wrap</option><option value="7">Fixed Header & Footer & No Wrap</option></select>
935
- <button type="reset" class="btn btn-default refresh gridreload image-button" title="Abort any changes and reset settings">
936
- <img src="/assets/icons/refresh.svg" class="icons-bg-black"> ${LANGUAGE.reset || 'Reset'}
937
- </button>
938
- <button type="button" class="btn btn-primary grid-submit boxy image-button" title="Save grid settings">
939
- <img src="/assets/icons/send.svg" class="icons-bg-white"> ${LANGUAGE.apply || 'Apply'}
940
- </button>`,
941
- })
942
-
943
- let modalFields2 = `
944
- <div class="modal fade" id="grid-lock" tabindex="-1" aria-labelledby="grid-lock-label" aria-hidden="true">
945
- <div class="modal-dialog">
946
- <div class="modal-content">
947
- <div class="modal-header">
948
- <h1 class="modal-title fs-5">Lock/Unlock</h1>
949
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
950
- </div>
951
- <div class="modal-body">
952
- <button title="Lock" style="background-color: #DC4C64; color:white" class="btn btn-save-lock boxy-small dimens2x image-button" type="button"><img src="/assets/icons/lock.svg" class="icons-bg-white"> Lock</button>
953
- <button title="Unlock" style="background-color: #14A44D; color:white" class="btn btn-save-unlock boxy-small dimens2x image-button" type="button"><img src="/assets/icons/lock-open.svg" class="icons-bg-white"> Unlock</button>
954
- </div>
955
- </div>
956
- </div>
957
- </div>`
958
- let modalFields3 = `
959
- <div class="modal fade" id="grid-approval" tabindex="-1" aria-labelledby="grid-approval-label" aria-hidden="true">
960
- <div class="modal-dialog">
961
- <div class="modal-content">
962
- <div class="modal-header">
963
- <h1 class="modal-title fs-5" >Approvals</h1>
964
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
965
- </div>
966
- <div class="modal-body" style="min-height: 150px">
967
- <div class="row"><div class="col-md-12 modal-body-approval"></div></div>
968
- </div>
969
- </div>
970
- </div>
971
- </div>`
972
- let modalFields4 = `
973
- <div class="modal fade" id="grid-delete-all" tabindex="-1" aria-labelledby="grid-delete-all-label" aria-hidden="true">
974
- <div class="modal-dialog">
975
- <div class="modal-content">
976
- <div class="modal-header">
977
- <h1 class="modal-title fs-5">Delete selected data</h1>
978
- <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
979
- </div>
980
- <div class="modal-body">
981
- <button title="Delete All" style="background-color: #DC4C64; color:white" class="btn btn-save-delete-selected boxy-small dimens2x image-button" type="button"><img src="/assets/icons/http-delete.svg" class="icons-bg-white"> Delete selected data</button>
982
- </div>
983
- </div>
984
- </div>
985
- </div>`
986
- try {
987
- return modalFields + modalFields2 + modalFields3 + modalFields4
988
- } catch (err) {
989
- console.log(err)
990
- }
991
- }
992
-
993
- Form.modalBuild = (obj) => {
994
- let html = '<!-- Modal -->'
995
- try {
996
- const size = obj.size ? `${obj.size}` : ''
997
- const id = obj.id ? `id="${obj.id}"` : ''
998
- const headerOptions = Util.attributeOptions(obj.headerOptions || {}, { class: 'modal-header' })
999
- const header = obj.header ? `<div ${headerOptions} >${obj.header}<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>` : ''
1000
- const body = obj.body ? obj.body : ''
1001
- const bodyOptions = Util.attributeOptions(obj.bodyOptions || {}, { class: 'modal-body' })
1002
- const footerOptions = Util.attributeOptions(obj.footerOptions || {}, { class: 'modal-footer' })
1003
- const footer = obj.footer ? `<div ${footerOptions} >${obj.footer}</div>` : ''
1004
- html += `${Util.newLine}<div class="modal fade " ${id} role="dialog" tabindex="-1">
1005
- <div class="modal-dialog ${size}">
1006
- <div class="modal-content">
1007
- ${header}
1008
- <div ${bodyOptions}>${body}</div>
1009
- ${footer}
1010
- </div>
1011
- </div>
1012
- </div>`
1013
- } catch (error) {
1014
- console.log(error)
1015
- }
1016
- return html
1017
- }
1018
-
1019
- module.exports = Form
1
+ /**
2
+ * Universal class Form UI HTML
3
+ * Created by sintret dev on 8/23/2021.
4
+ */
5
+
6
+ const Util = require('./Util')
7
+
8
+ const Form = {}
9
+ const addProperties = (obj, defaultObj = {}) => {
10
+ let html = ''
11
+ for (var key in obj) {
12
+ var value = defaultObj.hasOwnProperty(key) ? defaultObj[key] + obj[key] : obj[key]
13
+ html += ` ${key}="${obj[key]}" `
14
+ }
15
+ return html
16
+ }
17
+
18
+ Form.options = {
19
+ button: {
20
+ id: 'form-submit',
21
+ type: 'button',
22
+ class: 'btn btn-success boxy',
23
+ label: `<img src="/assets/icons/send.svg" class="icons-bg-white" > Submit`,
24
+ },
25
+ field: {},
26
+ }
27
+
28
+ Form.label = (field, label, required, htmlOptions = '') => {
29
+ required = required || false
30
+ const mark = required ? '*' : ''
31
+ return `<label for="${field}">${label} ${mark} ${htmlOptions}</label>`
32
+ }
33
+
34
+ Form.textarea = (obj) => {
35
+ obj.type = 'textarea'
36
+ return Form.field(obj)
37
+ }
38
+
39
+ Form.input = (obj) => {
40
+ obj.type = 'input'
41
+ return Form.field(obj)
42
+ }
43
+
44
+ Form.addProperty = (property, options = []) => {
45
+ ///We expect options to be a non-empty Array
46
+ if (!options.length) return
47
+ var optionsString = options.join(' ')
48
+ return ` ${property}="${optionsString}" `
49
+ }
50
+
51
+ Form.field = (obj) => {
52
+ //options and default options
53
+ let options = obj.options || {}
54
+ let htmlOptions = ''
55
+ for (let key in options) {
56
+ let val = options[key]
57
+ val = Util.replaceAll(val, '"', '')
58
+ if (obj.hasOwnProperty(key)) {
59
+ obj[key] = options[key]
60
+ } else {
61
+ htmlOptions += ` ${key}=${val} `
62
+ }
63
+ }
64
+ let type = obj.type || 'text',
65
+ id = obj.isTableModule ? '' : Form.addProperty('id', [obj.id]),
66
+ name = obj.name ? ` name="${obj.name}" ` : '',
67
+ title = obj.title || '',
68
+ prepend = obj.prepend || '',
69
+ append = obj.append || '',
70
+ placeholder = Form.addProperty('placeholder', [obj.placeholder]),
71
+ tabindex = Form.addProperty('tabindex', [obj.tabindex]),
72
+ value = obj.value == undefined ? '' : obj.value,
73
+ classview = obj.class ? ` class="${obj.class}" ` : ` class=" " `,
74
+ disabled = obj.disabled ? ` disabled="disabled" ` : '',
75
+ data = obj.data,
76
+ required = obj.required == true ? ` required ` : '',
77
+ table = !obj.table ? '' : obj.table,
78
+ frameworkcss = !obj.frameworkcss ? 'bootstrap5' : obj.frameworkcss,
79
+ form_css = !obj.form_css ? 'bootstrap' : obj.form_css,
80
+ attributes = !obj.attributes ? {} : obj.attributes,
81
+ style = !obj.style ? '' : ` style=${obj.style} `,
82
+ additional_attributes = !obj.additional_attributes ? '' : obj.additional_attributes,
83
+ information = !obj.information ? '' : `<div id="information-${obj.id}" class="form-text">${Util.replaceAll(obj.information.substring(1, obj.information.length - 1), '\r\n', '<br>')}</div>`
84
+ //replaceAll("\r\n","<br>")
85
+ let attributeDate = ''
86
+ if (obj.hasOwnProperty.attributeData) {
87
+ for (let key in obj.attributeData) {
88
+ attributeDate += ` data-${key}="${obj.attributeData[key]}" `
89
+ }
90
+ }
91
+ let hasInputGroup = false
92
+ let inputGroupLeft = '',
93
+ inputGroupRight = '',
94
+ inputGroupDivLeft = ''
95
+ if (attributes.hasOwnProperty('hasInputGroup') && attributes.hasInputGroup) {
96
+ hasInputGroup = true
97
+ prepend = `<div class="input-group mb-3">`
98
+ append = `</div>`
99
+ if (attributes.hasOwnProperty('inputGroupLeft') && attributes.inputGroupLeft) {
100
+ inputGroupLeft = `<span class="input-group-text">${attributes.inputGroupLeft}</span>`
101
+ }
102
+ if (attributes.hasOwnProperty('inputGroupRight') && attributes.inputGroupRight) {
103
+ inputGroupRight = `<span class="input-group-text">${attributes.inputGroupRight}</span>`
104
+ }
105
+ }
106
+ let displayForm = ''
107
+ let readonly = obj.readonly ? `readonly` : ``
108
+ let boxyclass = '',
109
+ checked = '',
110
+ selects = ''
111
+ switch (type) {
112
+ case 'text':
113
+ displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" ${disabled} ${readonly} autofocus="" ${tabindex} ${additional_attributes} type="${type}" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${style} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
114
+ break
115
+
116
+ case 'checkbox':
117
+ checked = value == 1 ? 'checked' : ''
118
+ displayForm = `${prepend}<input autocomplete="off" autofocus="" ${tabindex} ${disabled} ${readonly} ${additional_attributes} ${style} type="checkbox" class="form-check-input ${obj.class}" ${id} ${name} ${checked} ${htmlOptions}>${information}${append}`
119
+ break
120
+
121
+ case 'tags':
122
+ classview = ` class="form-control tags ${obj.class ? obj.class : ''} " `
123
+ let datahtml = ''
124
+ if (value) {
125
+ let dataValue = []
126
+ if (typeof value == 'string') {
127
+ dataValue = JSON.parse(value) || []
128
+ } else {
129
+ dataValue = value || []
130
+ }
131
+ dataValue.forEach(function (item) {
132
+ datahtml += `<option value="${item}" selected="selected">${item}</option>`
133
+ })
134
+ }
135
+ displayForm = `${prepend}<select ${classview} ${id} ${name} ${additional_attributes} ${placeholder} multiple data-allow-new="true">${datahtml}</select>${information}${append}`
136
+ break
137
+
138
+ case 'range':
139
+ let min = !obj.min ? 0 : obj.min
140
+ let max = !obj.max ? 100 : obj.max
141
+ displayForm = `${prepend}${inputGroupLeft}<input onmouseover="titlerange(this)" onchange="titlerange(this)" autocomplete="off" autofocus="" ${tabindex} type="${type}" class="form-range ${obj.class}" step="1" ${id} ${name} ${placeholder} ${style} ${required} value="${value}" data-t="${value}" min="${min}" max="${max}" ${htmlOptions}>${inputGroupRight}${information}${append}`
142
+ break
143
+
144
+ case 'hidden':
145
+ displayForm = `${prepend}<input autocomplete="off" autofocus="" ${tabindex} type="${type}" ${additional_attributes} ${style} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${append}`
146
+ break
147
+
148
+ case 'textarea':
149
+ displayForm = `${prepend}${inputGroupLeft}<textarea ${tabindex} ${disabled} class="form-control ${obj.class}" ${id} ${name} ${additional_attributes} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${value}</textarea>${inputGroupRight}${information}${append}`
150
+ break
151
+
152
+ case 'image':
153
+ boxyclass = value ? 'boxy' : ''
154
+ let stringvalue = value ? value.substring(13) : ''
155
+ let trashicon = stringvalue ? `<img class="tabler-icons icons-filter-danger" src="/assets/icons/trash-filled.svg" onclick="removeimage(this)">` : ''
156
+ displayForm = `${prepend}<input ${tabindex} type="file" accept="image/*" onchange="loadFile(this,'${obj.id}' )" data-width="${obj.width}" class="form-control ${obj.class || ''}" ${id} ${name} ${placeholder} value="${value}" ${htmlOptions}>
157
+ <div id="body${obj.id}" class="isfile" data-id="${obj.id}" data-table="${obj.routeName}" data-width="${obj.width}" data-name="${obj.title}" data-filename="${value}" data-required="${obj.required}"> <img class="mb-3" width="${obj.width}" id="file${obj.id}" /><br><a class="text-success" target="_blank" href="/uploads/${
158
+ obj.routeName
159
+ }/${value}"> ${stringvalue}</a> ${trashicon}</div>${append}`
160
+ break
161
+
162
+ case 'file':
163
+ boxyclass = value ? 'boxy' : ''
164
+ let stringvaluefile = value ? value.substring(13) : ''
165
+ let trashiconfile = stringvaluefile ? `<img class="tabler-icons icons-filter-danger" src="/assets/icons/trash-filled.svg" onclick="removeimage(this)">` : ''
166
+ displayForm = `${prepend}<input ${tabindex} type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint,text/plain, application/pdf,.css,.js,.jpg,.png,.gif" onchange="loadFile(this,'${obj.id}' )" class="form-control ${
167
+ obj.class || ''
168
+ }" ${id} ${name} ${placeholder} value="${value}" ${htmlOptions}>
169
+ <div id="body${obj.id}" class="isfile" data-id="${obj.id}" data-name="${obj.title}" data-table="${obj.routeName}" data-filename="${value}" data-required="${obj.required}"> <img class="mb-3" id="file${obj.id}" /><a class="text-success" target="_blank" href="/uploads/${
170
+ obj.routeName
171
+ }/${value}"> ${stringvaluefile}</a>${trashiconfile}</div>${information}${append}`
172
+ break
173
+
174
+ case 'email':
175
+ displayForm = `${prepend}<input autocomplete="off" autofocus="" ${readonly} ${disabled} ${additional_attributes} ${tabindex} ${style} type="email" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${information}${append}`
176
+ break
177
+
178
+ case 'number':
179
+ displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="text" class="form-control number ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
180
+ break
181
+
182
+ case 'integer':
183
+ displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="number" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
184
+ break
185
+
186
+ case 'datepicker':
187
+ displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="text" class="form-control datepicker ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
188
+ break
189
+
190
+ case 'datetimepicker':
191
+ displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} type="text" ${style} class="form-control datetimepicker ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
192
+ break
193
+
194
+ case 'password':
195
+ displayForm = `${prepend}${inputGroupLeft}<input autocomplete="off" autofocus="" ${disabled} ${readonly} ${additional_attributes} ${tabindex} ${style} type="password" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" ${htmlOptions}><span toggle="#password" class="bx bi-eye field-icon toggle-password"></span>${inputGroupRight}${information}${append}`
196
+ break
197
+
198
+ case 'switch':
199
+ checked = value == 1 ? ' checked ' : ''
200
+ displayForm = `${prepend}<p><input ${tabindex} type="checkbox" class="form-control ${obj.class}" ${readonly} ${style} ${id} ${additional_attributes} ${name} ${checked} ></p>${information}${append}`
201
+ break
202
+
203
+ case 'lexical':
204
+ displayForm = `${prepend}<div ${id}>${information}${append}`
205
+ break
206
+
207
+ case 'checkbox':
208
+ checked = value == 1 ? ' checked ' : ''
209
+ displayForm = `${prepend}<input ${tabindex} type="${type}" class="form-control ${obj.class}" ${readonly} ${style} ${id} ${additional_attributes} ${name} ${checked} >${information}${append}`
210
+ break
211
+
212
+ case 'dropdown_checkbox':
213
+ let checkboxes = ''
214
+ let val = []
215
+ if (typeof value == 'object') {
216
+ val = value
217
+ } else if (typeof value == 'string') {
218
+ if (value) {
219
+ val = JSON.parse(value)
220
+ }
221
+ }
222
+ data.forEach(function (item) {
223
+ const checked = Util.in_array(item, val) ? ' checked ' : ''
224
+ checkboxes += `<div class="checkbox">
225
+ <label class="">
226
+ <input type="checkbox" name="${obj.name}[${item}]" ${checked} value="${item}">
227
+ ${item}
228
+ </label>
229
+ </div>`
230
+ })
231
+ displayForm = `${prepend}<div class="form-check">${checkboxes}</div>${information}${append}`
232
+ break
233
+
234
+ case 'select':
235
+ var please_select = obj.please_select
236
+ if (please_select != undefined) {
237
+ if (please_select != '') {
238
+ selects += `<option value="">${please_select}</option>`
239
+ }
240
+ }
241
+ if (obj.hasOwnProperty('array')) {
242
+ var items = obj.array || []
243
+ if (items.length) {
244
+ items.forEach(function (item) {
245
+ if (item.label) {
246
+ const selected = item.value == value ? ' selected ' : ''
247
+ selects += `<option value="${item.value}" ${selected}>${item.label}</option>`
248
+ }
249
+ })
250
+ } else {
251
+ if (Array.isArray(data)) {
252
+ data.map((item) => {
253
+ if (item.zname) {
254
+ var selected = item.id == value ? ' selected ' : ''
255
+ selects += `<option value="${item.id}" ${selected}>${item.zname}</option>`
256
+ }
257
+ })
258
+ } else {
259
+ for (var keys in data) {
260
+ if (data[keys]) {
261
+ var selected = keys == value ? ' selected ' : ''
262
+ selects += `<option value="${keys}" ${selected}>${data[keys]}</option>`
263
+ }
264
+ }
265
+ }
266
+ }
267
+ } else {
268
+ if (Array.isArray(data)) {
269
+ data.map((item) => {
270
+ if (item.zname) {
271
+ const selected = item.id == value ? ' selected ' : ''
272
+ selects += `<option value="${item.id}" ${selected}>${item.zname}</option>`
273
+ }
274
+ })
275
+ } else {
276
+ for (let keys in data) {
277
+ if (data[keys]) {
278
+ let selected = keys == value ? ' selected ' : ''
279
+ selects += `<option value="${keys}" ${selected}>${data[keys]}</option>`
280
+ }
281
+ }
282
+ }
283
+ }
284
+ if (form_css == 'material_design') {
285
+ classview = Form.addProperty('class', ['selectpicker', obj.class])
286
+ }
287
+ displayForm = `${prepend}<select ${tabindex} ${style} ${additional_attributes} ${disabled} ${readonly} class="form-control form-select ${obj.class}" ${id} ${name} ${placeholder} ${required} ${htmlOptions} >${selects}</select>${information}${append}`
288
+ break
289
+
290
+ case 'radio':
291
+ let radios = ''
292
+ let arr = obj.array || []
293
+ arr.map((item, index) => {
294
+ //var selected = item.value == value ? ' selected ' : '';
295
+ const checked = item.value == value ? ' checked ' : ''
296
+ radios += `<div class="form-check">
297
+ <input class="form-check-input ${obj.class}" type="radio" name="${obj.name}" ${additional_attributes} value="${item.value}" id="${obj.id}${index}" ${checked}>
298
+ <label class="form-check-label" for="${obj.id}${index}">
299
+ ${item.label}
300
+ </label>
301
+ </div>`
302
+ })
303
+ displayForm = `${prepend} ${radios} ${information}${append}`
304
+ break
305
+
306
+ case 'select_user':
307
+ selects = ''
308
+ data.map((item) => {
309
+ const selected = item.value == value ? ' selected ' : ''
310
+ selects += `<option value="${item.id}" ${selected}>${item.fullname}</option>`
311
+ })
312
+
313
+ if (form_css == 'material_design') {
314
+ classview = Form.addProperty('class', ['selectpicker', obj.class])
315
+ }
316
+ displayForm = `${prepend}<select ${tabindex} class="form-control form-select ${obj.class}" ${id} ${name} ${placeholder} ${required} ${htmlOptions} >${selects}</select>${information}${append}`
317
+ break
318
+
319
+ case 'chain':
320
+ selects = ''
321
+ // for array item.value and item.text
322
+ // proptery is value and text
323
+ data.map((item) => {
324
+ var selected = item.id == value ? ' selected ' : ''
325
+ selects += `<option value="${item.id}" ${selected}>${item.zname}</option>`
326
+ })
327
+ if (form_css == 'material_design') {
328
+ classview = Form.addProperty('class', ['selectpicker', obj.class])
329
+ }
330
+ displayForm = `${prepend}<select ${tabindex} class="form-control form-select ${obj.class}" ${id} ${name} ${placeholder} ${required} ${htmlOptions} >${selects}</select>${information}${append}`
331
+ break
332
+
333
+ case 'multi':
334
+ selects = ''
335
+ if (data) {
336
+ data.map((item) => {
337
+ selects += `<option value="${item.id}">${item.zname}</option>`
338
+ })
339
+ }
340
+
341
+ var spanmulti = ''
342
+ if (value) {
343
+ let arr = []
344
+ arr = typeof value == 'string' ? JSON.parse(value) : value
345
+ if (Array.isArray(arr)) {
346
+ arr.forEach(function (item, index) {
347
+ spanmulti += `<span class='span${obj.id}'>${index + 1}. <input type='hidden' name='${obj.name}[]' value='${item}' />${obj.multi[item]}<img class='tabler-icons icons-filter-danger pull-right' src='/assets/icons/trash-filled.svg' onclick='$(this).closest("span").remove();' title='${LANGUAGE['delete']}' /><br></span>`
348
+ })
349
+ }
350
+ }
351
+ if (form_css == 'material_design') {
352
+ classview = Form.addProperty('class', ['selectpicker', obj.class])
353
+ }
354
+
355
+ let g = `<div class="input-group ">
356
+ <span class="input-group-text" id="dropdownadd${id}" class="dropdownadd" data-id="${id}" style="cursor: pointer" title="Add Data">+</span>
357
+ </div>
358
+ <div id="dropdownbox${id}" class="boxy">
359
+ <span class="span${id}">
360
+ </span>
361
+ </div>`
362
+ return `<div class="input-group">
363
+ <select ${tabindex} class="form-control ${obj.class} dropdown-multi" name='${obj.name}' ${id} ${placeholder} ${htmlOptions} >${selects}</select>
364
+ <span id="dropdownadd${obj.id}" class="input-group-text dropdownadd" data-id="${obj.id}" style="cursor: pointer;" title=" ${LANGUAGE['form_add_data']} ">+</span>
365
+ </div>
366
+ <div id="dropdownbox${obj.id}" class="boxy mb-3">${spanmulti}</div>`
367
+ break
368
+
369
+ case 'typeahead':
370
+ let typeahead_value = Util.replaceAll(obj.typeaheadvalue, '"', `'`)
371
+ displayForm = `${prepend}<div class="input-group">
372
+ <input ${tabindex} type="text" class="form-control ${obj.class}" id="${obj.id}Typeahead" autocomplete="off" data-provide="typeahead" id="${obj.id}Typeahead" placeholder="Please type a word" value="${typeahead_value}" >
373
+ <input type="hidden" ${id} ${name} ${placeholder} ${classview} ${required} value="${value}">
374
+ <span id="${obj.id}Clear" class="input-group-addon input-group-text dropdownadd" title="Clear" style="cursor: pointer;" title=" Add Data "><img src="/assets/icons/ban.svg" class="icons-bg-black" ></span>
375
+ </div>${information}${append}`
376
+ break
377
+
378
+ case 'table':
379
+ let html = ''
380
+ /*console.log(`table : ${JSON.stringify(obj.data)}`)
381
+ console.log(JSON.stringify(obj.data))
382
+ console.log(JSON.stringify(obj.properties));*/
383
+ for (let key in obj.data) {
384
+ if (obj.properties[key].hidden) {
385
+ html += `<th></th>`
386
+ } else {
387
+ html += `<th>${obj.data[key]}</th>`
388
+ }
389
+ }
390
+ let btnAdd = ''
391
+ if (!obj.isAddButton && !obj.viewOnly) {
392
+ btnAdd = `<th class="float-end"><img id="add${obj.id}" src="/assets/icons/plus.svg" class="icons-bg-white boxy-small btn-plus" ></th>`
393
+ }
394
+ obj.btnAdd = btnAdd
395
+ obj.html = html
396
+ obj.title = title
397
+ obj.table = table
398
+ obj.value = value
399
+ let datavalue = ''
400
+ if (obj.value) {
401
+ datavalue = JSON.stringify(obj.value)
402
+ datavalue = Util.replaceAll(datavalue, "'", '`')
403
+ }
404
+ obj.prepend = prepend
405
+ obj.body = `<div class="table-responsive">
406
+ <table id="table${obj.id}" class="table table-hover table-sm">
407
+ <thead>
408
+ <tr>
409
+ ${html}
410
+ ${obj.btnAdd}
411
+ </tr>
412
+ </thead>
413
+ <tbody id="body-${obj.id}" data-value='${datavalue}'>${obj.bodyTable}</tbody>
414
+ </table></div>`
415
+ displayForm = Form.card(frameworkcss, obj)
416
+ break
417
+
418
+ case 'multi_line_editor':
419
+ value = obj.value ? obj.value : {}
420
+ let description = obj.description || ''
421
+ for (var key in obj.fields) {
422
+ let val = !value[key] ? obj.fields[key] : value[key]
423
+ description = Util.replaceAll(description, `[[[${key}]]]`, `<span class="text-danger text-toggle" id="a_${key}" data-id="${key}" style="text-decoration: underline; cursor: pointer">${val}</span> <input type="hidden" name="${obj.name}[${key}]" class="editor-value" id="${key}" data-id="${key}" value="${val}" >`)
424
+ }
425
+ displayForm = `${prepend}<div class="boxy">${description}</div>${information}${append}`
426
+ break
427
+
428
+ case 'ide_editor':
429
+ displayForm = `<div class="ide_editor" id="editor_${obj.id}"></div>`
430
+ displayForm += `<textarea hidden ${classview} ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4"></textarea>${information}${append}`
431
+ break
432
+
433
+ case 'json':
434
+ displayForm += `<textarea ${additional_attributes} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${JSON.stringify(obj.value)}</textarea>${information}${append}`
435
+ break
436
+
437
+ case 'json_array':
438
+ displayForm += `<textarea ${additional_attributes} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${JSON.stringify(obj.value)}</textarea>${information}${append}`
439
+ break
440
+
441
+ case 'dragdrop':
442
+ //dataObject
443
+ let leftButtons = ``
444
+ let rightButtons = ``
445
+ let all = Object.keys(obj.dataObject)
446
+ all.map((item, index) => {
447
+ if (!value.includes(item)) {
448
+ rightButtons += `<li><button class="btn btn-danger boxy" type="button">${obj.dataObject[item]}<input type="hidden" name='trashx' value="${item}"></button></li>`
449
+ }
450
+ })
451
+ value = value || []
452
+ value.map((item, index) => {
453
+ leftButtons += `<li><button class="btn btn-primary boxy" type="button">${obj.dataObject[item]}<input type="hidden" name='${obj.name}[]' value="${item}"></button></li>`
454
+ })
455
+
456
+ displayForm += `<div id="dragdrop_${obj.id}" class="row contentfields">
457
+ <div class="col-md-6">
458
+ <h5>${obj.attributes.left}</h5>
459
+ <ol class="mydragable${obj.id} divboxlittle" data-type="left" data-name="${obj.name}[]">${leftButtons}</ol>
460
+ </div>
461
+ <div class="col-md-6">
462
+ <h5>${obj.attributes.right}</h5>
463
+ <ol class="mydragable${obj.id} divboxlittle" data-type="right" data-name="trashx">
464
+ ${rightButtons}
465
+ </ol>
466
+ </div>
467
+ </div>`
468
+ break
469
+
470
+ case 'array':
471
+ displayForm += `<textarea ${additional_attributes} class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${readonly} ${style} ${htmlOptions} rows="4">${JSON.stringify(obj.value)}</textarea>${information}${append}`
472
+ break
473
+
474
+ case 'virtual':
475
+ displayForm = `${prepend}<input ${additional_attributes} autocomplete="off" autofocus="" ${tabindex} ${style} type="text" ${classview} readonly ${id} ${placeholder} ${required} value="${value}" ${htmlOptions}>${information}${append}`
476
+ break
477
+
478
+ //additionals for form view in view
479
+ case 'plaintext':
480
+ displayForm = `<span class="">${obj.value || ''}</span>`
481
+ break
482
+
483
+ case 'div':
484
+ displayForm = `<div id="${obj.id}" class="${obj.class}">${obj.value}</div>`
485
+ break
486
+
487
+ case 'data_table':
488
+ displayForm = obj.html
489
+ break
490
+
491
+ case 'location':
492
+ displayForm = `${prepend}<input type="text" class="form-control ${obj.class}" id="search_map_location" placeholder="type a place" ${required} value="" ${htmlOptions}>${information}${append}
493
+ <textarea ${id} ${name} style="display: none" ${readonly} rows="2">${JSON.stringify(obj.value)}</textarea>
494
+ <div id="map_${obj.id}" style="background-color:#C3C3C3;width: 100%;height: ${obj.height}px"></div>`
495
+ break
496
+
497
+ case 'dropzone':
498
+ displayForm = `${prepend}<div ${tabindex} ${style} type="text" ${classview} ${id} ${htmlOptions}><label for="files" class="dropzone-container">
499
+ <div class="dz-message" data-dz-message><div class="file-icon"><span class="icon-small icons-primary"><img class="icons-bg-white icon-image-large" src="/assets/icons/file-plus.svg"></span></div>
500
+ <div class="text-center pt-3 px-5">
501
+ <p class="w-80 h5 text-dark fw-bold">Drag your documents, photos or videos here to start uploading.</p>
502
+ </div></div>
503
+ </label></div>${information}${append}`
504
+ break
505
+
506
+ case 'dropzoneview':
507
+ let countFiles = obj.value && obj.value.length ? obj.value.length + ' Files' : ''
508
+ let bodydropzoneview =
509
+ countFiles == '' ? '' : `<div class="card-header">${countFiles} <div class="float-end"><span class="icon-small icons-light" title="Download"><img onclick="location.href= '/zdownloads-dropzone/${obj.routeName}/${obj.key}/${obj.dataId}'" class="icons-bg-black gridview icon-image" src="/assets/icons/download.svg"></span></div> </div>`
510
+ displayForm = `<div class="card">
511
+ ${bodydropzoneview}
512
+ <div class="card-body">`
513
+ if (obj.value && obj.value.length > 0) {
514
+ obj.value.map((item) => {
515
+ let extFile = Util.fileExtension(item)
516
+ let filename = `/uploads/${obj.table}/${obj.key}/${item}`
517
+ if (extFile.type == 'image') {
518
+ displayForm += `<img src="${filename}" class="boxy zoom mx-2 my-2" width="200px">`
519
+ } else {
520
+ displayForm += '<br>' + Util.fileView(`/uploads/${obj.table}/${obj.key}/`, item, { withIcon: true }) + '<br>'
521
+ }
522
+ })
523
+ }
524
+ displayForm += `</div></div>`
525
+
526
+ break
527
+ default:
528
+ displayForm = `${prepend}${inputGroupLeft}<input ${disabled} autocomplete="nope" autofocus="" ${readonly} ${tabindex} type="${type}" class="form-control ${obj.class}" ${id} ${name} ${placeholder} ${required} value="${value}" data-t="${value}" ${htmlOptions}>${inputGroupRight}${information}${append}`
529
+ break
530
+ }
531
+
532
+ return displayForm
533
+ }
534
+
535
+ Form.group = (name, label, field) => {
536
+ return `<div class="form-group div${name} mb-3">${label}${field}</div>`
537
+ }
538
+
539
+ Form.button = (optionsExtends = {}) => {
540
+ let options = Form.options.button
541
+ let htmlOptions = ''
542
+ for (let key in optionsExtends) {
543
+ let val = optionsExtends[key]
544
+ val = Util.replaceAll(val, '"', '')
545
+ if (options.hasOwnProperty(key)) {
546
+ options[key] = optionsExtends[key]
547
+ } else {
548
+ htmlOptions += ` ${key}=${val} `
549
+ }
550
+ }
551
+ return `<button id="${options.id}" type="${options.type}" class="${options.class}" ${htmlOptions}>${options.label}</button>`
552
+ }
553
+
554
+ Form.buttonGroup = (buttons = []) => {
555
+ let html = `<div class="btn-group" role="group" aria-label="...">`
556
+ html += buttons.join(' ')
557
+ html += `</div>`
558
+ return html
559
+ }
560
+
561
+ Form.submit = (optionsExtends = {}) => {
562
+ let options = {
563
+ id: 'form-submit',
564
+ type: 'submit',
565
+ class: 'btn btn btn-success boxy image-button ',
566
+ label: `<img src="/assets/icons/send.svg" class="icons-bg-white" > <span>${LANGUAGE['submit']}</span>`,
567
+ }
568
+ let settings = { ...options, ...optionsExtends }
569
+ return Form.button(settings)
570
+ }
571
+
572
+ Form.pullRight = (frameworkcss) => {
573
+ if (frameworkcss == 'bootstrap3') {
574
+ return 'pull-right'
575
+ } else if (frameworkcss == 'bootstrap4') {
576
+ return 'float-right'
577
+ } else {
578
+ return 'float-end'
579
+ }
580
+ }
581
+
582
+ Form.breadcrumb = (type, arr) => {
583
+ let html = `<nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E&#34;);" aria-label="breadcrumb"><ol class="breadcrumb float-end">`
584
+ arr.map((item) => {
585
+ if (item.active == true) {
586
+ html += `<li class="breadcrumb-item active" aria-current="page">${item.text}</li>`
587
+ } else {
588
+ html += `<li class="breadcrumb-item"><a href="${item.href}">${item.text}</a></li>`
589
+ }
590
+ })
591
+ html += `</ol></nav>`
592
+ return html
593
+ }
594
+
595
+ Form.breadcrumbs = (arr) => {
596
+ let html = `<nav style="--bs-breadcrumb-divider: url(&#34;data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8'%3E%3Cpath d='M2.5 0L1 1.5 3.5 4 1 6.5 2.5 8l4-4-4-4z' fill='currentColor'/%3E%3C/svg%3E&#34;);" aria-label="breadcrumb"><ol class="breadcrumb float-end">`
597
+ arr.map((item) => {
598
+ if (item.active == true) {
599
+ html += `<li class="breadcrumb-item active" aria-current="page">${item.text}</li>`
600
+ } else {
601
+ html += `<li class="breadcrumb-item"><a href="${item.href}">${item.text}</a></li>`
602
+ }
603
+ })
604
+ html += `</ol></nav>`
605
+ return html
606
+ }
607
+
608
+ Form.breadcrumbIndex = () => {
609
+ return Form.breadcrumbs([
610
+ { text: LANGUAGE['home'], href: '/dashboard' },
611
+ { text: LANGUAGE['grid_list'], active: true },
612
+ ])
613
+ }
614
+
615
+ Form.breadcrumbCreate = (routeName) => {
616
+ return Form.breadcrumbs([
617
+ { text: LANGUAGE['home'], href: '/dashboard' },
618
+ { text: LANGUAGE['grid_list'], href: '/' + routeName },
619
+ { text: LANGUAGE['create'], active: true },
620
+ ])
621
+ }
622
+
623
+ Form.breadcrumbUpdate = (routeName, id) => {
624
+ return Form.breadcrumbs([
625
+ { text: LANGUAGE['home'], href: '/dashboard' },
626
+ { text: LANGUAGE['grid_list'], href: '/' + routeName },
627
+ { text: LANGUAGE['create'], href: '/' + routeName + '/create' },
628
+ { text: LANGUAGE['view'], href: '/' + routeName + '/view/' + id },
629
+ { text: LANGUAGE['update'], active: true },
630
+ ])
631
+ }
632
+
633
+ Form.breadcrumbView = (routeName) => {
634
+ return Form.breadcrumbs([
635
+ { text: LANGUAGE['home'], href: '/dashboard' },
636
+ { text: LANGUAGE['grid_list'], href: '/' + routeName },
637
+ { text: LANGUAGE['view'], active: true },
638
+ ])
639
+ }
640
+
641
+ Form.breadcrumbImport = (routeName) => {
642
+ return Form.breadcrumbs([
643
+ { text: LANGUAGE['home'], href: '/dashboard' },
644
+ { text: LANGUAGE['grid_list'], href: '/' + routeName },
645
+ { text: LANGUAGE['create'], href: '/' + routeName + '/create' },
646
+ { text: LANGUAGE['form_import'], active: true },
647
+ ])
648
+ }
649
+
650
+ Form.breadcrumbApproval = (routeName, id) => {
651
+ return Form.breadcrumbs([
652
+ { text: LANGUAGE['home'], href: '/dashboard' },
653
+ { text: LANGUAGE['grid_list'], href: '/' + routeName },
654
+ { text: LANGUAGE['update'], href: '/' + routeName + '/update/' + id },
655
+ { text: LANGUAGE['create'], href: '/' + routeName + '/create' },
656
+ { text: 'Approval', active: true },
657
+ ])
658
+ }
659
+
660
+ Form.grid = (type, obj) => {
661
+ return gridBootstrap5(obj)
662
+ }
663
+
664
+ /*
665
+ tab property
666
+ label,active,content,headerOptions
667
+ */
668
+ Form.tab = (type, obj) => {
669
+ return tabBootstrap5(obj)
670
+ }
671
+
672
+ Form.card = (type, obj) => {
673
+ return card45(obj)
674
+ }
675
+
676
+ //card 4 & 5 bootstrap
677
+ const card45 = (obj) => {
678
+ let html = obj.prepend
679
+ let objHeader = obj.headerOptions || {}
680
+ let headerOptions = obj.headerOptions ? addProperties(obj.headerOptions, { class: 'card' }) : addProperties({ class: 'card' })
681
+ let img = obj.img ? `<img ${addProperties(obj.img)} >` : ''
682
+ let title = `<div class="card-header"><h5 class="card-title">${obj.title}</h5></div>`
683
+ let footer = (obj.footer = obj.footer ? `<div class="card-footer">${obj.footer}</div>` : ``)
684
+ let append = !obj.append ? '' : obj.append
685
+ html += `<div ${headerOptions}>
686
+ ${img}
687
+ ${title}
688
+ <div class="card-body">
689
+ ${obj.body}
690
+ </div>
691
+ ${footer}
692
+ </div>`
693
+
694
+ html += append
695
+ return html
696
+ }
697
+
698
+ const cardBootstrap5 = (obj) => {
699
+ return `${obj.prepend}<div class="card div${obj.id}">
700
+ <div class="card-content">
701
+ <div class="card-body">
702
+ <div class="card-title">${obj.title}</div>
703
+ <div class="table-responsive">
704
+ <table id="table${obj.id}" class="table">
705
+ <thead>
706
+ <tr>
707
+ ${obj.html}
708
+ ${obj.btnAdd}
709
+ </tr>
710
+ </thead>
711
+ <tbody id="body-${obj.id}" data-value='${obj.value}'>${obj.table}</tbody>
712
+ </table>
713
+ </div>
714
+ </div>
715
+ </div>
716
+ </div>`
717
+ }
718
+
719
+ const gridBootstrap5 = (obj) => {
720
+ let levels = obj.levels
721
+ let routeName = obj.routeName
722
+ let advanceSearch = !obj.advanceSearch ? '' : obj.advanceSearch
723
+ let createBtn = '',
724
+ exportBtn = '',
725
+ importBtn = '',
726
+ superBtn = '',
727
+ exportBtnGroup = '',
728
+ selectPagesize = ''
729
+ if (levels.create) {
730
+ createBtn = `<button type="button" id="create_btn" class="btn btn-success btn-xs"><i class="fa fa-plus white-icon"></i></button>`
731
+ }
732
+ if (levels.export) {
733
+ exportBtn = `<button type="button" id="backupExcel" class="btn btn-info btn-xs" title="${obj.LANGUAGE['download_excel']}"><i class="fas fa-file-excel"></i></button>`
734
+
735
+ exportBtnGroup = `<div class="btn-group" role="group">
736
+ <button id="dropdownExport" type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
737
+ ${obj.LANGUAGE['grid_export_data']}
738
+ </button>
739
+ <div class="dropdown-menu" aria-labelledby="dropdownExport">
740
+ <a class="dropdown-item export-xls" href="#"><i class="text-success fa fa-file-excel-o"></i> Excel </a>
741
+ <a class="dropdown-item export-pdf" href="#"><i class="text-danger fa fa-file-pdf-o"></i> PDF </a>
742
+ </div>
743
+ </div>`
744
+ }
745
+ if (levels.import) {
746
+ importBtn = `<button type="button" id="importExcel" class="btn btn-warning btn-xs" title="<%- LANGUAGE['data_import'] %>"><i class="fas fa-file-import"></i></button>`
747
+ }
748
+ selectPagesize = `<div class="dropdown-menu" aria-labelledby="dropdownPagination">`
749
+ let pageSize = obj.gridFilters.pageSize || 20
750
+
751
+ for (var i = 0; i < obj.paginationApp.length; i++) {
752
+ var actived = pageSize == obj.paginationApp[i] ? ' active ' : ''
753
+ selectPagesize += `<a data-value="${obj.paginationApp[i]}" class="dropdown-item pageSizeGrid ${actived}" id="pagination${obj.paginationApp[i]}" href="#" >${obj.paginationApp[i]}</a>`
754
+ }
755
+ selectPagesize += `</div>`
756
+
757
+ let toolbarDefault = `<div class="float">
758
+ <div class="btn-group float-end" role="group" aria-label="Button group with nested dropdown">
759
+ ${createBtn}
760
+ ${exportBtn}
761
+ ${importBtn}
762
+ <button type="button" class="btn btn-secondary btn-xs" title="${LANGUAGE['grid_personalize_labeling']}" data-bs-toggle="modal" data-bs-target="#grid-labels" ><i class="fa fa-font"></i></button>
763
+ <button type="button" class="btn btn-info btn-xs" title="${LANGUAGE['grid_personalize_setting']}" data-bs-toggle="modal" data-bs-target="#grid-modal"><i class="fa fa-cog"></i></button>
764
+ <button type="button" id="reloadgrid" class="btn btn-default btn-xs" title="${LANGUAGE['grid_refresh']}"><i class="fas fa-redo"></i></button>
765
+ <div class="btn-group" role="group">
766
+ <button id="dropdownPagination" type="button" class="btn btn-info dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
767
+ Pagination ${pageSize}
768
+ </button>
769
+ ${selectPagesize}
770
+ </div>
771
+
772
+ <div class="btn-group" role="group">
773
+ <button id="dropdownExport" type="button" class="btn btn-secondary dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
774
+ ${obj.LANGUAGE['grid_export_data']}
775
+ </button>
776
+ <div class="dropdown-menu" aria-labelledby="dropdownExport">
777
+ <a class="dropdown-item export-xls" href="#"><i class="text-success fa fa-file-excel-o"></i> Excel </a>
778
+ <a class="dropdown-item export-pdf" href="#"><i class="text-danger fa fa-file-pdf-o"></i> PDF </a>
779
+ </div>
780
+ </div>
781
+
782
+ </div></div>`
783
+ let toolbar = obj.toolbar ? obj.toolbar : toolbarDefault
784
+ let html = ''
785
+ html += `<div class="card">
786
+ <div class="card-body">
787
+ <div class="float-end">
788
+ <div class="summary"></div>
789
+ </div>
790
+ <div class="card-title"><i class="fa fa-book"></i> ${obj.header}</div>
791
+ <div class="row">
792
+ ${toolbar}
793
+ <div style="padding-top: 7px;"><a href="#" class="open_advancesearch"> Advance Search</a></div>
794
+ ${advanceSearch}
795
+ </div>
796
+
797
+ <input type="hidden" id="pageSize" value="${pageSize}">
798
+ <div class="table-responsive pt-3 row">
799
+ <div id="jsGrid" class="table-responsive"></div>
800
+ </div>
801
+ </div>
802
+ </div>`
803
+ return html
804
+ }
805
+
806
+ const tabBootstrap5 = (arr = []) => {
807
+ let html = ''
808
+ html += `<ul class="nav nav-tabs" id="myTab" role="tablist">${Util.newLine}`
809
+ arr.forEach(function (item, index) {
810
+ var active = '',
811
+ selected = 'false'
812
+ if (item.active) {
813
+ active = 'active'
814
+ selected = 'true'
815
+ }
816
+ html += `${Util.tab}
817
+ <li class="nav-item" role="presentation" >
818
+ <button class="nav-link ${active}" id="tab${index}" data-bs-toggle="tab" data-bs-target="#arr${index}" type="button" role="tab" aria-controls="arrtab${index}" aria-selected="true">${item.label}</button>
819
+ </li>${Util.newLine}`
820
+ })
821
+ html += `</ul>`
822
+ return {
823
+ html: html,
824
+ class: 'tab-pane fade',
825
+ active: 'show active',
826
+ }
827
+ }
828
+
829
+ Form.build = (obj) => {
830
+ let html = ''
831
+ let required = !obj.required ? '' : `<span class="required-mark">*</span>`
832
+ let labelOptions = !obj.labelOptions ? '' : obj.labelOptions
833
+ let relation = ''
834
+ //form float
835
+ let float = false
836
+ let inline = false
837
+ let attributes = Object.prototype.hasOwnProperty.call(obj, 'attributes') ? obj.attributes : {}
838
+ let view_only = Object.prototype.hasOwnProperty.call(obj, 'view_only') ? obj.view_only : false
839
+ if (!view_only) {
840
+ if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'name')) {
841
+ if (obj.attributes.name == 'relation' || obj.attributes.name == 'typeahead' || obj.attributes.name == 'dropdown_multi') {
842
+ relation = `<a target="_blank" href="/${obj.attributes.table}"> > </a>`
843
+ }
844
+ }
845
+ }
846
+
847
+ if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'float')) {
848
+ float = obj.attributes.float || false
849
+ }
850
+ if (attributes && Object.prototype.hasOwnProperty.call(attributes, 'inline')) {
851
+ inline = obj.attributes.inline || false
852
+ }
853
+
854
+ if (float) {
855
+ //obj.class = "nice-float"
856
+ if (obj.type == 'checkbox') {
857
+ html += `<div class="form-switch mx-auto div${obj.id} mb-3">${Form.field(obj)}<label class="form-check-label" for="">${obj.id} ${required}</label></div>`
858
+ } else {
859
+ html += `<div class="form-floating mx-auto mb-3 mt-3 div${obj.id} mb-3">${Form.field(obj)}<label for="${obj.id}">${obj.title} ${required} ${relation}</label></div>`
860
+ }
861
+ } else {
862
+ if (inline) {
863
+ if (obj.type == 'checkbox') {
864
+ html += ` <div class="mb-3 row"><label for="${obj.id}" class="col form-check-label">${obj.title} ${labelOptions} ${required} ${relation}</label><div class="col-8">${Form.field(obj)}</div></div>`
865
+ } else {
866
+ html += ` <div class="mb-3 row"><label for="${obj.id}" class="col col-form-label">${obj.title} ${labelOptions} ${required} ${relation}</label><div class="col-8">${Form.field(obj)}</div></div>`
867
+ }
868
+ } else {
869
+ if (obj.type == 'checkbox') {
870
+ html += `<div class="form-check div${obj.id} mb-3">${Form.field(obj)}<label class="form-check-label" for="${obj.id}">${obj.title} ${labelOptions} ${required}</label></div>`
871
+ } else {
872
+ html += `<div class="form-group div${obj.id} mb-3"><label for="${obj.id}">${obj.title} ${labelOptions} ${required} ${relation}</label>${Form.field(obj)}</div>`
873
+ }
874
+ }
875
+ }
876
+ return html
877
+ }
878
+
879
+ Form.modal = (obj, LANGUAGE = {}) => {
880
+ let attributeData = obj.attributeData,
881
+ visibles = obj.visibles || [],
882
+ invisibles = obj.invisibles || [],
883
+ visiblesHtml = '',
884
+ invisiblesHtml = '',
885
+ labelsHtml = ''
886
+ visibles.map((item) => {
887
+ visiblesHtml += `<li data-name="${item}" draggable="true" class="image-li" role="option" aria-grabbed="false"><img src="/assets/icons/eye.svg" class="icons-bg-black"> ${attributeData.labels[item]}</li>`
888
+ })
889
+ invisibles.map((item) => {
890
+ invisiblesHtml += `<li data-name="${item}" draggable="true" class="image-li" role="option" aria-grabbed="false"><img src="/assets/icons/eye-off.svg" class="icons-bg-black"> ${attributeData.labels[item]}</li>`
891
+ })
892
+ let no = 1
893
+ for (let key in attributeData.labels) {
894
+ labelsHtml += `<tr><td>${no}</td><td>${key}</td><td>${attributeData.labels[key]}</td><td><input maxlength="25" type="text" class="form-control" required name="${obj.routeName}[${key}]" value="${attributeData.labels[key]}"></td></tr>`
895
+ no++
896
+ }
897
+ const modalFields = Form.modalBuild({
898
+ id: 'grid-modal',
899
+ size: 'modal-xl',
900
+ header: `<h5 id="dynagrid-1-grid-modal-label" class="modal-title">
901
+ <i class="fa fa-cog"></i> ${LANGUAGE.grid_settings || 'Settings Grid'}
902
+ </h5>`,
903
+ body: `<div class="container">
904
+ <form id="form-grid" class="form-vertical kv-form-bs4" action="/${obj.routeName}/grid" method="post">
905
+ <input type="hidden" name="_csrf" value="">
906
+ <div class="dynagrid-column-label">
907
+ ${LANGUAGE.grid_configure || 'Configure Order and Display of Grid Columns'}
908
+ </div>
909
+ <div class="row">
910
+ <div class="col-sm-5">
911
+ <ul id="gridleft" class="sortable-visible sortable list kv-connected cursor-move gridsortable" aria-dropeffect="move">
912
+ <li data-name="" class="alert alert-info dynagrid-sortable-header disabled">
913
+ ${LANGUAGE.grid_visible || 'Visible Columns'}
914
+ </li>
915
+ ${visiblesHtml}
916
+ </ul>
917
+ </div>
918
+ <div class="col-sm-2 text-center">
919
+ <div class="dynagrid-sortable-separator"><i class="fas fa-arrows-alt-h"></i></div>
920
+ </div>
921
+ <div class="col-sm-5">
922
+ <ul id="gridright"
923
+ class="sortable-hidden sortable list kv-connected cursor-move gridsortable" aria-dropeffect="move">
924
+ <li data-name="" class="alert alert-info dynagrid-sortable-header disabled">${LANGUAGE.grid_invisible || 'Hidden / Fixed Columns'}
925
+ </li>
926
+ ${invisiblesHtml}
927
+ </ul>
928
+ </div>
929
+ </div>
930
+ <input type="hidden" id="serialize_left" name="serialize_left" value=''/>
931
+ <input type="hidden" id="serialize_right" name="serialize_right" value=''/>
932
+ </form>
933
+ </div> <!-- .dynagrid-config-form -->`,
934
+ footer: `<select id="zgrid_default_type" class="form-control select-sm" style="width:100px"><option value="1">Standart</option><option value="2">Fixed Header</option><option value="3">Footer Total</option><option value="4">No Wrap</option><option value="5">Fixed Header & No Wrap</option><option value="6">Footer Total & No Wrap</option><option value="7">Fixed Header & Footer & No Wrap</option></select>
935
+ <button type="reset" class="btn btn-default refresh gridreload image-button" title="Abort any changes and reset settings">
936
+ <img src="/assets/icons/refresh.svg" class="icons-bg-black"> ${LANGUAGE.reset || 'Reset'}
937
+ </button>
938
+ <button type="button" class="btn btn-primary grid-submit boxy image-button" title="Save grid settings">
939
+ <img src="/assets/icons/send.svg" class="icons-bg-white"> ${LANGUAGE.apply || 'Apply'}
940
+ </button>`,
941
+ })
942
+
943
+ let modalFields2 = `
944
+ <div class="modal fade" id="grid-lock" tabindex="-1" aria-labelledby="grid-lock-label" aria-hidden="true">
945
+ <div class="modal-dialog">
946
+ <div class="modal-content">
947
+ <div class="modal-header">
948
+ <h1 class="modal-title fs-5">Lock/Unlock</h1>
949
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
950
+ </div>
951
+ <div class="modal-body">
952
+ <button title="Lock" style="background-color: #DC4C64; color:white" class="btn btn-save-lock boxy-small dimens2x image-button" type="button"><img src="/assets/icons/lock.svg" class="icons-bg-white"> Lock</button>
953
+ <button title="Unlock" style="background-color: #14A44D; color:white" class="btn btn-save-unlock boxy-small dimens2x image-button" type="button"><img src="/assets/icons/lock-open.svg" class="icons-bg-white"> Unlock</button>
954
+ </div>
955
+ </div>
956
+ </div>
957
+ </div>`
958
+ let modalFields3 = `
959
+ <div class="modal fade" id="grid-approval" tabindex="-1" aria-labelledby="grid-approval-label" aria-hidden="true">
960
+ <div class="modal-dialog">
961
+ <div class="modal-content">
962
+ <div class="modal-header">
963
+ <h1 class="modal-title fs-5" >Approvals</h1>
964
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
965
+ </div>
966
+ <div class="modal-body" style="min-height: 150px">
967
+ <div class="row"><div class="col-md-12 modal-body-approval"></div></div>
968
+ </div>
969
+ </div>
970
+ </div>
971
+ </div>`
972
+ let modalFields4 = `
973
+ <div class="modal fade" id="grid-delete-all" tabindex="-1" aria-labelledby="grid-delete-all-label" aria-hidden="true">
974
+ <div class="modal-dialog">
975
+ <div class="modal-content">
976
+ <div class="modal-header">
977
+ <h1 class="modal-title fs-5">Delete selected data</h1>
978
+ <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
979
+ </div>
980
+ <div class="modal-body">
981
+ <button title="Delete All" style="background-color: #DC4C64; color:white" class="btn btn-save-delete-selected boxy-small dimens2x image-button" type="button"><img src="/assets/icons/http-delete.svg" class="icons-bg-white"> Delete selected data</button>
982
+ </div>
983
+ </div>
984
+ </div>
985
+ </div>`
986
+ try {
987
+ return modalFields + modalFields2 + modalFields3 + modalFields4
988
+ } catch (err) {
989
+ console.log(err)
990
+ }
991
+ }
992
+
993
+ Form.modalBuild = (obj) => {
994
+ let html = '<!-- Modal -->'
995
+ try {
996
+ const size = obj.size ? `${obj.size}` : ''
997
+ const id = obj.id ? `id="${obj.id}"` : ''
998
+ const headerOptions = Util.attributeOptions(obj.headerOptions || {}, { class: 'modal-header' })
999
+ const header = obj.header ? `<div ${headerOptions} >${obj.header}<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>` : ''
1000
+ const body = obj.body ? obj.body : ''
1001
+ const bodyOptions = Util.attributeOptions(obj.bodyOptions || {}, { class: 'modal-body' })
1002
+ const footerOptions = Util.attributeOptions(obj.footerOptions || {}, { class: 'modal-footer' })
1003
+ const footer = obj.footer ? `<div ${footerOptions} >${obj.footer}</div>` : ''
1004
+ html += `${Util.newLine}<div class="modal fade " ${id} role="dialog" tabindex="-1">
1005
+ <div class="modal-dialog ${size}">
1006
+ <div class="modal-content">
1007
+ ${header}
1008
+ <div ${bodyOptions}>${body}</div>
1009
+ ${footer}
1010
+ </div>
1011
+ </div>
1012
+ </div>`
1013
+ } catch (error) {
1014
+ console.log(error)
1015
+ }
1016
+ return html
1017
+ }
1018
+
1019
+ module.exports = Form