@agung_dhewe/webapps 1.1.2

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.
Files changed (130) hide show
  1. package/LICENSE +28 -0
  2. package/README.md +2 -0
  3. package/jsconfig.json +10 -0
  4. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.css +2 -0
  5. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +11 -0
  6. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +1 -0
  7. package/libs/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
  8. package/libs/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
  9. package/libs/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
  10. package/libs/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
  11. package/libs/fgta5js-dist/fonts/karla.css +142 -0
  12. package/libs/webmodule/module-edit.css +163 -0
  13. package/libs/webmodule/module-footer.css +22 -0
  14. package/libs/webmodule/module-list.css +25 -0
  15. package/libs/webmodule/module.css +52 -0
  16. package/libs/webmodule/module.js +195 -0
  17. package/libs/webmodule/pagehelper.mjs +45 -0
  18. package/modules/generator/appgen-components.mjs +142 -0
  19. package/modules/generator/appgen-icons.mjs +6 -0
  20. package/modules/generator/appgen-io.mjs +784 -0
  21. package/modules/generator/appgen-ui-search.mjs +173 -0
  22. package/modules/generator/appgen-ui-unique.mjs +153 -0
  23. package/modules/generator/appgen-ui.mjs +1181 -0
  24. package/modules/generator/generator-context.mjs +18 -0
  25. package/modules/generator/generator-designtemplate.html +1508 -0
  26. package/modules/generator/generator-ext.html +0 -0
  27. package/modules/generator/generator-ext.mjs +3 -0
  28. package/modules/generator/generator.css +642 -0
  29. package/modules/generator/generator.mjs +195 -0
  30. package/modules/generator/generator.png +0 -0
  31. package/modules/generator/generatorEdit.html +185 -0
  32. package/modules/generator/generatorEdit.mjs +238 -0
  33. package/modules/generator/generatorList.html +32 -0
  34. package/modules/generator/generatorList.mjs +243 -0
  35. package/modules/login/login.css +11 -0
  36. package/modules/login/login.html +12 -0
  37. package/modules/login/login.mjs +111 -0
  38. package/package.json +46 -0
  39. package/percobaan/simmpan-ke-minio.js +24 -0
  40. package/src/api.js +80 -0
  41. package/src/apis/generator.api.js +226 -0
  42. package/src/apis/login.api.js +109 -0
  43. package/src/bucket.js +24 -0
  44. package/src/context.js +26 -0
  45. package/src/datalog.sql +22 -0
  46. package/src/datarecords.js +0 -0
  47. package/src/db.js +61 -0
  48. package/src/generator/createApiExtenderModule.js +54 -0
  49. package/src/generator/createApiModule.js +218 -0
  50. package/src/generator/createIcon.js +62 -0
  51. package/src/generator/createInfoAboutExtender.js +42 -0
  52. package/src/generator/createInfoLogs.js +41 -0
  53. package/src/generator/createInfoRecordExtender.js +41 -0
  54. package/src/generator/createModuleContext.js +48 -0
  55. package/src/generator/createModuleDetilEditHtml.js +110 -0
  56. package/src/generator/createModuleDetilEditMjs.js +172 -0
  57. package/src/generator/createModuleDetilListHtml.js +146 -0
  58. package/src/generator/createModuleDetilListMjs.js +73 -0
  59. package/src/generator/createModuleEjs.js +51 -0
  60. package/src/generator/createModuleExtenderHtml.js +43 -0
  61. package/src/generator/createModuleExtenderMjs.js +43 -0
  62. package/src/generator/createModuleHeaderEditHtml.js +148 -0
  63. package/src/generator/createModuleHeaderEditMjs.js +197 -0
  64. package/src/generator/createModuleHeaderListHtml.js +144 -0
  65. package/src/generator/createModuleHeaderListMjs.js +67 -0
  66. package/src/generator/createModuleMjs.js +67 -0
  67. package/src/generator/createModuleRollup.js +42 -0
  68. package/src/generator/createProgramData.js +96 -0
  69. package/src/generator/createTable.js +156 -0
  70. package/src/generator/ddl.js +475 -0
  71. package/src/generator/helper.js +149 -0
  72. package/src/generator/templates/__rollup-module.ejs +90 -0
  73. package/src/generator/templates/api-extender-module.js.ejs +0 -0
  74. package/src/generator/templates/api-module.js.ejs +818 -0
  75. package/src/generator/templates/module-context.ejs +16 -0
  76. package/src/generator/templates/module-ext-about.ejs +1 -0
  77. package/src/generator/templates/module-ext-record.ejs +1 -0
  78. package/src/generator/templates/module-ext.html.ejs +3 -0
  79. package/src/generator/templates/module-ext.mjs.ejs +21 -0
  80. package/src/generator/templates/module-logs.ejs +14 -0
  81. package/src/generator/templates/module.ejs.ejs +48 -0
  82. package/src/generator/templates/module.mjs.ejs +256 -0
  83. package/src/generator/templates/moduleDetilEdit.html.ejs +34 -0
  84. package/src/generator/templates/moduleDetilEdit.mjs.ejs +792 -0
  85. package/src/generator/templates/moduleDetilList.html.ejs +26 -0
  86. package/src/generator/templates/moduleDetilList.mjs.ejs +319 -0
  87. package/src/generator/templates/moduleHeaderEdit.html.ejs +53 -0
  88. package/src/generator/templates/moduleHeaderEdit.mjs.ejs +807 -0
  89. package/src/generator/templates/moduleHeaderList.html.ejs +24 -0
  90. package/src/generator/templates/moduleHeaderList.mjs.ejs +308 -0
  91. package/src/generator/templates/sqlAddField.ejs +3 -0
  92. package/src/generator/templates/sqlAddForeignKey.ejs +12 -0
  93. package/src/generator/templates/sqlAddUniqueIndex.ejs +4 -0
  94. package/src/generator/templates/sqlCreateTable.ejs +9 -0
  95. package/src/generator/templates/sqlDropForeignKey.ejs +3 -0
  96. package/src/generator/templates/sqlDropUniqueIndex.ejs +4 -0
  97. package/src/generator/templates/sqlModifyField.ejs +6 -0
  98. package/src/generator/trygenerate.js +83 -0
  99. package/src/generator/worker.js +389 -0
  100. package/src/helper.js +82 -0
  101. package/src/logger.js +39 -0
  102. package/src/router.js +84 -0
  103. package/src/routers/defaultLoginApi.js +29 -0
  104. package/src/routers/defaultLoginAsset.js +18 -0
  105. package/src/routers/defaultLoginPage.js +36 -0
  106. package/src/routers/defaultRootIndex.js +16 -0
  107. package/src/routers/downloadHandler.js +51 -0
  108. package/src/routers/fileUploadApi.js +15 -0
  109. package/src/routers/generatorApi.js +30 -0
  110. package/src/routers/generatorAsset.js +18 -0
  111. package/src/routers/generatorPage.js +37 -0
  112. package/src/routers/handleError.js +43 -0
  113. package/src/routers/handleModuleNotfound.js +12 -0
  114. package/src/routers/moduleApi.js +34 -0
  115. package/src/routers/modulePage.js +102 -0
  116. package/src/sequencerdoc.js +311 -0
  117. package/src/sequencerline.js +214 -0
  118. package/src/session.js +57 -0
  119. package/src/startup.js +59 -0
  120. package/src/webapps.js +239 -0
  121. package/src/workermanager.js +83 -0
  122. package/templates/_lib_debug.ejs +11 -0
  123. package/templates/_lib_production.ejs +5 -0
  124. package/templates/application.page.ejs +143 -0
  125. package/templates/generator.page.ejs +131 -0
  126. package/templates/index.page.ejs +24 -0
  127. package/templates/login.page.ejs +102 -0
  128. package/templates/moduleError.ejs +16 -0
  129. package/templates/moduleNotfound.ejs +14 -0
  130. package/webapps.code-workspace +11 -0
@@ -0,0 +1,784 @@
1
+ import Context from './generator-context.mjs'
2
+ import Components from './appgen-components.mjs'
3
+
4
+ const btn = {}
5
+ const ATTR_ENTITYID = 'data-entity-id'
6
+ const ATTR_COMPNAME = 'data-component-name'
7
+ const ATTR_ROWUNIQUE = 'data-rowuniqueindex'
8
+ const ATTR_ROWSEARCH = 'data-rowsearch'
9
+
10
+
11
+ // const Context = {}
12
+
13
+ const isValidName = str => /^[_a-z0-9]+$/.test(str) ;
14
+
15
+ const timestamp = () => {
16
+ const now = new Date();
17
+ const YYYY = now.getFullYear();
18
+ const MM = String(now.getMonth() + 1).padStart(2, "0");
19
+ const DD = String(now.getDate()).padStart(2, "0");
20
+ const HH = String(now.getHours()).padStart(2, "0");
21
+ const mm = String(now.getMinutes()).padStart(2, "0");
22
+ const SS = String(now.getSeconds()).padStart(2, "0");
23
+ return `${YYYY}${MM}${DD}${HH}${mm}${SS}`;
24
+ }
25
+
26
+ export default class AppGenIO {
27
+ Setup(config) {
28
+ AppGenIO_Setup(this, config)
29
+ }
30
+
31
+
32
+ AutoSave() {
33
+ AppGenIO_AutoSave(this)
34
+ }
35
+
36
+ GetDataFromCache() {
37
+ return AppGenIO_GetDataFromCache(this)
38
+ }
39
+
40
+ ReadData(content) {
41
+ AppGenIO_ReadData(this, content)
42
+ }
43
+
44
+ // cek AppGenIO_Setup untuk ovveride fungsi2 di bawah
45
+ AddEntity(data) {} // ini nanti di ovveride saat setup
46
+ startDesign(entity_id) {}
47
+
48
+
49
+ #autoSavePaused = false
50
+ get autoSavePaused() { return this.#autoSavePaused }
51
+ pauseAutoSave(autoSavePaused) {
52
+ console.log(autoSavePaused? 'auto save paused' : 'auto save resume')
53
+ this.#autoSavePaused = autoSavePaused
54
+ }
55
+
56
+ async getCurrentData() {
57
+ const data = await AppGenIO_GetCurrentWorkData(this)
58
+ return data
59
+ }
60
+
61
+ async updateCache() {
62
+ var data = await AppGenIO_GetCurrentWorkData(self)
63
+ AppGenIO_updateCache(data)
64
+ }
65
+
66
+ async reset() {
67
+ await AppGenIO_Reset(this)
68
+ }
69
+
70
+ load(data) {
71
+ AppGenIO_Load(this, data)
72
+ }
73
+
74
+
75
+ addFunction(fnName, fn) {
76
+ Context[fnName] = fn
77
+ }
78
+
79
+ }
80
+
81
+
82
+
83
+
84
+ function getValueFrom(datafield, query, propertyname) {
85
+ var el = datafield.querySelector(query)
86
+ if (el==null) {
87
+ return null
88
+ }
89
+ if (el[propertyname]===undefined) {
90
+ return null
91
+ }
92
+ return el[propertyname]
93
+ }
94
+
95
+ function getCheckedFrom(datafield, query) {
96
+ var el = datafield.querySelector(query)
97
+ if (el==null) {
98
+ return false
99
+ }
100
+
101
+ return el.checked===true ? true : false
102
+ }
103
+
104
+ function setValueTo(value, datafield, query, propertyname) {
105
+ var el = datafield.querySelector(query)
106
+ if (el==null) {
107
+ return null
108
+ }
109
+ if (el[propertyname]===undefined) {
110
+ return null
111
+ }
112
+ el[propertyname] = value
113
+ }
114
+
115
+ function setCheckedTo(checked, datafield, query) {
116
+ var el = datafield.querySelector(query)
117
+ if (el==null) {
118
+ return false
119
+ }
120
+ el.checked = checked
121
+ }
122
+
123
+ function setSelectedTo(value, datafield, query) {
124
+ var el = datafield.querySelector(query)
125
+ if (el==null) {
126
+ return false
127
+ }
128
+
129
+ for (let option of el.options) {
130
+ if (option.value === value) {
131
+ option.selected = true;
132
+ break;
133
+ }
134
+ }
135
+
136
+ }
137
+
138
+
139
+
140
+ function AppGenIO_Setup(self, config) {
141
+ self.AddEntity = config.AddEntity
142
+ self.startDesign = config.startDesign
143
+ self.addComponentToDesigner = config.addComponentToDesigner
144
+ self.addAction = config.addAction
145
+
146
+
147
+ btn.save = document.getElementById('btnAppGenSave')
148
+ btn.save.addEventListener('click', async (evt)=>{
149
+
150
+ const data = await AppGenIO_GetCurrentWorkData(self)
151
+ const suggestedName = data.name
152
+ const handle = await window.showSaveFilePicker({
153
+ suggestedName,
154
+ types: [
155
+ {
156
+ description: "JSON File",
157
+ accept: { "application/json": [".json"] },
158
+ },
159
+ ],
160
+ });
161
+
162
+
163
+ const writable = await handle.createWritable();
164
+ await writable.write(JSON.stringify(data, null, 2)); // prettify JSON
165
+ await writable.close();
166
+
167
+ // AppGenIO_Save(self, evt)
168
+ })
169
+
170
+
171
+
172
+ btn.load = document.getElementById('btnAppGenLoad')
173
+ btn.load.addEventListener('click', (evt)=>{
174
+ const input = document.createElement("input");
175
+ input.type = "file";
176
+ input.accept = ".json"; // opsional: filter ekstensi
177
+ input.style.display = "none"; // tidak perlu ditambahkan ke dokumen
178
+
179
+ input.addEventListener("change", () => {
180
+ if (input.files.length > 0) {
181
+ const file = input.files[0]
182
+ if (!file) return;
183
+
184
+ const reader = new FileReader();
185
+ reader.onload = function (e) {
186
+ const content = e.target.result;
187
+ AppGenIO_ReadData(self, content)
188
+ };
189
+ reader.readAsText(file);
190
+ }
191
+ });
192
+
193
+ input.click(); // harus dalam content clikc user
194
+ })
195
+ }
196
+
197
+ function AppGenIO_GetDataFromCache(self) {
198
+ const stored = localStorage.getItem("appgendata"); // baca data dari local storage
199
+ return stored
200
+ }
201
+
202
+
203
+ function AppGenIO_updateCache(data) {
204
+ localStorage.setItem("appgendata", JSON.stringify(data));
205
+ console.log(`saved ${timestamp()}`)
206
+ }
207
+
208
+ function AppGenIO_AutoSave(self) {
209
+ // autosave ke local storage per 10 detik
210
+ const svr = setInterval(async ()=>{
211
+ try {
212
+ if (!self.autoSavePaused) {
213
+ var data = await AppGenIO_GetCurrentWorkData(self)
214
+ AppGenIO_updateCache(data)
215
+ }
216
+ // clearInterval(svr)
217
+ } catch (err) {
218
+ console.log(err.message)
219
+ }
220
+ }, 10000)
221
+ }
222
+
223
+ /*
224
+ async function AppGenIO_Save(self, evt) {
225
+ try {
226
+ var data = await AppGenIO_GetCurrentWorkData(self)
227
+
228
+
229
+ // coba save ke file
230
+ const pretty = JSON.stringify(data, null, 2); // indentasi 2 spasi
231
+ const blob = new Blob([pretty], { type: "application/json" });
232
+ const url = URL.createObjectURL(blob);
233
+
234
+ const a = document.createElement("a");
235
+ a.href = url;
236
+ a.download = `${data.name}.json`;
237
+
238
+ if (data.name!='' && data.name!=null) {
239
+ a.click();
240
+ }
241
+
242
+ URL.revokeObjectURL(url);
243
+
244
+ } catch (err) {
245
+ await $fgta5.MessageBox.error(err.message)
246
+ }
247
+
248
+ }
249
+ */
250
+
251
+
252
+ async function AppGenIO_GetCurrentWorkData(self) {
253
+ const PROG = {
254
+ id: '',
255
+ appname: '',
256
+ name: '',
257
+ directory: '',
258
+ title: '',
259
+ description: '',
260
+ icon: '',
261
+ primary_entity_id: '',
262
+ primary_entity_name: '',
263
+ actions: [],
264
+ entities: {},
265
+ uniques: {},
266
+ search: {},
267
+ }
268
+
269
+ try {
270
+ AppGenIO_GetDef(self, PROG)
271
+ AppGenIO_GetActions(self, PROG)
272
+ AppGenIO_GetEntities(self, PROG)
273
+
274
+ return PROG
275
+ } catch (err) {
276
+ throw err
277
+ }
278
+
279
+
280
+ }
281
+
282
+ function AppGenIO_GetDef(self, PROG) {
283
+ const obj_programid = document.getElementById('obj_programid')
284
+ const obj_appname = document.getElementById('obj_appname')
285
+ const obj_programname = document.getElementById('obj_programname')
286
+ const obj_programtitle = document.getElementById('obj_programtitle')
287
+ const obj_directory = document.getElementById('obj_directory')
288
+ const obj_programdescription = document.getElementById('obj_programdescription')
289
+ const obj_icon = document.getElementById('upload-icon')
290
+
291
+
292
+ PROG.id = obj_programid.value
293
+ PROG.appname = obj_appname.value.toLowerCase()
294
+ PROG.name = obj_programname.value.toLowerCase()
295
+ PROG.title = obj_programtitle.value
296
+ PROG.directory = obj_directory.value
297
+ PROG.description = obj_programdescription.value
298
+ PROG.icon = obj_icon.style.backgroundImage
299
+
300
+ }
301
+
302
+ function AppGenIO_GetActions(self, PROG) {
303
+ PROG.actions = []
304
+
305
+ const actionlist = document.getElementById('action-lists')
306
+ const trs = actionlist.querySelectorAll('tr')
307
+ for (let tr of trs) {
308
+ const elname = tr.querySelector('[name="action-name"]')
309
+ const eltitle = tr.querySelector('[name="action-title"]')
310
+
311
+ PROG.actions.push({
312
+ name: elname.innerHTML,
313
+ title: eltitle.innerHTML
314
+ })
315
+ }
316
+
317
+ }
318
+
319
+ function AppGenIO_GetEntities(self, PROG) {
320
+ const el = document.getElementById('data-entities')
321
+ const trs = el.querySelectorAll('tr')
322
+ for (var tr of trs) {
323
+ tr.classList.remove('field-error')
324
+ try {
325
+ var entity_id = tr.getAttribute('data-entity-id')
326
+ let entity = AppGenIO_GetEntityData(self, entity_id)
327
+
328
+ if (!isValidName(entity.name)) {
329
+ throw new Error(`entity name '${entity.name}' tidak valid`)
330
+ }
331
+
332
+ if (PROG.entities[entity.name]!==undefined) {
333
+ // sudah ada, entiti duplikasi
334
+ throw new Error(`entity ${entity.name} terduplikasi`)
335
+ }
336
+
337
+ PROG.entities[entity.name] = entity
338
+ if (entity.isheader) {
339
+ PROG.primary_entity_id = entity_id
340
+ PROG.primary_entity_name = entity.name
341
+ }
342
+ } catch (err) {
343
+ tr.classList.add('field-error')
344
+ throw err
345
+ }
346
+ }
347
+ }
348
+
349
+
350
+ function AppGenIO_GetEntityData(self, entity_id) {
351
+ var entity = {
352
+ id: entity_id
353
+ }
354
+
355
+ var de = document.getElementById('entities-design')
356
+ var editor = de.querySelector(`div[name="entity-editor"][${ATTR_ENTITYID}="${entity_id}"]`)
357
+ editor.entity_id = entity_id
358
+
359
+
360
+ // get data info
361
+ var elName = editor.querySelector('div[name="designer-info"] div[name="col_name"]')
362
+ var elTitle = editor.querySelector('div[name="designer-info"] div[name="col_title"]')
363
+ var elTable = editor.querySelector('div[name="designer-info"] div[name="col_table"]')
364
+ var elPK = editor.querySelector('div[name="designer-info"] div[name="col_pk"]')
365
+ var elInputDescr = editor.querySelector('div[name="designer-info"] input[name="table-descr"]')
366
+ var elChkRowAdd = editor.querySelector('div[name="designer-info"] input[name="allow-row-add"]')
367
+ var elChkRowRemove = editor.querySelector('div[name="designer-info"] input[name="allow-row-remove"]')
368
+
369
+ var elIdMethod = editor.querySelector('div[name="designer-info"] select[name="identifier-method"]')
370
+ var elIdfPrefix = editor.querySelector('div[name="designer-info"] input[name="identifier-prefix"]')
371
+ var elIdBlock = editor.querySelector('div[name="designer-info"] input[name="identifier-block"]')
372
+ var elIdLength = editor.querySelector('div[name="designer-info"] input[name="identifier-length"]')
373
+
374
+
375
+
376
+
377
+ entity.name = elName.innerHTML.toLowerCase()
378
+ entity.isheader = entity.name=='header' ? true : false;
379
+ entity.title = elTitle.innerHTML
380
+ entity.table = elTable.innerHTML.toLowerCase()
381
+ entity.pk = elPK.innerHTML.toLowerCase()
382
+ entity.descr = elInputDescr.value
383
+ entity.allowRowAdd = elChkRowAdd.checked ? true : false
384
+ entity.allowRowRemove = elChkRowRemove.checked ? true : false
385
+ entity.identifierMethod = elIdMethod.value
386
+ entity.identifierPrefix = elIdfPrefix.value
387
+ entity.identifierBlock = elIdBlock.value
388
+ entity.identifierLength = elIdLength.value
389
+
390
+
391
+ entity.Items = {}
392
+
393
+
394
+ // ambil data items
395
+ let elAllFields = editor.querySelectorAll('div[name="design-data-field"]')
396
+ for (let elfield of elAllFields) {
397
+ elfield.classList.remove('field-error')
398
+ }
399
+
400
+ for (let elfield of elAllFields) {
401
+ let field = AppGenIO_GetFieldData(self, elfield)
402
+ if (entity.Items[field.name]!==undefined) {
403
+ elfield.classList.add('field-error')
404
+ throw new Error(`fieldname '${field.name}' terduplikasi!`)
405
+ }
406
+ entity.Items[field.name] = field
407
+ }
408
+
409
+ // ambil data unique
410
+ entity.Uniques = AppGenIO_GetEntityUnique(self, editor)
411
+ entity.Search = AppGenIO_GetEntitySearch(self, editor)
412
+
413
+
414
+
415
+ return entity
416
+ }
417
+
418
+ function AppGenIO_GetEntityUnique(self, editor) {
419
+ const uniques = {}
420
+ const tbl = editor.querySelector('table[name="tbl-unique"]')
421
+ const trs = tbl.querySelectorAll(`tr[${ATTR_ROWUNIQUE}]`)
422
+ for (var tr of trs) {
423
+ const tdName = tr.querySelector('td[data-name="name"]')
424
+ const tdFields = tr.querySelector('td[data-name="fields"]')
425
+ const name = tdName.innerHTML
426
+ const fields = tdFields.innerHTML
427
+
428
+ uniques[name] = {name, fields}
429
+ }
430
+
431
+ return uniques
432
+ }
433
+
434
+ function AppGenIO_GetEntitySearch(self, editor) {
435
+ console.log('get entity search')
436
+
437
+ const search = {}
438
+ const tbl = editor.querySelector('table[name="tbl-search"]')
439
+ const trs = tbl.querySelectorAll(`tr[${ATTR_ROWSEARCH}]`)
440
+ for (var tr of trs) {
441
+ const tdName = tr.querySelector('td[data-name="name"]')
442
+ const tdLabel = tr.querySelector('td[data-name="label"]')
443
+ const tdFields = tr.querySelector('td[data-name="fields"]')
444
+ const name = tdName.innerHTML
445
+ const label = tdLabel.innerHTML
446
+ const fields = tdFields.innerHTML
447
+
448
+ search[name] = {name, label, fields}
449
+ }
450
+
451
+ return search
452
+ }
453
+
454
+
455
+
456
+ function AppGenIO_GetFieldData(self, el) {
457
+ const field = {}
458
+
459
+ field.component = el.getAttribute(ATTR_COMPNAME)
460
+ field.data_fieldname = getValueFrom(el, 'input[name="fieldname"]', 'value')
461
+ field.name = field.data_fieldname.toLowerCase()
462
+
463
+ // ambil type variable
464
+ var sel_datatyle = el.querySelector('select[name="datatype"]')
465
+ field.data_type = sel_datatyle.options[sel_datatyle.selectedIndex].value
466
+
467
+ field.data_length = getValueFrom(el, 'input[name="datalength"]', 'value') ?? 0
468
+ field.data_precision = getValueFrom(el, 'input[name="dataprecission"]', 'value') ?? 0
469
+
470
+ // allownull
471
+ field.data_allownull = getCheckedFrom(el, 'input[name="allownull"]')
472
+
473
+ // get defaul value
474
+ if (field.component=='Checkbox') {
475
+ var defaultChecked = getCheckedFrom(el, 'input[name="defaultvalue"]')
476
+ field.data_defaultvalue = defaultChecked ? 1 : 0
477
+ } else {
478
+ var txt_defaultvalue = el.querySelector('input[name="defaultvalue"]')
479
+ field.data_defaultvalue = txt_defaultvalue.value
480
+ }
481
+
482
+ // field description
483
+ field.description = getValueFrom(el, 'input[name="description"]', 'value') ?? ''
484
+
485
+
486
+ // object related
487
+ field.input_name = getValueFrom(el, 'input[name="objectname"]', 'value') ?? ''
488
+ field.input_index = getValueFrom(el, 'input[name="index"]', 'value') ?? ''
489
+ field.input_label = getValueFrom(el, 'input[name="labeltext"]', 'value') ?? ''
490
+ field.input_placeholder = getValueFrom(el, 'input[name="placeholder"]', 'value') ?? ''
491
+ field.input_caption = getValueFrom(el, 'input[name="caption"]', 'value') ?? ''
492
+ field.input_information = getValueFrom(el, 'input[name="information"]', 'value') ?? ''
493
+ field.input_containercss = getValueFrom(el, 'input[name="input-containercss"]', 'value') ?? ''
494
+ field.input_inlinestyle = getValueFrom(el, 'input[name="input-inlinestyle"]', 'value') ?? ''
495
+
496
+
497
+ var sel_charcase = el.querySelector('select[name="charcasing"]')
498
+ if (sel_charcase!=null) {
499
+ field.input_charcase = sel_charcase.value
500
+ } else {
501
+ field.input_charcase = 'normal'
502
+ }
503
+
504
+ var chk_inputdisabled = el.querySelector('input[name="disabledinform"]')
505
+ field.input_disabled = chk_inputdisabled.checked ? true : false
506
+
507
+ var chk_showingrid = el.querySelector('input[name="showingrid"]')
508
+ field.showInGrid = chk_showingrid.checked ? true : false
509
+
510
+ var chk_showinform = el.querySelector('input[name="showinform"]')
511
+ field.showInForm = chk_showinform.checked ? true : false
512
+
513
+ // grid related
514
+ field.grid_formatter = getValueFrom(el, 'input[name="gridformatter"]', 'value') ?? ''
515
+ field.grid_css = getValueFrom(el, 'input[name="gridcss"]', 'value') ?? ''
516
+ field.grid_inlinestyle = getValueFrom(el, 'input[name="gridinlinestyle"]', 'value') ?? ''
517
+ field.grid_sorting = getCheckedFrom(el, 'input[name="gridsorting"]')
518
+
519
+
520
+
521
+ field.Validation = {}
522
+
523
+ // isRequired
524
+ field.Validation.isRequired = getCheckedFrom(el, 'input[name="isrequired"]')
525
+ field.Validation.isMinimum = getCheckedFrom(el, 'input[name="isbatasmin"]')
526
+ field.Validation.isMaximum = getCheckedFrom(el, 'input[name="isbatasmax"]')
527
+ field.Validation.Minimum = getValueFrom(el, 'input[name="minimum"]', 'value')
528
+ field.Validation.Maximum = getValueFrom(el, 'input[name="maximum"]', 'value')
529
+ field.Validation.messageDefault = getValueFrom(el, 'input[name="msg_invalid_default"]', 'value')
530
+ field.Validation.messageRequired = getValueFrom(el, 'input[name="msg_invalid_required"]', 'value')
531
+ field.Validation.messageMinimum = getValueFrom(el, 'input[name="msg_invalid_minimum"]', 'value')
532
+ field.Validation.messageMaximum = getValueFrom(el, 'input[name="msg_invalid_maximum"]', 'value')
533
+ field.Validation.hasCustomValidator = getCheckedFrom(el, 'input[name="hascustomvalidator"]')
534
+ field.Validation.customValidator = getValueFrom(el, 'input[name="validator"]', 'value')
535
+
536
+
537
+
538
+ field.Reference = {}
539
+ field.Reference.table = getValueFrom(el, 'input[name="ref_table"]', 'value')
540
+ field.Reference.pk = getValueFrom(el, 'input[name="ref_id"]', 'value')
541
+ field.Reference.bindingValue = getValueFrom(el, 'input[name="ref_id"]', 'value')
542
+ field.Reference.bindingText = getValueFrom(el, 'input[name="ref_text"]', 'value')
543
+ field.Reference.bindingDisplay = getValueFrom(el, 'input[name="ref_display"]', 'value')
544
+ field.Reference.loaderApiModule = getValueFrom(el, 'input[name="loaderapimodule"]', 'value')
545
+ field.Reference.loaderApiPath = getValueFrom(el, 'input[name="loaderapipath"]', 'value')
546
+
547
+
548
+ field.Handle = {}
549
+ field.Handle.changed = getCheckedFrom(el, 'input[name="ishandlechanged"]')
550
+ field.Handle.input = getCheckedFrom(el, 'input[name="ishandleinput"]')
551
+ field.Handle.keydown = getCheckedFrom(el, 'input[name="ishandlekeydown"]')
552
+ field.Handle.checked = getCheckedFrom(el, 'input[name="ishandlechecked"]')
553
+ field.Handle.selected = getCheckedFrom(el, 'input[name="ishandleselected"]')
554
+ field.Handle.selecting = getCheckedFrom(el, 'input[name="ishandleselecting"]')
555
+ field.Handle.populating = getCheckedFrom(el, 'input[name="ishandlepopulating"]')
556
+ field.Handle.loadingdata = getCheckedFrom(el, 'input[name="ishandleloadingdata"]')
557
+
558
+
559
+ if (!isValidName(field.data_fieldname)) {
560
+ el.classList.add('field-error')
561
+ throw new Error('Nama Field is not valid, gunakan huruf kecil, karakter special _ atau angka')
562
+ }
563
+
564
+ return field
565
+ }
566
+
567
+
568
+
569
+ async function AppGenIO_Reset(self) {
570
+ const datainit = {
571
+ id: '',
572
+ appname: '',
573
+ name: '',
574
+ directory: Context.targetDirectory,
575
+ title: '',
576
+ description: '',
577
+ icon: '',
578
+ primary_entity_id: '',
579
+ primary_entity_name: '',
580
+ actions: [],
581
+ entities: {},
582
+ }
583
+ await AppGenIO_ReadData(self, JSON.stringify(datainit))
584
+ }
585
+
586
+ async function AppGenIO_ReadData(self, content) {
587
+ const data = JSON.parse(content)
588
+ AppGenIO_Load(self, data)
589
+ }
590
+
591
+ async function AppGenIO_Load(self, data) {
592
+ // data def
593
+ const obj_programid = document.getElementById('obj_programid')
594
+ const obj_appname = document.getElementById('obj_appname')
595
+ const obj_programname = document.getElementById('obj_programname')
596
+ const obj_programtitle = document.getElementById('obj_programtitle')
597
+ const obj_directory = document.getElementById('obj_directory')
598
+ const obj_programdescription = document.getElementById('obj_programdescription')
599
+ const obj_icon = document.getElementById('upload-icon')
600
+
601
+ obj_programid.value = data.id
602
+ obj_appname.value = data.appname
603
+ obj_programname.value = data.name
604
+ obj_programtitle.value = data.title
605
+ obj_directory.value = data.directory
606
+ obj_programdescription.value = data.description
607
+ obj_icon.style.backgroundImage = data.icon
608
+
609
+
610
+ // actions
611
+ const elActions = document.getElementById('action-lists')
612
+ elActions.innerHTML = ''
613
+ for (var action of data.actions) {
614
+ self.addAction(action)
615
+ }
616
+
617
+ // clear data entity
618
+ const elEntities = document.getElementById('data-entities')
619
+ elEntities.innerHTML = ''
620
+
621
+ // clear data design
622
+ const elEntityDesign = document.getElementById('entities-design')
623
+ elEntityDesign.innerHTML = ''
624
+
625
+ const tbl_entity =document.getElementById('tbl_entity')
626
+ const tbody = tbl_entity.querySelector('tbody')
627
+ var de = document.getElementById('entities-design')
628
+ for (var entityname in data.entities) {
629
+ var entity = data.entities[entityname]
630
+
631
+
632
+ await self.AddEntity({
633
+ col_id: entity.id,
634
+ col_name: entity.name,
635
+ col_title: entity.title,
636
+ col_table: entity.table,
637
+ col_pk: entity.pk,
638
+ isheader: entity.isheader
639
+ })
640
+
641
+ self.startDesign(entity.id, true) // supperss start design
642
+
643
+ const btn = tbody.querySelector(`[name="col_btndesign"][${ATTR_ENTITYID}="${entity.id}"]`)
644
+ btn.click()
645
+
646
+
647
+ // isikan data entity
648
+ // TODO: isikan data entity
649
+ const editor = de.querySelector(`div[name="entity-editor"][${ATTR_ENTITYID}="${entity.id}"]`)
650
+ setValueTo(entity.descr, editor, 'div[name="designer-info"] input[name="table-descr"]', 'value')
651
+ setCheckedTo(entity.allowRowAdd, editor, 'div[name="designer-info"] input[name="allow-row-add"]')
652
+ setCheckedTo(entity.allowRowRemove, editor, 'div[name="designer-info"] input[name="allow-row-remove"]')
653
+ setValueTo(entity.identifierMethod, editor, 'div[name="designer-info"] select[name="identifier-method"]', 'value')
654
+ setValueTo(entity.identifierPrefix, editor, 'div[name="designer-info"] input[name="identifier-prefix"]', 'value')
655
+ setValueTo(entity.identifierBlock , editor, 'div[name="designer-info"] input[name="identifier-block"]', 'value')
656
+ setValueTo(entity.identifierLength, editor, 'div[name="designer-info"] input[name="identifier-length"]', 'value')
657
+
658
+ // ambil drop target dari entity
659
+ let droptarget = elEntityDesign.querySelector(`div[name="entity-editor"][${ATTR_ENTITYID}="${entity.id}"] div[name="drop-target"]`)
660
+
661
+ // console.log(entity)
662
+ for (var item_id in entity.Items) {
663
+ let item = entity.Items[item_id]
664
+
665
+ var componentname = item.component
666
+
667
+ let comp = Components[componentname]
668
+ let datafield = self.addComponentToDesigner(droptarget, comp)
669
+
670
+ // isi datafieldnya
671
+ AppGenIO_FillDataField(self, datafield, item)
672
+ }
673
+
674
+ // uniques
675
+ for (var uniq_name in entity.Uniques) {
676
+ let uniq = entity.Uniques[uniq_name]
677
+ let name = uniq.name
678
+ let fields = uniq.fields
679
+ Context.addUnique({uniq_name:name, uniq_fields:fields}, entity.id)
680
+ }
681
+
682
+ // search
683
+ for (var search_name in entity.Search) {
684
+ let search = entity.Search[search_name]
685
+ let name = search.name
686
+ let label = search.label
687
+ let fields = search.fields
688
+ Context.addSearch({
689
+ criteria_name: name,
690
+ criteria_label: label,
691
+ criteria_fields:fields
692
+ }, entity.id)
693
+ }
694
+
695
+ }
696
+
697
+ }
698
+
699
+ function AppGenIO_FillDataField(self, datafield, field) {
700
+
701
+ setValueTo(field.data_fieldname, datafield, 'input[name="fieldname"]', 'value')
702
+ setValueTo(field.data_fieldname, datafield, 'input[name="fieldname-summary"]', 'value')
703
+
704
+ setSelectedTo(field.data_type, datafield, 'select[name="datatype"]')
705
+
706
+ setValueTo(field.data_length, datafield, 'input[name="datalength"]', 'value')
707
+ setValueTo(field.data_precision, datafield, 'input[name="dataprecission"]', 'value')
708
+
709
+ setCheckedTo(field.data_allownull, datafield, 'input[name="allownull"]')
710
+
711
+ if (field.component=='Checkbox') {
712
+ setCheckedTo(field.data_defaultvalue, datafield, 'input[name="defaultvalue"]')
713
+ } else {
714
+ setValueTo(field.data_defaultvalue, datafield, 'input[name="defaultvalue"]', 'value')
715
+ }
716
+ setValueTo(field.description, datafield, 'input[name="description"]', 'value')
717
+
718
+
719
+ if (field.input_index===undefined) {
720
+ field.input_index = '0'
721
+ }
722
+
723
+ // object related
724
+ setValueTo(field.input_name, datafield, 'input[name="objectname"]', 'value')
725
+ setValueTo(field.input_index, datafield, 'input[name="index"]', 'value')
726
+ setValueTo(field.input_label, datafield, 'input[name="labeltext"]', 'value')
727
+ setValueTo(field.input_placeholder, datafield, 'input[name="placeholder"]', 'value')
728
+ setValueTo(field.input_caption, datafield, 'input[name="caption"]', 'value')
729
+ setValueTo(field.input_information, datafield, 'input[name="information"]', 'value')
730
+ setValueTo(field.input_containercss, datafield, 'input[name="input-containercss"]', 'value')
731
+ setValueTo(field.input_inlinestyle, datafield, 'input[name="input-inlinestyle"]', 'value')
732
+
733
+ setSelectedTo(field.input_charcase, datafield, 'select[name="charcasing"]')
734
+
735
+ setCheckedTo(field.input_disabled, datafield, 'input[name="disabledinform"]')
736
+ setCheckedTo(field.showInGrid, datafield, 'input[name="showingrid"]')
737
+ setCheckedTo(field.showInForm, datafield, 'input[name="showinform"]')
738
+
739
+
740
+ // grid related
741
+ setValueTo(field.grid_formatter, datafield, 'input[name="gridformatter"]', 'value')
742
+ setValueTo(field.grid_css, datafield, 'input[name="gridcss"]', 'value')
743
+ setValueTo(field.grid_inlinestyle, datafield, 'input[name="gridinlinestyle"]', 'value')
744
+ setCheckedTo(field.grid_sorting, datafield, 'input[name="gridsorting"]')
745
+
746
+
747
+ setCheckedTo(field.Validation.isRequired, datafield, 'input[name="isrequired"]')
748
+ setCheckedTo(field.Validation.isMinimum, datafield, 'input[name="isbatasmin"]')
749
+ setCheckedTo(field.Validation.isMaximum, datafield, 'input[name="isbatasmax"]')
750
+
751
+ setValueTo(field.Validation.Minimum, datafield, 'input[name="minimum"]', 'value')
752
+ setValueTo(field.Validation.Maximum, datafield, 'input[name="maximum"]', 'value')
753
+ setValueTo(field.Validation.messageDefault, datafield, 'input[name="msg_invalid_default"]', 'value')
754
+ setValueTo(field.Validation.messageRequired, datafield, 'input[name="msg_invalid_required"]', 'value')
755
+ setValueTo(field.Validation.messageMinimum, datafield, 'input[name="msg_invalid_minimum"]', 'value')
756
+ setValueTo(field.Validation.messageMaximum, datafield, 'input[name="msg_invalid_maximum"]', 'value')
757
+
758
+ setCheckedTo(field.Validation.hasCustomValidator, datafield, 'input[name="hascustomvalidator"]')
759
+ setValueTo(field.Validation.customValidator, datafield, 'input[name="validator"]', 'value')
760
+
761
+
762
+ setValueTo(field.Reference.table, datafield, 'input[name="ref_table"]', 'value')
763
+ setValueTo(field.Reference.pk, datafield, 'input[name="ref_id"]', 'value')
764
+
765
+ // TODO: ini nanti kalau perlu diperbaiki disini
766
+ // setValueTo(field.Reference.bindingValue, datafield, 'input[name="ref_id"]', 'value')
767
+
768
+ setValueTo(field.Reference.bindingDisplay, datafield, 'input[name="ref_display"]', 'value')
769
+ setValueTo(field.Reference.bindingText, datafield, 'input[name="ref_text"]', 'value')
770
+
771
+
772
+ setValueTo(field.Reference.loaderApiModule, datafield, 'input[name="loaderapimodule"]', 'value')
773
+ setValueTo(field.Reference.loaderApiPath, datafield, 'input[name="loaderapipath"]', 'value')
774
+
775
+ setCheckedTo(field.Handle.changed, datafield, 'input[name="ishandlechanged"]')
776
+ setCheckedTo(field.Handle.input, datafield, 'input[name="ishandleinput"]')
777
+ setCheckedTo(field.Handle.keydown, datafield, 'input[name="ishandlekeydown"]')
778
+ setCheckedTo(field.Handle.checked, datafield, 'input[name="ishandlechecked"]')
779
+ setCheckedTo(field.Handle.selected, datafield, 'input[name="ishandleselected"]')
780
+ setCheckedTo(field.Handle.selecting, datafield, 'input[name="ishandleselecting"]')
781
+ setCheckedTo(field.Handle.populating, datafield, 'input[name="ishandlepopulating"]')
782
+ setCheckedTo(field.Handle.loadingdata, datafield, 'input[name="ishandleloadingdata"]')
783
+
784
+ }