@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.
- package/LICENSE +28 -0
- package/README.md +2 -0
- package/jsconfig.json +10 -0
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.css +2 -0
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js +11 -0
- package/libs/fgta5js-dist/fgta5js-v1.8.3.min.js.map +1 -0
- package/libs/fgta5js-dist/fonts/karla-italic-latin-ext.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla-italic-latin.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla-normal-latin-ext.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla-normal-latin.woff2 +0 -0
- package/libs/fgta5js-dist/fonts/karla.css +142 -0
- package/libs/webmodule/module-edit.css +163 -0
- package/libs/webmodule/module-footer.css +22 -0
- package/libs/webmodule/module-list.css +25 -0
- package/libs/webmodule/module.css +52 -0
- package/libs/webmodule/module.js +195 -0
- package/libs/webmodule/pagehelper.mjs +45 -0
- package/modules/generator/appgen-components.mjs +142 -0
- package/modules/generator/appgen-icons.mjs +6 -0
- package/modules/generator/appgen-io.mjs +784 -0
- package/modules/generator/appgen-ui-search.mjs +173 -0
- package/modules/generator/appgen-ui-unique.mjs +153 -0
- package/modules/generator/appgen-ui.mjs +1181 -0
- package/modules/generator/generator-context.mjs +18 -0
- package/modules/generator/generator-designtemplate.html +1508 -0
- package/modules/generator/generator-ext.html +0 -0
- package/modules/generator/generator-ext.mjs +3 -0
- package/modules/generator/generator.css +642 -0
- package/modules/generator/generator.mjs +195 -0
- package/modules/generator/generator.png +0 -0
- package/modules/generator/generatorEdit.html +185 -0
- package/modules/generator/generatorEdit.mjs +238 -0
- package/modules/generator/generatorList.html +32 -0
- package/modules/generator/generatorList.mjs +243 -0
- package/modules/login/login.css +11 -0
- package/modules/login/login.html +12 -0
- package/modules/login/login.mjs +111 -0
- package/package.json +46 -0
- package/percobaan/simmpan-ke-minio.js +24 -0
- package/src/api.js +80 -0
- package/src/apis/generator.api.js +226 -0
- package/src/apis/login.api.js +109 -0
- package/src/bucket.js +24 -0
- package/src/context.js +26 -0
- package/src/datalog.sql +22 -0
- package/src/datarecords.js +0 -0
- package/src/db.js +61 -0
- package/src/generator/createApiExtenderModule.js +54 -0
- package/src/generator/createApiModule.js +218 -0
- package/src/generator/createIcon.js +62 -0
- package/src/generator/createInfoAboutExtender.js +42 -0
- package/src/generator/createInfoLogs.js +41 -0
- package/src/generator/createInfoRecordExtender.js +41 -0
- package/src/generator/createModuleContext.js +48 -0
- package/src/generator/createModuleDetilEditHtml.js +110 -0
- package/src/generator/createModuleDetilEditMjs.js +172 -0
- package/src/generator/createModuleDetilListHtml.js +146 -0
- package/src/generator/createModuleDetilListMjs.js +73 -0
- package/src/generator/createModuleEjs.js +51 -0
- package/src/generator/createModuleExtenderHtml.js +43 -0
- package/src/generator/createModuleExtenderMjs.js +43 -0
- package/src/generator/createModuleHeaderEditHtml.js +148 -0
- package/src/generator/createModuleHeaderEditMjs.js +197 -0
- package/src/generator/createModuleHeaderListHtml.js +144 -0
- package/src/generator/createModuleHeaderListMjs.js +67 -0
- package/src/generator/createModuleMjs.js +67 -0
- package/src/generator/createModuleRollup.js +42 -0
- package/src/generator/createProgramData.js +96 -0
- package/src/generator/createTable.js +156 -0
- package/src/generator/ddl.js +475 -0
- package/src/generator/helper.js +149 -0
- package/src/generator/templates/__rollup-module.ejs +90 -0
- package/src/generator/templates/api-extender-module.js.ejs +0 -0
- package/src/generator/templates/api-module.js.ejs +818 -0
- package/src/generator/templates/module-context.ejs +16 -0
- package/src/generator/templates/module-ext-about.ejs +1 -0
- package/src/generator/templates/module-ext-record.ejs +1 -0
- package/src/generator/templates/module-ext.html.ejs +3 -0
- package/src/generator/templates/module-ext.mjs.ejs +21 -0
- package/src/generator/templates/module-logs.ejs +14 -0
- package/src/generator/templates/module.ejs.ejs +48 -0
- package/src/generator/templates/module.mjs.ejs +256 -0
- package/src/generator/templates/moduleDetilEdit.html.ejs +34 -0
- package/src/generator/templates/moduleDetilEdit.mjs.ejs +792 -0
- package/src/generator/templates/moduleDetilList.html.ejs +26 -0
- package/src/generator/templates/moduleDetilList.mjs.ejs +319 -0
- package/src/generator/templates/moduleHeaderEdit.html.ejs +53 -0
- package/src/generator/templates/moduleHeaderEdit.mjs.ejs +807 -0
- package/src/generator/templates/moduleHeaderList.html.ejs +24 -0
- package/src/generator/templates/moduleHeaderList.mjs.ejs +308 -0
- package/src/generator/templates/sqlAddField.ejs +3 -0
- package/src/generator/templates/sqlAddForeignKey.ejs +12 -0
- package/src/generator/templates/sqlAddUniqueIndex.ejs +4 -0
- package/src/generator/templates/sqlCreateTable.ejs +9 -0
- package/src/generator/templates/sqlDropForeignKey.ejs +3 -0
- package/src/generator/templates/sqlDropUniqueIndex.ejs +4 -0
- package/src/generator/templates/sqlModifyField.ejs +6 -0
- package/src/generator/trygenerate.js +83 -0
- package/src/generator/worker.js +389 -0
- package/src/helper.js +82 -0
- package/src/logger.js +39 -0
- package/src/router.js +84 -0
- package/src/routers/defaultLoginApi.js +29 -0
- package/src/routers/defaultLoginAsset.js +18 -0
- package/src/routers/defaultLoginPage.js +36 -0
- package/src/routers/defaultRootIndex.js +16 -0
- package/src/routers/downloadHandler.js +51 -0
- package/src/routers/fileUploadApi.js +15 -0
- package/src/routers/generatorApi.js +30 -0
- package/src/routers/generatorAsset.js +18 -0
- package/src/routers/generatorPage.js +37 -0
- package/src/routers/handleError.js +43 -0
- package/src/routers/handleModuleNotfound.js +12 -0
- package/src/routers/moduleApi.js +34 -0
- package/src/routers/modulePage.js +102 -0
- package/src/sequencerdoc.js +311 -0
- package/src/sequencerline.js +214 -0
- package/src/session.js +57 -0
- package/src/startup.js +59 -0
- package/src/webapps.js +239 -0
- package/src/workermanager.js +83 -0
- package/templates/_lib_debug.ejs +11 -0
- package/templates/_lib_production.ejs +5 -0
- package/templates/application.page.ejs +143 -0
- package/templates/generator.page.ejs +131 -0
- package/templates/index.page.ejs +24 -0
- package/templates/login.page.ejs +102 -0
- package/templates/moduleError.ejs +16 -0
- package/templates/moduleNotfound.ejs +14 -0
- package/webapps.code-workspace +11 -0
|
@@ -0,0 +1,792 @@
|
|
|
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'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
const CurrentState = {}
|
|
7
|
+
const Crsl = Context.Crsl
|
|
8
|
+
const CurrentSectionId = Context.Sections.<%= modulePart %>
|
|
9
|
+
const CurrentSection = Crsl.Items[CurrentSectionId]
|
|
10
|
+
const Source = Context.Source
|
|
11
|
+
|
|
12
|
+
const TitleWhenNew = 'New <%= title %>'
|
|
13
|
+
const TitleWhenView = 'View <%= title %>'
|
|
14
|
+
const TitleWhenEdit = 'Edit <%= title %>'
|
|
15
|
+
const EditModeText = 'Edit'
|
|
16
|
+
const LockModeText = 'Lock'
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
const btn_edit = new $fgta5.ActionButton('<%= modulePart %>-btn_edit')
|
|
21
|
+
const btn_save = new $fgta5.ActionButton('<%= modulePart %>-btn_save')
|
|
22
|
+
const btn_new = new $fgta5.ActionButton('<%= modulePart %>-btn_new', '<%= moduleSection %>-addrow')
|
|
23
|
+
const btn_del = new $fgta5.ActionButton('<%= modulePart %>-btn_delete', '<%= moduleSection %>-delrow')
|
|
24
|
+
const btn_reset = new $fgta5.ActionButton('<%= modulePart %>-btn_reset')
|
|
25
|
+
const btn_prev = new $fgta5.ActionButton('<%= modulePart %>-btn_prev')
|
|
26
|
+
const btn_next = new $fgta5.ActionButton('<%= modulePart %>-btn_next')
|
|
27
|
+
|
|
28
|
+
const btn_recordstatus = document.getElementById('<%= moduleSection %>-btn_recordstatus')
|
|
29
|
+
const btn_logs = document.getElementById('<%= moduleSection %>-btn_logs')
|
|
30
|
+
|
|
31
|
+
const frm = new $fgta5.Form('<%= modulePart %>-frm');<% fields.forEach(field => { %>
|
|
32
|
+
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')
|
|
37
|
+
|
|
38
|
+
export const Section = CurrentSection
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export async function init(self, args) {
|
|
42
|
+
|
|
43
|
+
CurrentSection.addEventListener($fgta5.Section.EVT_BACKBUTTONCLICK, async (evt)=>{
|
|
44
|
+
backToList(self, evt)
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
frm.addEventListener('locked', (evt) => { frm_locked(self, evt) });
|
|
48
|
+
frm.addEventListener('unlocked', (evt) => { frm_unlocked(self, evt) });
|
|
49
|
+
frm.render()
|
|
50
|
+
|
|
51
|
+
btn_edit.addEventListener('click', (evt)=>{ btn_edit_click(self, evt) })
|
|
52
|
+
btn_save.addEventListener('click', (evt)=>{ btn_save_click(self, evt) })
|
|
53
|
+
btn_new.addEventListener('click', (evt)=>{ btn_new_click(self, evt) })
|
|
54
|
+
btn_del.addEventListener('click', (evt)=>{ btn_del_click(self, evt) })
|
|
55
|
+
btn_reset.addEventListener('click', (evt)=>{ btn_reset_click(self, evt)})
|
|
56
|
+
btn_prev.addEventListener('click', (evt)=>{ btn_prev_click(self, evt)})
|
|
57
|
+
btn_next.addEventListener('click', (evt)=>{ btn_next_click(self, evt)})
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
btn_recordstatus.addEventListener('click', evt=>{ btn_recordstatus_click(self, evt) })
|
|
61
|
+
btn_logs.addEventListener('click', evt=>{ btn_logs_click(self, evt) })
|
|
62
|
+
|
|
63
|
+
CurrentState.headerFormLocked = true
|
|
64
|
+
CurrentState.editDisabled = false
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
<% fieldHandles.forEach(field => { %>
|
|
68
|
+
// <%= field.component %>: <%= field.inputname %><% field.handles.forEach(hnd => { %>
|
|
69
|
+
<%= field.inputname %>.addEventListener('<%= hnd.eventname %>', <% if (hnd.eventname=='selecting') { %>async <% } %>(evt)=>{
|
|
70
|
+
const fn_<%= hnd.eventname %>_name = '<%= field.inputname %>_<%= hnd.eventname %>'
|
|
71
|
+
const fn_<%= hnd.eventname %> = Extender[fn_<%= hnd.eventname %>_name]
|
|
72
|
+
if (typeof fn_<%= field.inputname %>_<%= hnd.eventname %> === 'function') {
|
|
73
|
+
// 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)
|
|
76
|
+
} else {<% if (field.component=='Combobox' && hnd.eventname=='selecting') { %>
|
|
77
|
+
// default selecting
|
|
78
|
+
const cbo = evt.detail.sender
|
|
79
|
+
const dialog = evt.detail.dialog
|
|
80
|
+
const searchtext = evt.detail.searchtext!=null ? evt.detail.searchtext : ''
|
|
81
|
+
const url = `${Context.appsUrls.<%= hnd.appId %>.url}/<%- hnd.path %>`
|
|
82
|
+
const criteria = {
|
|
83
|
+
searchtext: searchtext,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
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]
|
|
88
|
+
if (typeof fn_<%= hnd.eventname %>_criteria === 'function') {
|
|
89
|
+
fn_<%= field.inputname %>_<%= hnd.eventname %>_criteria(self, <%= field.inputname %>, criteria)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
cbo.wait()
|
|
93
|
+
try {
|
|
94
|
+
const result = await Module.apiCall(url, {
|
|
95
|
+
criteria,
|
|
96
|
+
offset: evt.detail.offset,
|
|
97
|
+
limit: evt.detail.limit,
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
for (var row of result.data) {
|
|
101
|
+
evt.detail.addRow(row.<%= hnd.field_value %>, row.<%= hnd.field_text %>, row)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
dialog.setNext(result.nextoffset, result.limit)
|
|
105
|
+
} catch (err) {
|
|
106
|
+
$fgta5.MessageBox.error(err.message)
|
|
107
|
+
} finally {
|
|
108
|
+
cbo.wait(false)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
<% } else { %>
|
|
112
|
+
console.warn('Extender.<%= field.inputname %>_<%= hnd.eventname %> is not implemented')<% } %>
|
|
113
|
+
}
|
|
114
|
+
})<% }) %>
|
|
115
|
+
<% }) %>
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
export async function openSelectedData(self, params) {
|
|
120
|
+
console.log('openSelectedData')
|
|
121
|
+
|
|
122
|
+
let mask = $fgta5.Modal.createMask()
|
|
123
|
+
try {
|
|
124
|
+
<% comboboxList.forEach(cbo => { %><%= cbo.inputname %>.clear()
|
|
125
|
+
<% }) %>
|
|
126
|
+
const id = params.keyvalue
|
|
127
|
+
const data = await openData(self, id)
|
|
128
|
+
|
|
129
|
+
<% if (detilHasUpload) { %>
|
|
130
|
+
dataOpened(self, data)<% } %>
|
|
131
|
+
|
|
132
|
+
CurrentState.currentOpenedId = id
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
// jika posisi header dalam keadaan unlock (bisa edit, perlu cek kondisi data, untuk menentukan bisa diedit atau tidak)
|
|
136
|
+
if (!CurrentState.headerFormLocked) {
|
|
137
|
+
const fn_iseditdisabled_name = '<%= modulePart %>_isEditDisabled'
|
|
138
|
+
const fn_iseditdisabled = Extender[fn_iseditdisabled_name]
|
|
139
|
+
if (typeof fn_iseditdisabled === 'function') {
|
|
140
|
+
const editDisabled = fn_iseditdisabled(self, data)
|
|
141
|
+
CurrentState.editDisabled = editDisabled
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// disable primary key
|
|
146
|
+
setPrimaryKeyState(self, {disabled:true})
|
|
147
|
+
|
|
148
|
+
frm.setData(data)
|
|
149
|
+
frm.acceptChanges()
|
|
150
|
+
frm.lock()
|
|
151
|
+
|
|
152
|
+
const fn_formopened_name = '<%= modulePart %>_formOpened'
|
|
153
|
+
const fn_formopened = Extender[fn_formopened_name]
|
|
154
|
+
if (typeof fn_formopened === 'function') {
|
|
155
|
+
fn_formopened(self, frm, CurrentState)
|
|
156
|
+
}
|
|
157
|
+
} catch (err) {
|
|
158
|
+
CurrentState.currentOpenedId = null
|
|
159
|
+
throw err
|
|
160
|
+
} finally {
|
|
161
|
+
mask.close()
|
|
162
|
+
mask = null
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export function getForm(self) {
|
|
167
|
+
return frm
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export function clearForm(self, text) {
|
|
171
|
+
frm.clear(text)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function headerLocked(self) {
|
|
175
|
+
CurrentState.headerFormLocked = true
|
|
176
|
+
CurrentState.editDisabled = true
|
|
177
|
+
btn_new.disabled = true
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function headerUnlocked(self) {
|
|
181
|
+
CurrentState.headerFormLocked = false
|
|
182
|
+
CurrentState.editDisabled = false
|
|
183
|
+
btn_new.disabled = false
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export function disableNextButton(self, disabled=true) {
|
|
187
|
+
btn_next.disabled = disabled
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export function disablePrevButton(self, disabled=true) {
|
|
191
|
+
btn_prev.disabled = disabled
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function keyboardAction(self, actionName) {
|
|
195
|
+
if (actionName=='save') {
|
|
196
|
+
frm.acceptInput()
|
|
197
|
+
btn_save.click()
|
|
198
|
+
} else if (actionName=='new') {
|
|
199
|
+
frm.acceptInput()
|
|
200
|
+
btn_new.click()
|
|
201
|
+
} else if (actionName=='escape') {
|
|
202
|
+
frm.acceptInput()
|
|
203
|
+
if (frm.isLocked() || frm.isNew()) {
|
|
204
|
+
backToList(self)
|
|
205
|
+
} else {
|
|
206
|
+
btn_edit.click() // untuk lock data
|
|
207
|
+
}
|
|
208
|
+
} else if (actionName=='togleEdit') {
|
|
209
|
+
frm.acceptInput()
|
|
210
|
+
btn_edit.click()
|
|
211
|
+
} else if (actionName=='right') {
|
|
212
|
+
btn_next.click()
|
|
213
|
+
} else if (actionName=='left') {
|
|
214
|
+
btn_prev.click()
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
async function newData(self, datainit) {
|
|
220
|
+
try {
|
|
221
|
+
<% if (detilHasUpload) { %>
|
|
222
|
+
<% uploadFields.forEach(uploadfield => { %>
|
|
223
|
+
<%= uploadfield.inputname %>.setDownloadLink(null)
|
|
224
|
+
|
|
225
|
+
<% }) %><% } %>frm.newData(datainit)
|
|
226
|
+
frm.acceptChanges()
|
|
227
|
+
frm.setAsNewData()
|
|
228
|
+
} catch (err) {
|
|
229
|
+
throw err
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
async function openData(self, id) {
|
|
235
|
+
const url = `/${Context.moduleName}/<%= sectionName %>-open`
|
|
236
|
+
try {
|
|
237
|
+
const result = await Module.apiCall(url, { id })
|
|
238
|
+
return result
|
|
239
|
+
} catch (err) {
|
|
240
|
+
throw err
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function createData(self, data, formData) {
|
|
245
|
+
const url = `/${Context.moduleName}/<%= sectionName %>-create`
|
|
246
|
+
try {
|
|
247
|
+
const result = await Module.apiCall(url, { data, source: Source }, formData)
|
|
248
|
+
return result
|
|
249
|
+
} catch (err) {
|
|
250
|
+
throw err
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function updateData(self, data, formData) {
|
|
255
|
+
const url = `/${Context.moduleName}/<%= sectionName %>-update`
|
|
256
|
+
try {
|
|
257
|
+
const result = await Module.apiCall(url, { data, source: Source }, formData)
|
|
258
|
+
return result
|
|
259
|
+
} catch (err) {
|
|
260
|
+
throw err
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function deleteData(self, id) {
|
|
265
|
+
const url = `/${Context.moduleName}/<%= sectionName %>-delete`
|
|
266
|
+
try {
|
|
267
|
+
const result = await Module.apiCall(url, { id, source: Source })
|
|
268
|
+
return result
|
|
269
|
+
} catch (err) {
|
|
270
|
+
throw err
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
async function backToList(self, evt) {
|
|
276
|
+
// cek apakah ada perubahan data
|
|
277
|
+
let goback = false
|
|
278
|
+
if (frm.isChanged()) {
|
|
279
|
+
// ada perubahan data, konfirmasi apakah mau lanjut back
|
|
280
|
+
var ret = await $fgta5.MessageBox.confirm(Module.BACK_CONFIRM)
|
|
281
|
+
if (ret=='ok') {
|
|
282
|
+
// user melanjutkan back, walaupun data berubah
|
|
283
|
+
// reset dahulu data form
|
|
284
|
+
frm.reset()
|
|
285
|
+
goback = true
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
goback = true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (goback) {
|
|
292
|
+
frm.lock()
|
|
293
|
+
const listId = Context.Sections.<%= moduleSection %>List
|
|
294
|
+
const listSection = Crsl.Items[listId]
|
|
295
|
+
listSection.show({direction: 1})
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
async function frm_locked(self, evt) {
|
|
301
|
+
console.log('frm_locked')
|
|
302
|
+
|
|
303
|
+
CurrentSection.Title = TitleWhenView
|
|
304
|
+
|
|
305
|
+
btn_edit.setText(EditModeText)
|
|
306
|
+
|
|
307
|
+
// todo: cek dulu apakah boleh add/remove rows
|
|
308
|
+
|
|
309
|
+
btn_edit.disabled = false
|
|
310
|
+
btn_save.disabled = true
|
|
311
|
+
btn_new.disabled = false
|
|
312
|
+
btn_del.disabled = true
|
|
313
|
+
btn_reset.disabled = true
|
|
314
|
+
btn_prev.disabled = false
|
|
315
|
+
btn_next.disabled = false
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
// Extender untuk event locked
|
|
319
|
+
const fn_name = '<%= modulePart %>_formLocked'
|
|
320
|
+
const fn = Extender[fn_name]
|
|
321
|
+
if (typeof fn === 'function') {
|
|
322
|
+
fn(self, frm, CurrentState)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// jika heder form dalam kondisi lock,
|
|
326
|
+
// tetap tidak bisa hapus
|
|
327
|
+
if (CurrentState.editDisabled) {
|
|
328
|
+
btn_edit.disabled = true
|
|
329
|
+
btn_new.disabled = true
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async function frm_unlocked(self, evt) {
|
|
335
|
+
console.log('frm_unlocked')
|
|
336
|
+
|
|
337
|
+
if (frm.isNew()) {
|
|
338
|
+
CurrentSection.Title = TitleWhenNew
|
|
339
|
+
|
|
340
|
+
} else {
|
|
341
|
+
CurrentSection.Title = TitleWhenEdit
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
btn_edit.setText(LockModeText)
|
|
345
|
+
|
|
346
|
+
btn_edit.disabled = false
|
|
347
|
+
btn_save.disabled = false
|
|
348
|
+
btn_new.disabled = true
|
|
349
|
+
btn_del.disabled = false
|
|
350
|
+
btn_reset.disabled = false
|
|
351
|
+
btn_prev.disabled = true
|
|
352
|
+
btn_next.disabled = true
|
|
353
|
+
|
|
354
|
+
// Extender untuk event Unlocked
|
|
355
|
+
const fn_name = '<%= modulePart %>_formUnlocked'
|
|
356
|
+
const fn = Extender[fn_name]
|
|
357
|
+
if (typeof fn === 'function') {
|
|
358
|
+
fn(self, frm)
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async function setPrimaryKeyState(self, opt) {
|
|
363
|
+
const obj_pk = frm.getPrimaryInput()
|
|
364
|
+
obj_pk.disabled = opt.disabled===true
|
|
365
|
+
if (opt.placeholder!==undefined) {
|
|
366
|
+
obj_pk.placeholder = opt.placeholder
|
|
367
|
+
}
|
|
368
|
+
if (opt.value!==undefined) {
|
|
369
|
+
obj_pk.value = opt.value
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
<% if (detilHasUpload) { %>
|
|
374
|
+
async function downloadFile(self, objectname, filename) {
|
|
375
|
+
console.log(`downloading ${filename}`)
|
|
376
|
+
const url = `/download`
|
|
377
|
+
try {
|
|
378
|
+
const param = {
|
|
379
|
+
bucketname: Context.moduleName,
|
|
380
|
+
objectname: objectname
|
|
381
|
+
}
|
|
382
|
+
await Module.download(url, param)
|
|
383
|
+
} catch (err) {
|
|
384
|
+
console.error(err)
|
|
385
|
+
await $fgta5.MessageBox.error(err.message)
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
async function dataOpened(self, data) {
|
|
390
|
+
const docid = data.<%= headerPrimaryKey %>
|
|
391
|
+
const rowid = data.<%= detilPrimaryKey %>
|
|
392
|
+
|
|
393
|
+
<% uploadFields.forEach(uploadfield => { %>
|
|
394
|
+
<%= uploadfield.inputname %>.setDownloadLink(data.<%= uploadfield.fieldname %>, async ()=>{
|
|
395
|
+
const filename = data.<%= uploadfield.fieldname %>
|
|
396
|
+
const objectname = `${docid}/<%= entityName %>/${rowid}-<%= uploadfield.fieldname %>`
|
|
397
|
+
await downloadFile(self, objectname, filename)
|
|
398
|
+
})
|
|
399
|
+
<% }) %>
|
|
400
|
+
}
|
|
401
|
+
<% } %>
|
|
402
|
+
|
|
403
|
+
async function btn_edit_click(self, evt) {
|
|
404
|
+
console.log('btn_edit_click')
|
|
405
|
+
|
|
406
|
+
if (frm.isLocked()) {
|
|
407
|
+
// user mau inlock
|
|
408
|
+
frm.lock(false)
|
|
409
|
+
} else {
|
|
410
|
+
if (frm.isChanged() || frm.isNew()) {
|
|
411
|
+
await $fgta5.MessageBox.warning(Module.EDIT_WARNING)
|
|
412
|
+
return
|
|
413
|
+
}
|
|
414
|
+
frm.lock(true)
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
async function btn_new_click(self, evt) {
|
|
420
|
+
console.log('new')
|
|
421
|
+
const sourceSection = evt.target.getAttribute('data-sectionsource')
|
|
422
|
+
|
|
423
|
+
const <%= moduleSection %>List = self.Modules.<%= moduleSection %>List
|
|
424
|
+
const listsecid = <%= moduleSection %>List.Section.Id
|
|
425
|
+
const fromListSection = sourceSection===listsecid
|
|
426
|
+
|
|
427
|
+
if (fromListSection) {
|
|
428
|
+
console.log('tambahkan row baru')
|
|
429
|
+
CurrentSection.setSectionReturn(<%= moduleSection %>List.Section)
|
|
430
|
+
await CurrentSection.show()
|
|
431
|
+
} else {
|
|
432
|
+
// klik new dari form
|
|
433
|
+
let cancel_new = false
|
|
434
|
+
if (frm.isChanged()) {
|
|
435
|
+
const ret = await $fgta5.MessageBox.confirm(Module.NEWDATA_CONFIRM)
|
|
436
|
+
if (ret=='cancel') {
|
|
437
|
+
cancel_new = true
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (cancel_new) {
|
|
441
|
+
return
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (frm.AutoID) {
|
|
446
|
+
setPrimaryKeyState(self, {disabled:true, placeholder:'[AutoID]'})
|
|
447
|
+
} else {
|
|
448
|
+
setPrimaryKeyState(self, {disabled:false, placeholder:'ID'})
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
|
|
452
|
+
try {
|
|
453
|
+
|
|
454
|
+
// ambil id header
|
|
455
|
+
const <%= moduleName %>HeaderEdit = self.Modules.<%= moduleName %>HeaderEdit
|
|
456
|
+
const frmHeader = <%= moduleName %>HeaderEdit.getHeaderForm()
|
|
457
|
+
const header_pk = frmHeader.getPrimaryInput()
|
|
458
|
+
const <%= headerPrimaryKey %> = header_pk.value
|
|
459
|
+
|
|
460
|
+
// inisiasi data baru
|
|
461
|
+
let datainit = {
|
|
462
|
+
<%= headerPrimaryKey %>,<% defaultInits.forEach(setdefault => { %>
|
|
463
|
+
<%- setdefault %>,
|
|
464
|
+
<% }) %>}
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
// jika perlu modifikasi data initial,
|
|
468
|
+
// atau dialog untuk opsi data baru,
|
|
469
|
+
// dapat dibuat di Extender.newData
|
|
470
|
+
const fn_newdata_name = '<%= modulePart %>_newData'
|
|
471
|
+
const fn_newdata = Extender[fn_newdata_name]
|
|
472
|
+
if (typeof fn_newdata === 'function') {
|
|
473
|
+
await fn_newdata(self, datainit, frm)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// buat data baru
|
|
477
|
+
await newData(self, datainit)
|
|
478
|
+
|
|
479
|
+
// buka lock, agar user bisa edit
|
|
480
|
+
frm.lock(false)
|
|
481
|
+
|
|
482
|
+
// matikan tombol edit dan del saat kondisi form adalah data baru
|
|
483
|
+
btn_edit.disabled = true
|
|
484
|
+
btn_del.disabled = true
|
|
485
|
+
} catch (err) {
|
|
486
|
+
console.error(err)
|
|
487
|
+
await $fgta5.MessageBox.error(err.message)
|
|
488
|
+
if (fromListSection) {
|
|
489
|
+
// jika saat tombol baru dipilih saat di list, tampilan kembalikan ke list
|
|
490
|
+
self.Modules.<%= moduleSection %>List.Section.show()
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
async function btn_save_click(self, evt) {
|
|
497
|
+
console.log('btn_save_click')
|
|
498
|
+
|
|
499
|
+
// Extender Autofill
|
|
500
|
+
const fn_autofill_name = '<%= modulePart %>_autofill'
|
|
501
|
+
const fn_autofill = Extender[fn_autofill_name]
|
|
502
|
+
if (typeof fn_autofill === 'function') {
|
|
503
|
+
await fn_autofill(self, frm)
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// cek apakah data valid
|
|
507
|
+
const valid = frm.validate()
|
|
508
|
+
if (!valid) {
|
|
509
|
+
const message = frm.getLastError()
|
|
510
|
+
console.warn(message)
|
|
511
|
+
$fgta5.MessageBox.warning(message)
|
|
512
|
+
return
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
// abaikan jika bukan data baru dan tidak ada perubahan
|
|
517
|
+
let dataToSave
|
|
518
|
+
const isNewData = frm.isNew()
|
|
519
|
+
if (!isNewData) {
|
|
520
|
+
// cek dulu apakah ada perubahaan
|
|
521
|
+
if (!frm.isChanged()) {
|
|
522
|
+
// skip save jika tidak ada perubahan data
|
|
523
|
+
console.log('tidak ada perubahan data, skip save')
|
|
524
|
+
return
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// ambil hanya data yang berubah
|
|
528
|
+
dataToSave = frm.getDataChanged()
|
|
529
|
+
|
|
530
|
+
} else {
|
|
531
|
+
|
|
532
|
+
// untuk posisi data baru, ambil semua data
|
|
533
|
+
dataToSave = frm.getData()
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
// bila ada file, upload filenya
|
|
538
|
+
let formData = null
|
|
539
|
+
const files = frm.getFiles()
|
|
540
|
+
if (files!=null) {
|
|
541
|
+
formData = new FormData();
|
|
542
|
+
for (let name in files) {
|
|
543
|
+
const file = files[name]
|
|
544
|
+
formData.append(name, file)
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
// Extender Saving
|
|
550
|
+
const fn_datasaving_name = '<%= modulePart %>_dataSaving'
|
|
551
|
+
const fn_datasaving = Extender[fn_datasaving_name]
|
|
552
|
+
if (typeof fn_datasaving === 'function') {
|
|
553
|
+
await fn_datasaving(self, dataToSave, frm)
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
let mask = $fgta5.Modal.createMask()
|
|
559
|
+
try {
|
|
560
|
+
let result
|
|
561
|
+
|
|
562
|
+
if (isNewData) {
|
|
563
|
+
result = await createData(self, dataToSave, formData)
|
|
564
|
+
} else {
|
|
565
|
+
result = await updateData(self, dataToSave, formData)
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
console.log('result', result)
|
|
569
|
+
const obj_pk = frm.getPrimaryInput()
|
|
570
|
+
const pk = obj_pk.getBindingData()
|
|
571
|
+
const idValue = result[pk]
|
|
572
|
+
|
|
573
|
+
console.log(`get data id ${idValue}`)
|
|
574
|
+
const data = await openData(self, idValue)
|
|
575
|
+
console.log('data', data)
|
|
576
|
+
|
|
577
|
+
<% if (detilHasUpload) { %>
|
|
578
|
+
dataOpened(self, data)<% } %>
|
|
579
|
+
|
|
580
|
+
CurrentState.currentOpenedId = idValue
|
|
581
|
+
|
|
582
|
+
if (frm.AutoID) {
|
|
583
|
+
console.log('update field ID di form')
|
|
584
|
+
obj_pk.value = idValue
|
|
585
|
+
} else {
|
|
586
|
+
// jika bukan autoID, kunci field PK menjadi disabled
|
|
587
|
+
setPrimaryKeyState(self, {disabled:true})
|
|
588
|
+
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// update form
|
|
592
|
+
frm.setData(data)
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
// Extender Saving
|
|
596
|
+
const fn_datasaved_name = '<%= modulePart %>_dataSaved'
|
|
597
|
+
const fn_datasaved = Extender[fn_datasaved_name]
|
|
598
|
+
if (typeof fn_datasaved === 'function') {
|
|
599
|
+
await fn_datasaved(self, data, frm)
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
// persist perubahan di form
|
|
604
|
+
frm.acceptChanges()
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
if (isNewData) {
|
|
608
|
+
// saat new data, posisi button toggle edit akan disabled
|
|
609
|
+
// setelah berhasil save, nyalakan button edit (untuk lock)
|
|
610
|
+
btn_edit.disabled = false
|
|
611
|
+
|
|
612
|
+
// buat baris baru di grid
|
|
613
|
+
console.log('tamabah baris baru di grid')
|
|
614
|
+
self.Modules.<%= moduleSection %>List.addNewRow(self, data)
|
|
615
|
+
} else {
|
|
616
|
+
console.log('update data baris yang dibuka')
|
|
617
|
+
self.Modules.<%= moduleSection %>List.updateCurrentRow(self, data)
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
} catch (err) {
|
|
621
|
+
console.error(err)
|
|
622
|
+
await $fgta5.MessageBox.error(err.message)
|
|
623
|
+
} finally {
|
|
624
|
+
mask.close()
|
|
625
|
+
mask = null
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async function btn_del_click(self, evt) {
|
|
630
|
+
console.log('btn_del_click')
|
|
631
|
+
|
|
632
|
+
// jika data masih dalam kondisi baru (belum di save,
|
|
633
|
+
// perintah delete harus dibatalkan,
|
|
634
|
+
// karena belum ada data di database)
|
|
635
|
+
const isNewData = frm.isNew()
|
|
636
|
+
if (isNewData) {
|
|
637
|
+
console.log('posisi data baru, skip delete')
|
|
638
|
+
return
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const obj_pk = frm.getPrimaryInput()
|
|
642
|
+
const idValue = obj_pk.value
|
|
643
|
+
|
|
644
|
+
// konfirmasi untuk delete data
|
|
645
|
+
const resp = await $fgta5.MessageBox.confirm(Module.DELETE_CONFIRM + `id: ${idValue}`)
|
|
646
|
+
if (resp!='ok') {
|
|
647
|
+
return
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
console.log('delete data')
|
|
651
|
+
let mask = $fgta5.Modal.createMask()
|
|
652
|
+
try {
|
|
653
|
+
const result = await deleteData(self, idValue)
|
|
654
|
+
|
|
655
|
+
// hapus current row yang dipilih di list
|
|
656
|
+
self.Modules.<%= moduleSection %>List.removeCurrentRow(self)
|
|
657
|
+
|
|
658
|
+
// kembali ke list
|
|
659
|
+
self.Modules.<%= moduleSection %>List.Section.show()
|
|
660
|
+
|
|
661
|
+
|
|
662
|
+
// lock kembali form
|
|
663
|
+
frm.lock()
|
|
664
|
+
|
|
665
|
+
} catch (err) {
|
|
666
|
+
console.error(err)
|
|
667
|
+
await $fgta5.MessageBox.error(err.message)
|
|
668
|
+
} finally {
|
|
669
|
+
mask.close()
|
|
670
|
+
mask = null
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
async function btn_reset_click(self, evt) {
|
|
675
|
+
console.log('btn_reset_click')
|
|
676
|
+
|
|
677
|
+
const isNewData = frm.isNew()
|
|
678
|
+
if (isNewData) {
|
|
679
|
+
// untuk data baru, di reset berarti sama seperti membuat data baru
|
|
680
|
+
console.log('reset: buat data baru')
|
|
681
|
+
newData(self)
|
|
682
|
+
} else {
|
|
683
|
+
if (frm.isChanged()) {
|
|
684
|
+
// ada perubahan data, tampilkan konfirmasi perubahan data
|
|
685
|
+
var resp = await $fgta5.MessageBox.confirm(Module.RESET_CONFIRM)
|
|
686
|
+
if (resp!='ok') {
|
|
687
|
+
// user klik tombil cancel
|
|
688
|
+
console.log('cancel reset')
|
|
689
|
+
return
|
|
690
|
+
}
|
|
691
|
+
console.log('reset form')
|
|
692
|
+
frm.reset()
|
|
693
|
+
} else {
|
|
694
|
+
console.log('tidak ada perubahan data, reset data tidak dieksekusi')
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
async function btn_prev_click(self, evt) {
|
|
701
|
+
console.log('btn_prev_click')
|
|
702
|
+
self.Modules.<%= moduleSection %>List.selectPreviousRow(self)
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
async function btn_next_click(self, evt) {
|
|
706
|
+
console.log('btn_next_click')
|
|
707
|
+
self.Modules.<%= moduleSection %>List.selectNextRow(self)
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
async function btn_recordstatus_click(self, evt) {
|
|
713
|
+
console.log('btn_recordstatus_click')
|
|
714
|
+
const params = {
|
|
715
|
+
Context,
|
|
716
|
+
sectionReturn: CurrentSection
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
pageHelper.openSection(self, 'fRecord-section', params, async ()=>{
|
|
720
|
+
|
|
721
|
+
let mask = $fgta5.Modal.createMask()
|
|
722
|
+
try {
|
|
723
|
+
// ambil data
|
|
724
|
+
const pk = frm.getPrimaryInput()
|
|
725
|
+
const id = pk.value
|
|
726
|
+
const data = await openData(self, id)
|
|
727
|
+
|
|
728
|
+
obj_createby.innerHTML = data._createby
|
|
729
|
+
obj_createdate.innerHTML = data._createdate
|
|
730
|
+
obj_modifyby.innerHTML = data._modifyby
|
|
731
|
+
obj_modifydate.innerHTML = data._modifydate
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
// jika mau menambah beberapa informasi mengenai record,
|
|
735
|
+
// misalnya commit by, postby, dll
|
|
736
|
+
// melalui extender <%= modulePart %>_addRecordInfo
|
|
737
|
+
const fn_addrecordinfo_name = '<%= modulePart %>_addRecordInfo'
|
|
738
|
+
const fn_addrecordinfo = Extender[fn_addrecordinfo_name]
|
|
739
|
+
if (typeof fn_addrecordinfo === 'function') {
|
|
740
|
+
await fn_addrecordinfo(self, data)
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
} catch (err) {
|
|
744
|
+
console.error(err)
|
|
745
|
+
$fgta5.MessageBox.error(err.message)
|
|
746
|
+
} finally {
|
|
747
|
+
mask.close()
|
|
748
|
+
mask = null
|
|
749
|
+
}
|
|
750
|
+
})
|
|
751
|
+
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
async function btn_logs_click(self, evt) {
|
|
755
|
+
const params = {
|
|
756
|
+
Context,
|
|
757
|
+
sectionReturn: CurrentSection
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
pageHelper.openSection(self, 'fLogs-section', params, async ()=>{
|
|
761
|
+
// get log data
|
|
762
|
+
const pk = frm.getPrimaryInput()
|
|
763
|
+
const id = pk.value
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
let mask = $fgta5.Modal.createMask()
|
|
767
|
+
try {
|
|
768
|
+
|
|
769
|
+
const url = `${Context.appsUrls.core.url}/logs/list`
|
|
770
|
+
const criteria = {
|
|
771
|
+
module: Context.moduleName,
|
|
772
|
+
table: '<%= tablename %>',
|
|
773
|
+
id: id
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
const result = await Module.apiCall(url, {
|
|
777
|
+
criteria
|
|
778
|
+
})
|
|
779
|
+
|
|
780
|
+
const sc = document.getElementById('fLogs-section')
|
|
781
|
+
const tbody = sc.querySelector('tbody')
|
|
782
|
+
pageHelper.renderLog(tbody, result.data)
|
|
783
|
+
} catch (err) {
|
|
784
|
+
console.error(err)
|
|
785
|
+
$fgta5.MessageBox.error(err.message)
|
|
786
|
+
} finally {
|
|
787
|
+
mask.close()
|
|
788
|
+
mask = null
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
})
|
|
792
|
+
}
|