@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,195 @@
1
+ import Context from './generator-context.mjs'
2
+ import * as generatorList from './generatorList.mjs'
3
+ import * as generatorEdit from './generatorEdit.mjs'
4
+ import * as generatorExtender from './generator-ext.mjs'
5
+
6
+ const app = Context.app
7
+ const Crsl = Context.Crsl
8
+
9
+
10
+ export default class extends Module {
11
+ constructor() {
12
+ super()
13
+ }
14
+
15
+ async main(args={}) {
16
+
17
+ console.log('initializing module...')
18
+ app.setTitle('Generator')
19
+ app.showFooter(true)
20
+
21
+ args.autoLoadGridData = true
22
+
23
+ const self = this
24
+
25
+
26
+ // module-module yang di load perlu di pack dulu ke dalam variable
27
+ // jangan import lagi module-module ini di dalam mjs tersebut
28
+ // karena akan terjadi cyclic redudancy pada saat di rollup
29
+ self.Modules = {
30
+ generatorList,
31
+ generatorEdit,
32
+ generatorExtender
33
+ }
34
+
35
+ try {
36
+
37
+ // inisiasi sisi server
38
+ try {
39
+ const result = await Module.apiCall(`/${Context.moduleName}/init`, { })
40
+ Context.notifierId = result.notifierId
41
+ Context.notifierSocket = result.notifierSocket
42
+ Context.userId = result.userId
43
+ Context.userFullname = result.userFullname
44
+ Context.sid = result.sid
45
+ Context.targetDirectory = result.targetDirectory
46
+ Context.appsUrls = result.appsUrls
47
+
48
+ } catch (err) {
49
+ throw err
50
+ }
51
+
52
+
53
+ await Promise.all([
54
+ generatorList.init(self, args),
55
+ generatorEdit.init(self, args),
56
+ generatorExtender.init(self, args)
57
+ ])
58
+
59
+ // render dan setup halaman
60
+ await render(self)
61
+
62
+ // listen keyboard action
63
+ listenUserKeys(self)
64
+
65
+ // kalau user melakukan reload, konfirm dulu
66
+ const isFormDirty = true
67
+ window.onbeforeunload = (evt)=>{
68
+ if (isFormDirty) {
69
+ evt.preventDefault();
70
+ return "Changes you made may not be saved."
71
+ }
72
+ };
73
+ } catch (err) {
74
+ throw err
75
+ }
76
+ }
77
+
78
+
79
+ numberboxDatatypeChange(el) {
80
+ const datatype = el.value
81
+ const designField = el.closest('div[name="design-data-field"]');
82
+ const gridFormatter = designField.querySelector('input[name="gridformatter"]')
83
+
84
+ // datatype: int, smallint, bigint, decimal
85
+ // format: decimal, int
86
+ if (datatype=='smallint') {
87
+ gridFormatter.value = 'int(v)'
88
+ } else if (datatype=='decimal') {
89
+ gridFormatter.value = 'decimal(v, 2)'
90
+ } else {
91
+ gridFormatter.value = 'decimal(v, 0)'
92
+ }
93
+ }
94
+ }
95
+
96
+
97
+
98
+ async function render(self) {
99
+ try {
100
+ const footerButtonsContainer = document.getElementsByClassName('footer-buttons-container')
101
+ Module.renderFooterButtons(footerButtonsContainer)
102
+
103
+ Crsl.setIconUrl('/generator/generator.png')
104
+
105
+ Crsl.addEventListener($fgta5.SectionCarousell.EVT_SECTIONSHOWING, (evt)=>{
106
+ var sectionId = evt.detail.commingSection.Id
107
+ for (let cont of footerButtonsContainer) {
108
+ var currContainerSectionId = cont.getAttribute('data-section')
109
+ if (currContainerSectionId==sectionId) {
110
+ setTimeout(()=>{
111
+ cont.classList.remove('hidden')
112
+ cont.style.animation = 'dropped 0.3s forwards'
113
+ setTimeout(()=>{
114
+ cont.style.animation = 'unset'
115
+ }, 300)
116
+ }, 500)
117
+ } else {
118
+ cont.classList.add('hidden')
119
+ }
120
+ }
121
+ })
122
+
123
+ // generator-ext.mjs, export function extendPage(self) {}
124
+ // jangan exekusi langsung dari userExtender, karena akan error saat di rollup
125
+ const extendPage = self.Modules.generatorExtender.extendPage
126
+ if (typeof extendPage === 'function') {
127
+ extendPage(self)
128
+ } else {
129
+ console.warn(`'extendPage' tidak diimplementasikan di extender`)
130
+ }
131
+
132
+ } catch (err) {
133
+ throw err
134
+ }
135
+ }
136
+
137
+
138
+ function listenUserKeys(self) {
139
+ document.addEventListener('keydown', (evt) => {
140
+ const id = Crsl.CurrentSection.Id
141
+ const moduleId = Context.SectionMap[id]
142
+ const module = self.Modules[moduleId]
143
+
144
+ // jika ada dialog yang terbuka, semua event keyboard abaikan dulu, keculai tombol escape
145
+ const dialog = document.querySelector('dialog[open]');
146
+ if (dialog) {
147
+ if (evt.key.toLowerCase()=='escape') {
148
+ dialog.close();
149
+ evt.preventDefault();
150
+ } else if ((evt.ctrlKey || evt.metaKey) && evt.key.toLowerCase() === 's') {
151
+ evt.preventDefault();
152
+ }
153
+ return
154
+ }
155
+
156
+ // Cek apakah tombol Ctrl (atau Cmd di Mac) ditekan bersamaan dengan huruf 'S'
157
+ const key = evt.key.toLowerCase()
158
+ if ((evt.ctrlKey || evt.metaKey) && key === 's') {
159
+ evt.preventDefault(); // Mencegah aksi default (save page)
160
+ keyboardAction(self, module, 'save', evt)
161
+ } else if ((evt.ctrlKey || evt.metaKey) && key === 'n') {
162
+ evt.preventDefault(); // Mencegah aksi default
163
+ keyboardAction(self, module, 'new', evt)
164
+ } else if ( key ==='escape') {
165
+ evt.preventDefault();
166
+ keyboardAction(self, module, 'escape', evt)
167
+ } else if ( key === 'f2' ) {
168
+ keyboardAction(self, module, 'togleEdit', evt)
169
+ } else if ( key === 'arrowup' ) {
170
+ keyboardAction(self, module, 'up', evt)
171
+ } else if ( key === 'arrowdown' ) {
172
+ keyboardAction(self, module, 'down', evt)
173
+ } else if ( key === 'arrowright' ) {
174
+ keyboardAction(self, module, 'right', evt)
175
+ } else if ( key === 'arrowleft' ) {
176
+ keyboardAction(self, module, 'left', evt)
177
+ } else if ( key === 'enter' ) {
178
+ keyboardAction(self, module, 'enter', evt)
179
+ }
180
+ });
181
+ }
182
+
183
+
184
+ function keyboardAction(self, module, actionName, evt) {
185
+
186
+ if (module!=null) {
187
+ module.keyboardAction(self, actionName, evt)
188
+ } else {
189
+ // untuk keperluan log dan about, saat escape: back
190
+ if (actionName=='escape') {
191
+ Crsl.CurrentSection.back()
192
+ }
193
+ }
194
+
195
+ }
Binary file
@@ -0,0 +1,185 @@
1
+ <!--
2
+ * Designer Editor
3
+ * nama program, deskripsi, table utama
4
+ * data2 detil related ke data utama
5
+ * drag and drop componen-component ke masing2 header / detail, kemudian dikonfigurasi
6
+ * -->
7
+ <div id="appgen-datadesign-layout">
8
+ <div id="layout-definition">
9
+ <div class="subtitle" style="grid-column: span 3;">Module Definition</div>
10
+
11
+ <label for="obj_programid">ID</label>
12
+ <input type="text" id="obj_programid" placeholder="[auto-id]" disabled>
13
+
14
+ <!-- kalau mau nambah baru, row span harus disesuaikan -->
15
+ <div id="upload-icon" style="grid-row: span 6;">
16
+ <label>
17
+ change
18
+ <input id="btn_IconUpload" type="file" accept=".svg,.png" style="display: none;" />
19
+ </label>
20
+ </div>
21
+
22
+ <label for="obj_appname">App Name</label>
23
+ <input type="text" id="obj_appname" style="text-transform: lowercase;">
24
+
25
+ <label for="obj_programname">Program Name</label>
26
+ <input type="text" id="obj_programname" style="text-transform: lowercase;">
27
+
28
+ <label for="obj_programname">Title</label>
29
+ <input type="text" id="obj_programtitle">
30
+
31
+ <label for="obj_directory">Directory</label>
32
+ <input type="text" id="obj_directory">
33
+
34
+ <label for="obj_programdescription">Description</label>
35
+ <input type="text" id="obj_programdescription">
36
+
37
+ </div>
38
+
39
+ <div id="layout-action">
40
+ <div class="subtitle">Actions</div>
41
+ <table cellpadding="0" cellspacing="0">
42
+ <tbody id="action-lists">
43
+ </tbody>
44
+ <tfoot>
45
+ <tr>
46
+ <td>
47
+ <input type="textbox" placeholder="action name" id="txt_action_name" class="action-input action-name">
48
+ </td>
49
+ <td>
50
+ <input type="textbox" placeholder="title" id="txt_action_title" class="action-input action-title">
51
+ </td>
52
+ <td>
53
+ <input type="textbox" placeholder="permission" id="txt_action_permission" class="action-input action-permission">
54
+ </td>
55
+ <td>
56
+ <button id="btn_action_add" class="action-button-add">Add</button>
57
+ </td>
58
+ </tr>
59
+ </tfoot>
60
+ </table>
61
+ </div>
62
+
63
+ <!-- Definisi Header Detil -->
64
+ <div id="layout-entity">
65
+ <div class="subtitle">Entites</div>
66
+ <table id="tbl_entity" cellpadding="0" cellspacing="0">
67
+ <thead>
68
+ <tr>
69
+ <th name="col_name">Name</th>
70
+ <th name="col_title">Title</th>
71
+ <th name="col_table">Table</th>
72
+ <th name="col_pk">PK</th>
73
+ <th name="col_btndesign"></th>
74
+ <th name="col_btnremove"></th>
75
+ <th name="col_id">ID</th>
76
+ </tr>
77
+ </thead>
78
+ <tbody id="data-entities">
79
+
80
+ </tbody>
81
+ <tfoot>
82
+ <tr>
83
+ <td colspan="7" style="padding-left: 0;"><button id="btn_addentity">Add Entity</button></td>
84
+ </tr>
85
+ </tfoot>
86
+
87
+ </table>
88
+
89
+ </div>
90
+
91
+ <!-- Table Editor, menerima drag and drop dari component -->
92
+ <div id="layout-editor" class="hidden">
93
+ <div class="subtitle">Data Editor</div>
94
+ <div id="entities-design"></div>
95
+ </div>
96
+
97
+ <!-- Side Bar, untuk daftar komponen yang bisa di drag and drop, dan lain2 -->
98
+ <div id="layout-sidebar" class="hidden">
99
+ <div >
100
+ <div class="subtitle">Components</div>
101
+ <div id="crud-component-list">
102
+ </div>
103
+ <div class="subtitle">Design</div>
104
+ <div class="design-tools-container">
105
+ <a id="btn_ShowSummary" class="design-button">
106
+ <svg version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
107
+ <g fill="#e6e6e6" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
108
+ <path d="m3 40h42v5h-42z"/>
109
+ <path d="m3 31.5h42v5h-42z"/>
110
+ <path d="m3 22h42v5h-42z"/>
111
+ <path d="m3 12.5h42v5h-42z"/>
112
+ <path d="m3 3h42v5h-42z"/>
113
+ </g>
114
+ </svg>
115
+ </a>
116
+ <a id="btn_ShowDetail" class="design-button">
117
+ <svg version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
118
+ <g fill="#e6e6e6" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
119
+ <path d="m3 3h42v16h-42z"/>
120
+ <path d="m3 23h42v10h-42z"/>
121
+ <path d="m3 37h42v8h-42z"/>
122
+ </g>
123
+ </svg>
124
+ </a>
125
+ </div>
126
+ <div class="design-tools-container" style="margin-top: 30px">
127
+ <a id="btn_ShowFields" class="design-button">
128
+ <svg version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
129
+ <rect x="5" y="11" width="39" height="25" fill="#e6e6e6"/>
130
+ <path d="m20.5 10.25h-16.5v27h16.5" fill="none" stroke="#000" stroke-linecap="square" stroke-width="3"/>
131
+ <path d="m38 10.25h6v27h-6" fill="none" stroke="#000" stroke-linecap="square" stroke-width="3"/>
132
+ <path d="m30 3.4251v41.15" fill="none" stroke="#000" stroke-linecap="square" stroke-width="3"/>
133
+ <path d="m25 3.0239h10" fill="none" stroke="#000" stroke-linecap="square" stroke-width="3"/>
134
+ <path d="m25 44.575h10" fill="none" stroke="#000" stroke-linecap="square" stroke-width="3"/>
135
+ <path d="m21.791 30.263h-2.2408l-1.5505-4.2631h-6.8392l-1.5505 4.2631h-2.1346l5.7559-15.296h2.8036zm-4.4391-6.0094-2.7718-7.5091-2.7824 7.5091z" fill="#1a1a1a" stroke-linecap="square" stroke-width="3" aria-label="A"/>
136
+ </svg>
137
+ </a>
138
+
139
+ <a id="btn_ShowUniq" class="design-button">
140
+ <svg version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
141
+ <g fill="#1a1a1a">
142
+ <ellipse cx="24.5" cy="11" rx="16.5" ry="8"/>
143
+ <path d="m18.25 6.4615v30.462l5 5.5385 8.3333-6.9231v-2.7692l-5-2.7692 6.6667-4.1538-6.6667-4.1538 5.4167-4.1538v-11.077z"/>
144
+ </g>
145
+ </svg>
146
+ </a>
147
+
148
+ <a id="btn_ShowSearch" class="design-button">
149
+ <svg version="1.1" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
150
+ <g fill="#e6e6e6" stroke="#000" stroke-linecap="square">
151
+ <circle cx="29.75" cy="18.75" r="13.25" stroke-width="3"/>
152
+ <path d="m15 32-8 7" stroke-width="6"/>
153
+ </g>
154
+ </svg>
155
+ </a>
156
+ </div>
157
+ </div>
158
+ </div>
159
+
160
+ </div>
161
+ <div style="margin-top: 100px" class="hidden">
162
+
163
+
164
+ </div>
165
+
166
+
167
+
168
+
169
+ <div class="footer-buttons-container hidden">
170
+ <div></div>
171
+ <div>
172
+ <button id="generatorEdit-btn_save">Save</button>
173
+
174
+ <button id="generatorEdit-btn_new" data-action="generator-new">New</button>
175
+
176
+ <button id="btnAppGenLoad" class="hidden">
177
+ Import<input id="input-file" type="file" style="display: none;">
178
+ </button>
179
+
180
+ <button id="btnAppGenSave" class="hidden">Export</button>
181
+
182
+ <button id="generatorEdit-btn_generate">Generate</button>
183
+ </div>
184
+ <div></div>
185
+ </div>
@@ -0,0 +1,238 @@
1
+ import Context from './generator-context.mjs'
2
+ import AppGenUI from './appgen-ui.mjs'
3
+ import * as Extender from './generator-ext.mjs'
4
+
5
+
6
+ const CurrentState = {}
7
+ const Crsl = Context.Crsl
8
+ const CurrentSectionId = Context.Sections.generatorEdit
9
+ const CurrentSection = Crsl.Items[CurrentSectionId]
10
+
11
+ const ui = new AppGenUI(Context.app)
12
+ const btn_new = new $fgta5.ActionButton('generatorEdit-btn_new', 'generator-new')
13
+ const btn_save = new $fgta5.ActionButton('generatorEdit-btn_save')
14
+ const btn_generate = new $fgta5.ActionButton('generatorEdit-btn_generate')
15
+
16
+ const obj_appname = document.getElementById('obj_appname')
17
+ const obj_directory = document.getElementById('obj_directory')
18
+
19
+
20
+ export const Section = CurrentSection
21
+
22
+ export async function init(self, args) {
23
+ console.log('initializing generatorEdit ...')
24
+
25
+ CurrentSection.addEventListener($fgta5.Section.EVT_BACKBUTTONCLICK, async (evt)=>{
26
+ backToList(self, evt)
27
+ })
28
+
29
+
30
+ btn_new.addEventListener('click', (evt)=>{ btn_new_click(self, evt)})
31
+ btn_save.addEventListener('click', (evt)=>{ btn_save_click(self, evt)})
32
+ btn_generate.addEventListener('click', (evt)=>{ btn_generate_click(self, evt) })
33
+
34
+ obj_appname.addEventListener('change', (evt)=>{ obj_appname_change(self, evt) })
35
+
36
+ await ui.Init(Context)
37
+
38
+ ui.pauseAutoSave(true)
39
+
40
+ }
41
+
42
+ export async function openSelectedData(self, params) {
43
+ console.log('openSelectedData')
44
+
45
+ let mask = $fgta5.Modal.createMask()
46
+ try {
47
+ const id = params.keyvalue
48
+
49
+ console.log(params)
50
+ const result = await openData(self, id)
51
+ const data = result.generator_data
52
+
53
+ data.id = result.generator_id
54
+
55
+ ui.load(data)
56
+ } catch (err) {
57
+ throw err
58
+ } finally {
59
+ mask.close()
60
+ mask = null
61
+ }
62
+ }
63
+
64
+
65
+ export function keyboardAction(self, actionName) {
66
+ if (actionName=='save') {
67
+ btn_save.click()
68
+ } else if (actionName=='escape') {
69
+ const listSection = Crsl.Items[Context.Sections.generatorList]
70
+ listSection.show({direction:1})
71
+ }
72
+ }
73
+
74
+ async function openData(self, id) {
75
+ const apiOpen = new $fgta5.ApiEndpoint(`/${Context.moduleName}/open`)
76
+ try {
77
+ const result = await apiOpen.execute({ id })
78
+ return result
79
+ } catch (err) {
80
+ CurrentState.currentOpenedId = null
81
+ throw err
82
+ } finally {
83
+ apiOpen.dispose()
84
+ }
85
+ }
86
+
87
+ async function backToList(self, evt) {
88
+ let goback = true
89
+ if (goback) {
90
+ evt.detail.fn_ShowNextSection()
91
+ }
92
+ }
93
+
94
+
95
+ async function obj_appname_change(self, evt) {
96
+ const el = evt.target
97
+ const value = el.value
98
+
99
+ if (Context.appsUrls[value]===undefined) {
100
+ const resp = await $fgta5.MessageBox.error(`nama apps '${value}' tidak teregister di daftar apps`)
101
+ return
102
+ }
103
+
104
+ // console.log(Context.appsUrls[value].directory)
105
+ obj_directory.value = Context.appsUrls[value].directory
106
+ }
107
+
108
+
109
+ async function btn_new_click(self, evt) {
110
+ console.log('btn_new_click')
111
+ const sourceSection = evt.target.getAttribute('data-sectionsource')
112
+ const generatorList = self.Modules.generatorList
113
+ const listsecid = generatorList.Section.Id
114
+ const fromListSection = sourceSection===listsecid
115
+ if (fromListSection) {
116
+ // btn new di klik dari list
117
+ await CurrentSection.show()
118
+
119
+ // cek id, jika tidak kosong, perlu di-reset
120
+ const id = document.getElementById('obj_programid')
121
+ if (id!='') {
122
+ await ui.reset()
123
+ await ui.NewData()
124
+ ui.updateCache()
125
+ }
126
+
127
+ } else {
128
+ const resp = await $fgta5.MessageBox.confirm('apakah anda yakin akan membuat data baru?')
129
+ if (resp=='ok') {
130
+ await ui.reset()
131
+ await ui.NewData()
132
+ ui.updateCache()
133
+ }
134
+ }
135
+
136
+ }
137
+
138
+ async function btn_save_click(self, evt) {
139
+ console.log('btn_save_click')
140
+ const data = await ui.getCurrentData()
141
+
142
+ let mask = $fgta5.Modal.createMask()
143
+ try {
144
+ const result = await Save(self, data)
145
+ ui.setCurrentId(result.generator_id)
146
+
147
+ console.log(result)
148
+ } catch (err) {
149
+ console.error(err)
150
+ $fgta5.MessageBox.error(err.message)
151
+ } finally {
152
+ mask.close()
153
+ mask = null
154
+ }
155
+ }
156
+
157
+
158
+ async function btn_generate_click(self, evt) {
159
+ console.log('btn_generate_click')
160
+ const data = await ui.getCurrentData()
161
+
162
+ let mask = $fgta5.Modal.createMask()
163
+ btn_generate.disabled = true
164
+ ui.pauseAutoSave(true)
165
+ try {
166
+ if (data.id=='') {
167
+ throw new Error('save dahulu sebelum generate')
168
+ }
169
+ const result = await Generate(self, data, mask)
170
+ console.log(result)
171
+ $fgta5.MessageBox.info('done')
172
+ } catch (err) {
173
+ console.error(err)
174
+ $fgta5.MessageBox.error(err.message)
175
+ } finally {
176
+ btn_generate.disabled = false
177
+ ui.pauseAutoSave(false)
178
+ mask.close()
179
+ mask = null
180
+ }
181
+
182
+ }
183
+
184
+
185
+ async function Save(self, data) {
186
+ const url = `/${Context.moduleName}/save`
187
+ try {
188
+ const result = await Module.apiCall(url, { data })
189
+ return result
190
+ } catch (err) {
191
+ throw err
192
+ }
193
+ }
194
+
195
+ async function Generate(self, data, mask) {
196
+ return new Promise(async (resolve, reject)=>{
197
+ const jobId = Date.now()
198
+ const clientId = `${Context.notifierId}-${jobId}`
199
+ const notifierSocket = Context.notifierSocket
200
+ const ws = new WebSocket(`${notifierSocket}/?clientId=${clientId}`);
201
+
202
+ ws.onmessage = (event) => {
203
+ const data = JSON.parse(event.data);
204
+ if (data.status === 'done') {
205
+ ws.close();
206
+ resolve(data);
207
+ } else if (data.status=='error') {
208
+ ws.close();
209
+ reject(new Error(data.info.message))
210
+ } else if (data.status=='message') {
211
+ console.log(data)
212
+ mask.setText(data.info.message)
213
+ } else if (data.status==='timeout') {
214
+ ws.close();
215
+ reject(new Error('generate timeout'));
216
+ }
217
+ };
218
+
219
+ ws.onerror = (err) => {
220
+ ws.close();
221
+ console.error(err)
222
+ reject(err);
223
+ };
224
+
225
+
226
+ const apiGen = new $fgta5.ApiEndpoint(`/${Context.moduleName}/generate`)
227
+ try {
228
+ const result = await apiGen.execute({ data, notifierSocket, clientId })
229
+ console.log(result)
230
+
231
+ // di sini tidak perlu resolve, karena resolve akan menunggu message dari websocket
232
+ } catch (err) {
233
+ reject(err)
234
+ } finally {
235
+ apiGen.dispose()
236
+ }
237
+ })
238
+ }
@@ -0,0 +1,32 @@
1
+ <div class="search-container">
2
+ <div id="generatorList-pnl_search" class="search-parameters">
3
+ <input id="generatorList-txt_appname" fgta5-component="Textbox" placeholder="application" autocomplete="off" spellcheck="false" binding="appname">
4
+ <input id="generatorList-txt_searchtext" fgta5-component="Textbox" placeholder="search" autocomplete="off" spellcheck="false" binding="searchtext">
5
+ </div>
6
+ <button id="generatorList-btn_gridload">Load</button>
7
+ </div>
8
+
9
+ <table id="generatorList-tbl" fgta5-component="Gridview">
10
+ <thead>
11
+ <tr data-header key="generator_id">
12
+ <th data-name="generator_id" binding="generator_id">ID</th>
13
+ <th data-name="generator_modulename" binding="generator_modulename" sorting="true">Module</th>
14
+ <th data-name="generator_appname" binding="generator_appname" sorting="true">Application</th>
15
+ </tr>
16
+ </thead>
17
+ </table>
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+ <div class="footer-buttons-container">
27
+ <div></div>
28
+ <div>
29
+ <button id="generatorList-btn_new" data-action="generator-new" data-sectionsource="generatorList-section">New</button>
30
+ </div>
31
+ <div></div>
32
+ </div>