@agung_dhewe/webapps 1.1.2 → 1.2.4

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 (94) hide show
  1. package/lib/fgta5js-dist/fgta5js-v1.8.5.min.js +11 -0
  2. package/lib/fgta5js-dist/fgta5js-v1.8.5.min.js.map +1 -0
  3. package/{libs → lib}/webmodule/module-edit.css +73 -18
  4. package/{libs → lib}/webmodule/module-list.css +13 -0
  5. package/lib/webmodule/module-print.css +28 -0
  6. package/{libs → lib}/webmodule/module.css +13 -6
  7. package/{libs → lib}/webmodule/module.js +14 -4
  8. package/lib/webmodule/pagehelper.mjs +129 -0
  9. package/modules/generator/appgen-io.mjs +153 -76
  10. package/modules/generator/appgen-ui.mjs +234 -167
  11. package/modules/generator/generator-designtemplate-def.html +38 -0
  12. package/modules/generator/generator-designtemplate.html +11 -1492
  13. package/modules/generator/generator.css +103 -65
  14. package/modules/generator/generator.mjs +1 -1
  15. package/modules/generator/generator.svg +98 -0
  16. package/modules/generator/generatorEdit.mjs +43 -35
  17. package/modules/generator/generatorList.mjs +27 -0
  18. package/modules/generator/tpl-designerinfo.html +100 -0
  19. package/modules/generator/tpl-field-checkbox.html +200 -0
  20. package/modules/generator/tpl-field-combobox.html +228 -0
  21. package/modules/generator/tpl-field-datepicker.html +192 -0
  22. package/modules/generator/tpl-field-filebox.html +189 -0
  23. package/modules/generator/tpl-field-numberbox.html +218 -0
  24. package/modules/generator/tpl-field-textbox.html +255 -0
  25. package/modules/generator/tpl-field-timepicker.html +192 -0
  26. package/modules/generator/tpl-searchdesign.html +32 -0
  27. package/modules/generator/tpl-uniquedesign.html +25 -0
  28. package/modules/login/login.css +10 -2
  29. package/package.json +5 -3
  30. package/percobaan/coba-sequencer.js +16 -0
  31. package/src/api.js +12 -9
  32. package/src/apis/generator.api.js +35 -23
  33. package/src/apis/login.api.js +1 -0
  34. package/src/context.js +12 -2
  35. package/src/db.js +58 -32
  36. package/src/generator/createApiModule.js +4 -1
  37. package/src/generator/createIcon.js +24 -2
  38. package/src/generator/createLayoutCss.js +107 -0
  39. package/src/generator/createModuleDetilEditHtml.js +12 -1
  40. package/src/generator/createModuleDetilEditMjs.js +32 -28
  41. package/src/generator/createModuleDetilListHtml.js +14 -7
  42. package/src/generator/createModuleDetilListMjs.js +13 -1
  43. package/src/generator/createModuleHeaderEditHtml.js +13 -1
  44. package/src/generator/createModuleHeaderEditMjs.js +23 -2
  45. package/src/generator/createProgramData.js +3 -2
  46. package/src/generator/createTable.js +42 -38
  47. package/src/generator/helper.js +45 -27
  48. package/src/generator/templates/__rollup-module copy.ejs +90 -0
  49. package/src/generator/templates/__rollup-module.ejs +102 -31
  50. package/src/generator/templates/api-module.js.ejs +171 -32
  51. package/src/generator/templates/layout.css.ejs +24 -0
  52. package/src/generator/templates/module-ext.html.ejs +1 -1
  53. package/src/generator/templates/module-ext.mjs.ejs +19 -1
  54. package/src/generator/templates/module.ejs.ejs +8 -0
  55. package/src/generator/templates/module.mjs.ejs +42 -5
  56. package/src/generator/templates/moduleDetilEdit.html.ejs +11 -0
  57. package/src/generator/templates/moduleDetilEdit.mjs.ejs +135 -30
  58. package/src/generator/templates/moduleDetilList.html.ejs +2 -1
  59. package/src/generator/templates/moduleDetilList.mjs.ejs +86 -11
  60. package/src/generator/templates/moduleHeaderEdit.html.ejs +8 -1
  61. package/src/generator/templates/moduleHeaderEdit.mjs.ejs +123 -36
  62. package/src/generator/templates/moduleHeaderList.html.ejs +5 -1
  63. package/src/generator/templates/moduleHeaderList.mjs.ejs +47 -15
  64. package/src/generator/trygenerate.js +18 -2
  65. package/src/generator/worker.js +83 -72
  66. package/src/helper.js +12 -13
  67. package/src/logger.js +12 -12
  68. package/src/notifier.js +29 -0
  69. package/src/routers/generatorApi.js +9 -3
  70. package/src/routers/generatorPage.js +3 -1
  71. package/src/routers/moduleApi.js +1 -1
  72. package/src/routers/modulePage.js +42 -7
  73. package/src/sequencerdoc.js +22 -46
  74. package/src/sequencerline.js +16 -4
  75. package/src/session.js +69 -33
  76. package/src/startup.js +47 -10
  77. package/src/webapps.js +62 -18
  78. package/templates/_lib_debug.ejs +8 -8
  79. package/templates/_lib_production.ejs +2 -2
  80. package/templates/application.page.ejs +43 -8
  81. package/templates/generator.page.ejs +4 -3
  82. package/templates/index.page.ejs +2 -2
  83. package/templates/login.page.ejs +3 -3
  84. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +0 -11
  85. package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +0 -1
  86. package/libs/webmodule/pagehelper.mjs +0 -45
  87. package/modules/generator/generator.png +0 -0
  88. /package/{libs/fgta5js-dist/fgta5js-v1.8.3.min.css → lib/fgta5js-dist/fgta5js-v1.8.5.min.css} +0 -0
  89. /package/{libs → lib}/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
  90. /package/{libs → lib}/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
  91. /package/{libs → lib}/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
  92. /package/{libs → lib}/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
  93. /package/{libs → lib}/fgta5js-dist/fonts/karla.css +0 -0
  94. /package/{libs → lib}/webmodule/module-footer.css +0 -0
@@ -1,3 +1,8 @@
1
+ <div id="<%= modulePart %>-head">
2
+ <div id="<%= modulePart %>-head-title" class="section-detil-title"></div>
3
+ <div id="<%= modulePart %>-head-descr" class="section-detil-descr"></div>
4
+ </div>
5
+
1
6
  <form id="<%= modulePart %>-frm" class="module-form" locked="true" autoid="<%= autoid %>" primarykey="<%= primaryKeyElementId %>"><% fields.forEach(field => { %>
2
7
 
3
8
  <!-- <%= field.component %>: <%= field.fieldname %>-->
@@ -9,8 +14,14 @@
9
14
  >
10
15
  </div>
11
16
  <% }) %>
17
+
18
+
19
+ <div id="<%= modulePart %>-footer"></div>
20
+
12
21
  </form>
13
22
 
23
+
24
+
14
25
  <div class="panel-recordbar" data-view="nodetil">
15
26
  <div><a id="<%= moduleSection %>-btn_recordstatus" href="javascript:void(0)" tabindex="-1">Record Status</a></div>
16
27
  <div><a id="<%= moduleSection %>-btn_logs" href="javascript:void(0)" tabindex="-1">Logs</a></div>
@@ -1,13 +1,15 @@
1
1
  import Context from './<%= moduleName %>-context.mjs'
2
- import * as Extender from './<%= moduleName %>-ext.mjs'
3
- import * as pageHelper from '/public/libs/webmodule/pagehelper.mjs'
2
+ import * as Ext from './<%= moduleName %>-ext.mjs'
3
+ import * as pageHelper from '/public/lib/webmodule/pagehelper.mjs'
4
+
5
+ const Extender = Ext.<%=extenderDetil%> ?? Ext
4
6
 
5
7
 
6
- const CurrentState = {}
7
8
  const Crsl = Context.Crsl
8
9
  const CurrentSectionId = Context.Sections.<%= modulePart %>
9
10
  const CurrentSection = Crsl.Items[CurrentSectionId]
10
11
  const Source = Context.Source
12
+ const CurrentState = {}
11
13
 
12
14
  const TitleWhenNew = 'New <%= title %>'
13
15
  const TitleWhenView = 'View <%= title %>'
@@ -30,10 +32,11 @@ const btn_logs = document.getElementById('<%= moduleSection %>-btn_logs')
30
32
 
31
33
  const frm = new $fgta5.Form('<%= modulePart %>-frm');<% fields.forEach(field => { %>
32
34
  const <%= field.inputname %> = frm.Inputs['<%= field.elementId %>']<% }) %>
33
- const obj_createby = document.getElementById('fRecord-section-createby')
34
- const obj_createdate = document.getElementById('fRecord-section-createdate')
35
- const obj_modifyby = document.getElementById('fRecord-section-modifyby')
36
- const obj_modifydate = document.getElementById('fRecord-section-modifydate')
35
+ const rec_createby = document.getElementById('fRecord-section-createby')
36
+ const rec_createdate = document.getElementById('fRecord-section-createdate')
37
+ const rec_modifyby = document.getElementById('fRecord-section-modifyby')
38
+ const rec_modifydate = document.getElementById('fRecord-section-modifydate')
39
+ const rec_id = document.getElementById('fRecord-section-id')
37
40
 
38
41
  export const Section = CurrentSection
39
42
 
@@ -63,35 +66,53 @@ export async function init(self, args) {
63
66
  CurrentState.headerFormLocked = true
64
67
  CurrentState.editDisabled = false
65
68
 
69
+ CurrentState.Actions = {
70
+ newdata: btn_new,
71
+ edit: btn_edit,
72
+ }
73
+
74
+ CurrentState.getHeaderForm = () => {
75
+ const <%= moduleName %>HeaderEdit = self.Modules.<%= moduleName %>HeaderEdit
76
+ const frmHeader = <%= moduleName %>HeaderEdit.getHeaderForm()
77
+ return frmHeader
78
+ }
79
+
66
80
 
67
81
  <% fieldHandles.forEach(field => { %>
68
82
  // <%= field.component %>: <%= field.inputname %><% field.handles.forEach(hnd => { %>
69
83
  <%= field.inputname %>.addEventListener('<%= hnd.eventname %>', <% if (hnd.eventname=='selecting') { %>async <% } %>(evt)=>{
70
84
  const fn_<%= hnd.eventname %>_name = '<%= field.inputname %>_<%= hnd.eventname %>'
71
85
  const fn_<%= hnd.eventname %> = Extender[fn_<%= hnd.eventname %>_name]
72
- if (typeof fn_<%= field.inputname %>_<%= hnd.eventname %> === 'function') {
86
+ if (typeof fn_<%= hnd.eventname %> === 'function') {
73
87
  // create function di Extender<% if (field.component=='Combobox' && hnd.eventname=='selecting') { %> (jika perlu)<% } %>:
74
- // export async function <%= field.inputname %>_<%= hnd.eventname %>(self, <%= field.inputname %>, frm, evt)
75
- fn_<%= field.inputname %>_<%= hnd.eventname %>(self, <%= field.inputname %>, frm, evt)
88
+ // export async function <%= field.inputname %>_<%= hnd.eventname %>(self, <%= field.inputname %>, frm, evt) {}
89
+ fn_<%= hnd.eventname %>(self, <%= field.inputname %>, frm, evt)
76
90
  } else {<% if (field.component=='Combobox' && hnd.eventname=='selecting') { %>
77
91
  // default selecting
78
92
  const cbo = evt.detail.sender
79
93
  const dialog = evt.detail.dialog
80
94
  const searchtext = evt.detail.searchtext!=null ? evt.detail.searchtext : ''
81
- const url = `${Context.appsUrls.<%= hnd.appId %>.url}/<%- hnd.path %>`
95
+ const url = <% if (hnd.appId=='/') { %>'<%- hnd.path %>'<% } else { %>`${Context.appsUrls.<%= hnd.appId %>.url}/<%- hnd.path %>`<% } %>
96
+ const sort = {}
82
97
  const criteria = {
83
98
  searchtext: searchtext,
84
99
  }
85
100
 
101
+ evt.detail.url = url
102
+ evt.detail.CurrentState = CurrentState
103
+
104
+ // buat function di extender:
105
+ // export function <%= field.inputname %>_<%= hnd.eventname %>_criteria(self, <%= field.inputname %>, frm, criteria, sort, evt) {}
86
106
  const fn_<%= hnd.eventname %>_criteria_name = '<%= field.inputname %>_<%= hnd.eventname %>_criteria'
87
- const fn_<%= field.inputname %>_<%= hnd.eventname %>_criteria = Extender[fn_<%= hnd.eventname %>_criteria_name]
107
+ const fn_<%= hnd.eventname %>_criteria = Extender[fn_<%= hnd.eventname %>_criteria_name]
88
108
  if (typeof fn_<%= hnd.eventname %>_criteria === 'function') {
89
- fn_<%= field.inputname %>_<%= hnd.eventname %>_criteria(self, <%= field.inputname %>, criteria)
109
+ fn_<%= hnd.eventname %>_criteria(self, <%= field.inputname %>, frm, criteria, sort, evt)
90
110
  }
91
111
 
92
112
  cbo.wait()
93
113
  try {
94
- const result = await Module.apiCall(url, {
114
+ const result = await Module.apiCall(evt.detail.url, {
115
+ sort,
95
116
  criteria,
96
117
  offset: evt.detail.offset,
97
118
  limit: evt.detail.limit,
@@ -129,9 +150,11 @@ export async function openSelectedData(self, params) {
129
150
  <% if (detilHasUpload) { %>
130
151
  dataOpened(self, data)<% } %>
131
152
 
153
+ const suspended = self.Modules.<%= headerModulePartEdit %>.getCurrentState().Actions.edit.isSuspended()
154
+
155
+ CurrentState.editDisabled = suspended
132
156
  CurrentState.currentOpenedId = id
133
157
 
134
-
135
158
  // jika posisi header dalam keadaan unlock (bisa edit, perlu cek kondisi data, untuk menentukan bisa diedit atau tidak)
136
159
  if (!CurrentState.headerFormLocked) {
137
160
  const fn_iseditdisabled_name = '<%= modulePart %>_isEditDisabled'
@@ -145,15 +168,22 @@ export async function openSelectedData(self, params) {
145
168
  // disable primary key
146
169
  setPrimaryKeyState(self, {disabled:true})
147
170
 
171
+ // isi form dengan data
148
172
  frm.setData(data)
149
- frm.acceptChanges()
150
- frm.lock()
151
-
173
+
174
+ // jika ada kebutuhan untuk oleh lagi form dan data, bisa lakukan di extender
175
+ // export function <%= modulePart %>_formOpened(self, frm, CurrentState) {}
152
176
  const fn_formopened_name = '<%= modulePart %>_formOpened'
153
177
  const fn_formopened = Extender[fn_formopened_name]
154
178
  if (typeof fn_formopened === 'function') {
155
179
  fn_formopened(self, frm, CurrentState)
156
180
  }
181
+
182
+
183
+ // finally, accept changes dan lock form
184
+ frm.acceptChanges()
185
+ frm.lock()
186
+
157
187
  } catch (err) {
158
188
  CurrentState.currentOpenedId = null
159
189
  throw err
@@ -163,6 +193,10 @@ export async function openSelectedData(self, params) {
163
193
  }
164
194
  }
165
195
 
196
+ export function getCurrentState(self) {
197
+ return CurrentState
198
+ }
199
+
166
200
  export function getForm(self) {
167
201
  return frm
168
202
  }
@@ -175,12 +209,28 @@ export function headerLocked(self) {
175
209
  CurrentState.headerFormLocked = true
176
210
  CurrentState.editDisabled = true
177
211
  btn_new.disabled = true
212
+
213
+ // Extender untuk event Locked
214
+ // export function <%= modulePart %>_formLocked(self, frm, CurrentState) {}
215
+ const fn_name = '<%= modulePart %>_formLocked'
216
+ const fn = Extender[fn_name]
217
+ if (typeof fn === 'function') {
218
+ fn(self, frm, CurrentState)
219
+ }
178
220
  }
179
221
 
180
222
  export function headerUnlocked(self) {
181
223
  CurrentState.headerFormLocked = false
182
224
  CurrentState.editDisabled = false
183
225
  btn_new.disabled = false
226
+
227
+ // Extender untuk event Unlocked
228
+ // export function <%= modulePart %>_formUnlocked(self, frm, CurrentState) {}
229
+ const fn_name = '<%= modulePart %>_formUnlocked'
230
+ const fn = Extender[fn_name]
231
+ if (typeof fn === 'function') {
232
+ fn(self, frm, CurrentState)
233
+ }
184
234
  }
185
235
 
186
236
  export function disableNextButton(self, disabled=true) {
@@ -316,6 +366,7 @@ async function frm_locked(self, evt) {
316
366
 
317
367
 
318
368
  // Extender untuk event locked
369
+ // export function <%= modulePart %>_formLocked(self, frm, CurrentState) {}
319
370
  const fn_name = '<%= modulePart %>_formLocked'
320
371
  const fn = Extender[fn_name]
321
372
  if (typeof fn === 'function') {
@@ -352,6 +403,7 @@ async function frm_unlocked(self, evt) {
352
403
  btn_next.disabled = true
353
404
 
354
405
  // Extender untuk event Unlocked
406
+ // export function <%= modulePart %>_formUnlocked(self, frm) {}
355
407
  const fn_name = '<%= modulePart %>_formUnlocked'
356
408
  const fn = Extender[fn_name]
357
409
  if (typeof fn === 'function') {
@@ -458,19 +510,20 @@ async function btn_new_click(self, evt) {
458
510
  const <%= headerPrimaryKey %> = header_pk.value
459
511
 
460
512
  // inisiasi data baru
461
- let datainit = {
513
+ const datainit = {
462
514
  <%= headerPrimaryKey %>,<% defaultInits.forEach(setdefault => { %>
463
- <%- setdefault %>,
464
- <% }) %>}
515
+ <%- setdefault %>,<% }) %>
516
+ }
465
517
 
466
518
 
467
519
  // jika perlu modifikasi data initial,
468
520
  // atau dialog untuk opsi data baru,
469
521
  // dapat dibuat di Extender.newData
522
+ // export async function <%= modulePart %>_newData(self, datainit, frm, CurrentState) {}
470
523
  const fn_newdata_name = '<%= modulePart %>_newData'
471
524
  const fn_newdata = Extender[fn_newdata_name]
472
525
  if (typeof fn_newdata === 'function') {
473
- await fn_newdata(self, datainit, frm)
526
+ await fn_newdata(self, datainit, frm, CurrentState)
474
527
  }
475
528
 
476
529
  // buat data baru
@@ -497,6 +550,7 @@ async function btn_save_click(self, evt) {
497
550
  console.log('btn_save_click')
498
551
 
499
552
  // Extender Autofill
553
+ // export async function <%= modulePart %>_autofill(self, frm) {}
500
554
  const fn_autofill_name = '<%= modulePart %>_autofill'
501
555
  const fn_autofill = Extender[fn_autofill_name]
502
556
  if (typeof fn_autofill === 'function') {
@@ -547,12 +601,19 @@ async function btn_save_click(self, evt) {
547
601
 
548
602
 
549
603
  // Extender Saving
604
+ // export async function <%= modulePart %>_dataSaving(self, dataToSave, frm, args) {}
605
+ const args = { cancelSave: false }
550
606
  const fn_datasaving_name = '<%= modulePart %>_dataSaving'
551
607
  const fn_datasaving = Extender[fn_datasaving_name]
552
608
  if (typeof fn_datasaving === 'function') {
553
- await fn_datasaving(self, dataToSave, frm)
609
+ await fn_datasaving(self, dataToSave, frm, args)
554
610
  }
555
611
 
612
+ // batalkan save, jika ada request cancel
613
+ if (args.cancelSave) {
614
+ console.log('save is canceled')
615
+ return
616
+ }
556
617
 
557
618
 
558
619
  let mask = $fgta5.Modal.createMask()
@@ -596,7 +657,8 @@ async function btn_save_click(self, evt) {
596
657
  const fn_datasaved_name = '<%= modulePart %>_dataSaved'
597
658
  const fn_datasaved = Extender[fn_datasaved_name]
598
659
  if (typeof fn_datasaved === 'function') {
599
- await fn_datasaved(self, data, frm)
660
+ // export async function <%= modulePart %>_dataSaved(self, data, frm) {}
661
+ await fn_datasaved(self, result, frm)
600
662
  }
601
663
 
602
664
 
@@ -650,11 +712,38 @@ async function btn_del_click(self, evt) {
650
712
  console.log('delete data')
651
713
  let mask = $fgta5.Modal.createMask()
652
714
  try {
715
+
716
+ // Extender Deleting
717
+ // export async function <%= modulePart %>_dataDeleting(self, id, args) {}
718
+ const args = { cancelDelete: false }
719
+ const fn_datadeleting_name = '<%= modulePart %>_dataDeleting'
720
+ const fn_datadeleting = Extender[fn_datadeleting_name]
721
+ if (typeof fn_datadeleting === 'function') {
722
+ await fn_datadeleting(self, idValue, args)
723
+ }
724
+
725
+ // batalkan save, jika ada request cancel
726
+ if (args.cancelDelete) {
727
+ console.log('delete is canceled')
728
+ return
729
+ }
730
+
653
731
  const result = await deleteData(self, idValue)
654
732
 
733
+
734
+
735
+ // Extender Delete
736
+ // export async function <%= modulePart %>_dataDeleted(self, data) {}
737
+ const fn_datadeleted_name = '<%= modulePart %>_dataDeleted'
738
+ const fn_datadeleted = Extender[fn_datadeleted_name]
739
+ if (typeof fn_datadeleted === 'function') {
740
+ await fn_datadeleted(self, result)
741
+ }
742
+
743
+
655
744
  // hapus current row yang dipilih di list
656
745
  self.Modules.<%= moduleSection %>List.removeCurrentRow(self)
657
-
746
+
658
747
  // kembali ke list
659
748
  self.Modules.<%= moduleSection %>List.Section.show()
660
749
 
@@ -716,6 +805,12 @@ async function btn_recordstatus_click(self, evt) {
716
805
  sectionReturn: CurrentSection
717
806
  }
718
807
 
808
+ if (frm.isNew()) {
809
+ console.warn('tidak bisa buka rescord status jika data baru')
810
+ $fgta5.MessageBox.warning('Record Status bisa dibuka setelah data disimpan')
811
+ return;
812
+ }
813
+
719
814
  pageHelper.openSection(self, 'fRecord-section', params, async ()=>{
720
815
 
721
816
  let mask = $fgta5.Modal.createMask()
@@ -725,15 +820,17 @@ async function btn_recordstatus_click(self, evt) {
725
820
  const id = pk.value
726
821
  const data = await openData(self, id)
727
822
 
728
- obj_createby.innerHTML = data._createby
729
- obj_createdate.innerHTML = data._createdate
730
- obj_modifyby.innerHTML = data._modifyby
731
- obj_modifydate.innerHTML = data._modifydate
823
+ rec_id.innerHTML = id
824
+ rec_createby.innerHTML = data._createby
825
+ rec_createdate.innerHTML = data._createdate
826
+ rec_modifyby.innerHTML = data._modifyby
827
+ rec_modifydate.innerHTML = data._modifydate
732
828
 
733
829
 
734
830
  // jika mau menambah beberapa informasi mengenai record,
735
831
  // misalnya commit by, postby, dll
736
832
  // melalui extender <%= modulePart %>_addRecordInfo
833
+ // export async function <%= modulePart %>_addRecordInfo(self, data) {}
737
834
  const fn_addrecordinfo_name = '<%= modulePart %>_addRecordInfo'
738
835
  const fn_addrecordinfo = Extender[fn_addrecordinfo_name]
739
836
  if (typeof fn_addrecordinfo === 'function') {
@@ -757,6 +854,12 @@ async function btn_logs_click(self, evt) {
757
854
  sectionReturn: CurrentSection
758
855
  }
759
856
 
857
+ if (frm.isNew()) {
858
+ console.warn('tidak bisa buka logs jika data baru')
859
+ $fgta5.MessageBox.warning('Logs bisa dibuka setelah data disimpan')
860
+ return;
861
+ }
862
+
760
863
  pageHelper.openSection(self, 'fLogs-section', params, async ()=>{
761
864
  // get log data
762
865
  const pk = frm.getPrimaryInput()
@@ -766,7 +869,9 @@ async function btn_logs_click(self, evt) {
766
869
  let mask = $fgta5.Modal.createMask()
767
870
  try {
768
871
 
769
- const url = `${Context.appsUrls.core.url}/logs/list`
872
+
873
+ const logApp = Context.appsUrls.core ?? Context.appsUrls[Context.appName]
874
+ const url = `${logApp.url}/logs/list`
770
875
  const criteria = {
771
876
  module: Context.moduleName,
772
877
  table: '<%= tablename %>',
@@ -1,5 +1,6 @@
1
1
  <div id="<%= modulePart %>-head">
2
-
2
+ <div id="<%= modulePart %>-head-title" class="section-detil-title"></div>
3
+ <div id="<%= modulePart %>-head-descr" class="section-detil-descr"></div>
3
4
  </div>
4
5
 
5
6
 
@@ -1,5 +1,7 @@
1
1
  import Context from './<%= moduleName %>-context.mjs'
2
- import * as Extender from './<%= moduleName %>-ext.mjs'
2
+ import * as Ext from './<%= moduleName %>-ext.mjs'
3
+
4
+ const Extender = Ext.<%=extenderDetil%> ?? Ext
3
5
 
4
6
  const Crsl = Context.Crsl
5
7
  const CurrentSectionId = Context.Sections.<%= modulePart %>
@@ -31,7 +33,8 @@ export async function init(self, args) {
31
33
 
32
34
  // tambahkan event lain di extender: rowrender, rowremoving
33
35
  // dapatkan parameternya di evt.detail
34
- const fn_addTableEvents_name = '<%= sectionName %>List_addTableEvents'
36
+ // export function <%= modulePart %>_addTableEvents(self, tbl) {}
37
+ const fn_addTableEvents_name = '<%= modulePart %>_addTableEvents'
35
38
  const fn_addTableEvents = Extender[fn_addTableEvents_name]
36
39
  if (typeof fn_addTableEvents === 'function') {
37
40
  fn_addTableEvents(self, tbl)
@@ -47,6 +50,7 @@ export async function init(self, args) {
47
50
  btn_delrow.addEventListener('click', (evt)=>{ btn_delrow_click(self, evt) })
48
51
 
49
52
  // Extend list detil
53
+ // export function <%= modulePart %>_init(self) {}
50
54
  const fn_name = '<%= modulePart %>_init'
51
55
  const fn_<%= modulePart %>_init = Extender[fn_name]
52
56
  if (typeof fn_<%= modulePart %>_init === 'function') {
@@ -56,6 +60,22 @@ export async function init(self, args) {
56
60
  CurrentState.headerFormLocked = true
57
61
  }
58
62
 
63
+ function setDefaultHeadTitle(self, headerForm) {
64
+ const data = headerForm.getData()
65
+
66
+ <% if (bindHeadTitle!='') { %>const detilTitleElements = document.getElementsByClassName('section-detil-title')
67
+ for (let el of detilTitleElements) {
68
+ el.innerHTML = data.<%= bindHeadTitle %>
69
+ }
70
+
71
+ <% } %><% if (bindHeadDescr!='') { %>const detilDescrElements = document.getElementsByClassName('section-detil-descr')
72
+ for (let el of detilDescrElements) {
73
+ el.innerHTML = data.<%= bindHeadDescr %>
74
+ }<% } %>
75
+
76
+ }
77
+
78
+
59
79
  export async function openList(self, params) {
60
80
  const moduleHeaderEdit = params.moduleHeaderEdit
61
81
 
@@ -63,10 +83,13 @@ export async function openList(self, params) {
63
83
  const pk = headerForm.getPrimaryInput()
64
84
  const id = pk.value
65
85
 
86
+ // set title halaman ini sesuai data di header
87
+ setDefaultHeadTitle(self, headerForm)
66
88
 
67
89
  // apabila mau menambahkan informasi saat detil list dibuka,
68
90
  // misalnya menambahkan informasi beberapa data dari formHeader
69
91
  // bisa di set pada Extender.<%= modulePart %>_openList : bisa menggunakan template untuk di embed ke header pada detil list
92
+ // export function <%= modulePart %>_openList(self, headerForm) {}
70
93
  const fn_name = '<%= modulePart %>_openList'
71
94
  const fn_<%= modulePart %>_openList = Extender[fn_name]
72
95
  if (typeof fn_<%= modulePart %>_openList === 'function') {
@@ -81,16 +104,31 @@ export async function openList(self, params) {
81
104
  tbl.clear()
82
105
  tbl_loadData(self, {criteria, sort})
83
106
 
84
-
85
- if (CurrentState.headerFormLocked) {
86
- btn_addrow.setAttribute('disabled', '')
107
+ const <%= moduleEdit %> = self.Modules.<%= moduleEdit %>
108
+ const btn_addrow = <%= moduleEdit %>.getCurrentState().Actions.newdata
109
+ <% if (!allowRowAdd) { %>
110
+ const btn_edit = <%= moduleEdit %>.getCurrentState().Actions.edit
111
+ btn_addrow.suspend() <% } %><% if (!allowRowRemove) { %>
112
+ btn_delrow.suspend() <% } %><% if (!allowRowEdit) { %>
113
+ btn_edit.suspend()
114
+ <% } %>
115
+
116
+
117
+ // walaupun CurrentState.headerFormLocked, tapi kalau header edit tidak di suspend tetap bisa add/remove row di detil
118
+ const suspended = self.Modules.<%= headerModulePartEdit %>.getCurrentState().Actions.edit.isSuspended()
119
+ if (suspended) {
120
+ btn_addrow.disabled = true
87
121
  btn_delrow.disabled = true
88
122
  } else {
89
- btn_addrow.removeAttribute('disabled')
123
+ btn_addrow.disabled = false
90
124
  btn_delrow.disabled = false
91
125
  }
92
126
  }
93
127
 
128
+ export function getCurrentState(self) {
129
+ return CurrentState
130
+ }
131
+
94
132
  export function getGrid(self) {
95
133
  return tbl
96
134
  }
@@ -170,19 +208,26 @@ export function keyboardAction(self, actionName) {
170
208
  tbl.nextRecord()
171
209
  } else if (actionName=='enter') {
172
210
  const <%= moduleEdit %> = self.Modules.<%= moduleEdit %>
173
- <%= moduleEdit %>.Section.show({}, (evt)=>{
174
- openRow(self, tbl.CurrentRow)
175
- })
211
+ if (tbl.CurrentRow!=null) {
212
+ <%= moduleEdit %>.Section.show({}, (evt)=>{
213
+ openRow(self, tbl.CurrentRow)
214
+ })
215
+ }
176
216
  }
177
217
  }
178
218
 
179
219
 
180
220
  function setCurrentRow(self, tr) {
181
221
  CurrentState.SelectedRow = tr
222
+ tbl.CurrentRow = tr
182
223
  }
183
224
 
184
225
 
185
226
  async function openRow(self, tr) {
227
+ if (tr==null) {
228
+ return
229
+ }
230
+
186
231
  const keyvalue = tr.getAttribute('keyvalue')
187
232
  const key = tr.getAttribute('key')
188
233
 
@@ -209,13 +254,22 @@ async function openRow(self, tr) {
209
254
 
210
255
  async function listRows(self, criteria, offset, limit, sort) {
211
256
  const url = `/${Context.moduleName}/<%= sectionName %>-list`
257
+ const evt = { url, limit }
258
+
259
+ // export async function <%= modulePart %>_dataLoad(self, criteria, sort, evt) {}
260
+ const fn_dataLoad_name = '<%= modulePart %>_dataLoad'
261
+ const fn_dataLoad = Extender[fn_dataLoad_name]
262
+ if (typeof fn_dataLoad === 'function') {
263
+ await fn_dataLoad(self, criteria, sort, evt)
264
+ }
265
+
212
266
  try {
213
267
  const columns = []
214
- const result = await Module.apiCall(url, {
268
+ const result = await Module.apiCall(evt.url, {
215
269
  columns,
216
270
  criteria,
217
271
  offset,
218
- limit,
272
+ limit: evt.limit,
219
273
  sort
220
274
  })
221
275
  return result
@@ -231,6 +285,14 @@ async function deleteRows(self, data) {
231
285
 
232
286
  const result = await Module.apiCall(url, { data })
233
287
  if (result.deleted) {
288
+
289
+ // export async function <%= modulePart %>_rowsDeleted(self, data) {}
290
+ const fn_name = '<%= modulePart %>_rowsDeleted'
291
+ const fn = Extender[fn_name]
292
+ if (typeof fn === 'function') {
293
+ await fn(self, result)
294
+ }
295
+
234
296
  return true
235
297
  } else {
236
298
  throw new Error(result.message)
@@ -277,8 +339,21 @@ async function tbl_loadData(self, params={}) {
277
339
  if (offset===0) {
278
340
  tbl.clear()
279
341
  }
342
+
343
+
344
+ tbl.setCriteria(criteria)
280
345
  tbl.addRows(result.data)
281
346
  tbl.setNext(result.nextoffset, result.limit)
347
+
348
+
349
+ // export async function <%= modulePart %>_tableDataLoaded(self, tbl, result) {}
350
+ const fn_name = '<%= modulePart %>_tableDataLoaded'
351
+ const fn = Extender[fn_name]
352
+ if (typeof fn === 'function') {
353
+ await fn(self, tbl, result)
354
+ }
355
+
356
+
282
357
  } catch (err) {
283
358
  console.error(err)
284
359
  $fgta5.MessageBox.error(err.message)
@@ -12,12 +12,15 @@
12
12
  </form>
13
13
 
14
14
 
15
+ <div id="<%= modulePart %>-footer">
16
+ </div>
17
+
15
18
  <div id="panel-detil-selector" class="panel-detil <% if (detilCount==0) { %>hidden<% } %>">
16
19
  <div panel-title>
17
20
  Information Detil
18
21
  </div>
19
22
  <div panel-content><% sectionDetils.forEach(detil => { %>
20
- <div class="panel-detil-row">
23
+ <div class="panel-detil-row" id="<%= modulePart %>-info-<%= detil.entityName %>-row">
21
24
  <div data-label><a href="javascript:void(0)" data-target-section="<%= detil.listModulePart %>" data-current-section="<%= modulePart %>"><%= detil.title %></a></div>
22
25
  <div data-info>&nbsp</div>
23
26
  </div><% }) %>
@@ -28,6 +31,10 @@
28
31
  </div>
29
32
  </div>
30
33
 
34
+ <div id="<%= modulePart %>-panelaction" class="panel-action<% if (actionList.length==0) { %> hidden<% } %>"><% if (actionList.length>0) { %><% actionList.forEach(action => { %>
35
+ <button id="<%= action.elementId %>"><%= action.title %></button><% }) %>
36
+ <% } %></div>
37
+
31
38
 
32
39
  <div class="panel-recordbar" <% if (detilCount==0) { %>data-view="nodetil"<% } %>>
33
40
  <div><a id="<%= moduleSection %>-btn_recordstatus" href="javascript:void(0)" tabindex="-1">Record Status</a></div>