@es-labs/jslib 0.0.1
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/CHANGELOG.md +4 -0
- package/README.md +42 -0
- package/__test__/services.test.js +32 -0
- package/auth/index.js +226 -0
- package/auth/keyv.js +23 -0
- package/auth/knex.js +29 -0
- package/auth/redis.js +23 -0
- package/comms/email.js +123 -0
- package/comms/nexmo.js +44 -0
- package/comms/telegram.js +43 -0
- package/comms/telegram2/inbound.js +314 -0
- package/comms/telegram2/outbound.js +574 -0
- package/comms/webpush.js +60 -0
- package/config.js +37 -0
- package/express/controller/auth/oauth.js +39 -0
- package/express/controller/auth/oidc.js +87 -0
- package/express/controller/auth/own.js +100 -0
- package/express/controller/auth/saml.js +74 -0
- package/express/upload.js +48 -0
- package/index.js +1 -0
- package/iso/README.md +4 -0
- package/iso/__tests__/csv-utils.spec.js +128 -0
- package/iso/__tests__/datetime.spec.js +101 -0
- package/iso/__tests__/fetch.spec.js +270 -0
- package/iso/csv-utils.js +206 -0
- package/iso/datetime.js +103 -0
- package/iso/fetch.js +129 -0
- package/iso/fetch2.js +180 -0
- package/iso/log-filter.js +17 -0
- package/iso/sleep.js +6 -0
- package/iso/ws.js +63 -0
- package/node/oss-files/oss-uploader-client-fetch.js +258 -0
- package/node/oss-files/oss-uploader-client-fetch.md +31 -0
- package/node/oss-files/oss-uploader-client.js +219 -0
- package/node/oss-files/oss-uploader-server.js +199 -0
- package/node/oss-files/oss-uploader-usage.js +121 -0
- package/node/oss-files/oss-uploader-usage.md +34 -0
- package/node/oss-files/s3-uploader-client.js +217 -0
- package/node/oss-files/s3-uploader-server.js +123 -0
- package/node/oss-files/s3-uploader-usage.js +77 -0
- package/node/oss-files/s3-uploader-usage.md +34 -0
- package/package.json +53 -0
- package/packageInfo.js +9 -0
- package/services/ali.js +279 -0
- package/services/aws.js +194 -0
- package/services/db/__tests__/keyv.spec.js +31 -0
- package/services/db/keyv.js +14 -0
- package/services/db/knex.js +67 -0
- package/services/db/redis.js +51 -0
- package/services/index.js +57 -0
- package/services/mq/README.md +8 -0
- package/services/websocket.js +139 -0
- package/t4t/README.md +1 -0
- package/traps.js +20 -0
- package/utils/__tests__/aes.spec.js +52 -0
- package/utils/aes.js +23 -0
- package/web/UI.md +71 -0
- package/web/bwc-autocomplete.js +211 -0
- package/web/bwc-combobox.js +343 -0
- package/web/bwc-fileupload.js +87 -0
- package/web/bwc-loading-overlay.js +54 -0
- package/web/bwc-t4t-form.js +511 -0
- package/web/bwc-table.js +756 -0
- package/web/fetch.js +129 -0
- package/web/i18n.js +24 -0
- package/web/idle.js +49 -0
- package/web/parse-jwt.js +15 -0
- package/web/pwa.js +84 -0
- package/web/sign-pad.js +164 -0
- package/web/t4t-fe.js +164 -0
- package/web/util.js +126 -0
- package/web/web-cam.js +182 -0
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
// TODO fix
|
|
2
|
+
// onsubmit --> multi select
|
|
3
|
+
// error messages on submit
|
|
4
|
+
|
|
5
|
+
// attributes
|
|
6
|
+
// - mode: add, edit
|
|
7
|
+
//
|
|
8
|
+
// properties
|
|
9
|
+
// - record
|
|
10
|
+
// - config (t4t config)
|
|
11
|
+
//
|
|
12
|
+
// methods
|
|
13
|
+
//
|
|
14
|
+
// events
|
|
15
|
+
|
|
16
|
+
//
|
|
17
|
+
// requires bwc-combobox, debounce, autocomplete
|
|
18
|
+
import './bwc-combobox.js'
|
|
19
|
+
import { debounce } from './util.js'
|
|
20
|
+
import { autocomplete } from './t4t-fe.js'
|
|
21
|
+
|
|
22
|
+
const bulma = {
|
|
23
|
+
// the keys are from t4t cols.<col>.ui.tag
|
|
24
|
+
input: {
|
|
25
|
+
tag: 'div',
|
|
26
|
+
className: 'field',
|
|
27
|
+
children: [
|
|
28
|
+
{ tag: 'label', className: 'label' },
|
|
29
|
+
{ tag: 'div', className: 'control', children: [
|
|
30
|
+
{ tag: 'input-placeholder', className: 'input' },
|
|
31
|
+
] },
|
|
32
|
+
{ tag: 'p', className: 'help is-danger', errorLabel: true }
|
|
33
|
+
]
|
|
34
|
+
}, // end input
|
|
35
|
+
textarea: {
|
|
36
|
+
tag: 'div',
|
|
37
|
+
className: 'field',
|
|
38
|
+
children: [
|
|
39
|
+
{ tag: 'label', className: 'label' },
|
|
40
|
+
{ tag: 'div', className: 'control', children: [
|
|
41
|
+
{ tag: 'input-placeholder', className: 'textarea' },
|
|
42
|
+
] },
|
|
43
|
+
{ tag: 'p', className: 'help is-danger', errorLabel: true }
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
select: { // ugly multiple
|
|
47
|
+
tag: 'div',
|
|
48
|
+
className: 'field',
|
|
49
|
+
children: [
|
|
50
|
+
{
|
|
51
|
+
tag: 'div',
|
|
52
|
+
className: 'control',
|
|
53
|
+
children: [
|
|
54
|
+
{ tag: 'label', className: 'label' },
|
|
55
|
+
{
|
|
56
|
+
tag: 'div',
|
|
57
|
+
className: 'select is-fullwidth', // need to add is-multiple for bulma
|
|
58
|
+
children: [
|
|
59
|
+
{ tag: 'input-placeholder' },
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}, // end select
|
|
66
|
+
'bwc-combobox': {
|
|
67
|
+
tag: 'div',
|
|
68
|
+
className: 'field',
|
|
69
|
+
children: [
|
|
70
|
+
{ tag: 'label', className: 'label' },
|
|
71
|
+
{ tag: 'div', className: 'control has-icons-left', children: [
|
|
72
|
+
{ tag: 'input-placeholder' }, // TODO className = 'input'
|
|
73
|
+
] },
|
|
74
|
+
{ tag: 'p', className: 'help is-danger', errorLabel: true }
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
} // end bulma
|
|
78
|
+
|
|
79
|
+
// Bootstrap - TODO VERIFY
|
|
80
|
+
const bootstrap = {
|
|
81
|
+
input: {
|
|
82
|
+
tag: 'div',
|
|
83
|
+
children: [
|
|
84
|
+
{ tag: 'label', className: 'form-label' },
|
|
85
|
+
{ tag: 'input-placeholder', className: 'form-control' },
|
|
86
|
+
{ tag: 'div', className: 'form-text', errorLabel: true }
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
textarea: {
|
|
90
|
+
tag: 'div',
|
|
91
|
+
children: [
|
|
92
|
+
{ tag: 'label', className: 'form-label' },
|
|
93
|
+
{ tag: 'input-placeholder', className: 'form-control' },
|
|
94
|
+
{ tag: 'div', className: 'form-text', errorLabel: true }
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
select: {
|
|
98
|
+
tag: 'div',
|
|
99
|
+
children: [
|
|
100
|
+
{ tag: 'label', className: 'form-label' },
|
|
101
|
+
{ tag: 'input-placeholder', className: 'form-select' },
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
'bwc-combobox': {
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Mui CSS - TODO VERIFY
|
|
109
|
+
const muicss = {
|
|
110
|
+
input: {
|
|
111
|
+
tag: 'div',
|
|
112
|
+
className: 'mui-textfield',
|
|
113
|
+
children: [
|
|
114
|
+
{ tag: 'label', children: [ { tag: 'span', className: 'mui--text-danger', errorLabel: true } ] },
|
|
115
|
+
{ tag: 'input-placeholder' },
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
textarea: {
|
|
119
|
+
tag: 'div',
|
|
120
|
+
className: 'mui-textfield',
|
|
121
|
+
children: [
|
|
122
|
+
{ tag: 'label', children: [ { tag: 'span', className: 'mui--text-danger', errorLabel: true } ] },
|
|
123
|
+
{ tag: 'input-placeholder' },
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
select: {
|
|
127
|
+
tag: 'div',
|
|
128
|
+
className: 'mui-select',
|
|
129
|
+
children: [
|
|
130
|
+
{ tag: 'label' },
|
|
131
|
+
{ tag: 'input-placeholder' },
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
'bwc-combobox': {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const framework = bulma // set as bulma first
|
|
139
|
+
|
|
140
|
+
const template = document.createElement('template')
|
|
141
|
+
|
|
142
|
+
template.innerHTML = /*html*/`
|
|
143
|
+
<style>
|
|
144
|
+
.input-widget {
|
|
145
|
+
/* background-color: red; */
|
|
146
|
+
display: flex;
|
|
147
|
+
flex-direction: row;
|
|
148
|
+
justify-content: center;
|
|
149
|
+
align-items: center;
|
|
150
|
+
height: var(--bwc-t4t-form-height, calc(100vh - 100px));
|
|
151
|
+
}
|
|
152
|
+
.form-area {
|
|
153
|
+
align-self: center;
|
|
154
|
+
/* background-color: lightgray; */
|
|
155
|
+
overflow: auto;
|
|
156
|
+
height: 96%;
|
|
157
|
+
width: 80%;
|
|
158
|
+
}
|
|
159
|
+
.top-area {
|
|
160
|
+
display: flex;
|
|
161
|
+
flex-direction: row;
|
|
162
|
+
justify-content: center;
|
|
163
|
+
align-items: center;
|
|
164
|
+
|
|
165
|
+
padding: 8px;
|
|
166
|
+
position: sticky;
|
|
167
|
+
top: 0px;
|
|
168
|
+
background-color: lightgray;
|
|
169
|
+
z-index: 1;
|
|
170
|
+
}
|
|
171
|
+
.bottom-area {
|
|
172
|
+
display: flex;
|
|
173
|
+
flex-direction: row;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
align-items: center;
|
|
176
|
+
|
|
177
|
+
padding: 8px;
|
|
178
|
+
position: sticky;
|
|
179
|
+
bottom: 0px;
|
|
180
|
+
background-color: lightgray;
|
|
181
|
+
z-index: 1;
|
|
182
|
+
}
|
|
183
|
+
</style>
|
|
184
|
+
<div class="input-widget">
|
|
185
|
+
<form class="form-area" onsubmit="return false;">
|
|
186
|
+
<div class="top-area"><h1>Hello</h1></div>
|
|
187
|
+
<div class="content-area">
|
|
188
|
+
</div>
|
|
189
|
+
<div class="bottom-area">
|
|
190
|
+
<div class="button-group">
|
|
191
|
+
<!-- create buttons here -->
|
|
192
|
+
<button type="submit" class="btn-submit button is-link">Submit</button>
|
|
193
|
+
<button type="button" class="btn-cancel button is-link is-light">Cancel</button>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
<form>
|
|
197
|
+
</div>
|
|
198
|
+
`
|
|
199
|
+
|
|
200
|
+
class BwcT4tForm extends HTMLElement {
|
|
201
|
+
constructor() {
|
|
202
|
+
super()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
#config = [] // from table config property passed in
|
|
206
|
+
#record = {} // from record property passed in
|
|
207
|
+
#xcols = {} // extended column information - info on input element, event, etc...
|
|
208
|
+
|
|
209
|
+
get config () { return this.#config }
|
|
210
|
+
set config (val) { this.#config = val }
|
|
211
|
+
|
|
212
|
+
get record () { return this.#record }
|
|
213
|
+
set record (val) {
|
|
214
|
+
this.#record = val
|
|
215
|
+
if (this.#config && this.#record) {
|
|
216
|
+
// console.log('do render - val (this.#record)', val)
|
|
217
|
+
// console.log('do render - config', this.#config)
|
|
218
|
+
this._render()
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
connectedCallback() {
|
|
223
|
+
// console.log('bwc-t4t-form', this.#config, this.#record)
|
|
224
|
+
this.appendChild(template.content.cloneNode(true))
|
|
225
|
+
if (this.#config && this.#record) {
|
|
226
|
+
this._render()
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
static get observedAttributes() { return ['mode'] }
|
|
231
|
+
|
|
232
|
+
// attributeChangedCallback(name, oldVal, newVal) {
|
|
233
|
+
// switch (name) {
|
|
234
|
+
// case 'mode': break
|
|
235
|
+
// default: break
|
|
236
|
+
// }
|
|
237
|
+
// }
|
|
238
|
+
|
|
239
|
+
get mode() { return this.getAttribute('mode') }
|
|
240
|
+
set mode(val) { this.setAttribute('mode', val) }
|
|
241
|
+
|
|
242
|
+
// node is current node in tree, k = column key, c = column object
|
|
243
|
+
formEl (node, k, c) {
|
|
244
|
+
const mode = this.mode
|
|
245
|
+
if (c[mode] === 'hide') return null
|
|
246
|
+
|
|
247
|
+
// console.log(k, c)
|
|
248
|
+
const { tag, className, attrs, children, errorLabel } = node
|
|
249
|
+
// console.log(tag, className, attrs)
|
|
250
|
+
const elementTag = (tag === 'input-placeholder') ? c.ui.tag : tag // replace for this
|
|
251
|
+
const el = document.createElement(elementTag)
|
|
252
|
+
|
|
253
|
+
if (!this.#xcols[k]) this.#xcols[k] = { }
|
|
254
|
+
|
|
255
|
+
if (tag === 'label') el.innerText = c.label // set the label
|
|
256
|
+
|
|
257
|
+
const inputAttrs = c?.ui?.attrs // set col specific attributes for the input
|
|
258
|
+
if (inputAttrs) {
|
|
259
|
+
for (let key in inputAttrs) {
|
|
260
|
+
el.setAttribute(key, inputAttrs[key])
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// DONE: input - text, integer, decimal, date, time, datetime, file(upload)
|
|
265
|
+
// DONE: select (single and multiple, limited options)
|
|
266
|
+
// DONE: textarea
|
|
267
|
+
// DONE: bwc-combobox (multiple with tags), TODO: need to test more
|
|
268
|
+
|
|
269
|
+
if (['input', 'textarea', 'select', 'bwc-combobox'].includes(elementTag)) { // its an input
|
|
270
|
+
if (c.mode === 'readonly') el.setAttribute('disabled', true) // select is disabled, as it applies to more html tags
|
|
271
|
+
if (c.required) el.setAttribute('required', true)
|
|
272
|
+
|
|
273
|
+
if (elementTag === 'select') { // set the options
|
|
274
|
+
// console.log('select', el.value, k, this.#record[k], this.mode)
|
|
275
|
+
const selectString = (this.mode === 'add') ? c.default || '' : this.#record[k] || ''
|
|
276
|
+
const selected = !selectString ? [] : (c?.ui?.attrs?.multiple) ? selectString.split(',') : [selectString]
|
|
277
|
+
const options = c?.ui?.options
|
|
278
|
+
for (let option of options) {
|
|
279
|
+
const optEl = document.createElement('option')
|
|
280
|
+
optEl.value = option.key
|
|
281
|
+
optEl.innerText = option.text
|
|
282
|
+
if (selected.includes(option.key)) {
|
|
283
|
+
optEl.selected = true // set selected
|
|
284
|
+
}
|
|
285
|
+
el.appendChild(optEl)
|
|
286
|
+
}
|
|
287
|
+
} else { // other input
|
|
288
|
+
if (elementTag === 'bwc-combobox') {
|
|
289
|
+
// console.log('bwc-combobox', this.#record)
|
|
290
|
+
el.setAttribute('listid', 'list-'+k)
|
|
291
|
+
el.setAttribute('object-key', 'key')
|
|
292
|
+
el.setAttribute('object-text', 'text')
|
|
293
|
+
if (c?.ui?.attrs?.multiple) el.setAttribute('multiple', '')
|
|
294
|
+
if (c?.ui?.attrs?.repeat) el.setAttribute('repeat', '')
|
|
295
|
+
if (c?.ui?.attrs?.allowCustomTag) el.setAttribute('allow-custom-tag', '')
|
|
296
|
+
if (c?.ui?.attrs?.tagLimit) el.setAttribute('tag-limit', c.ui.attrs.tagLimit)
|
|
297
|
+
// disbled and required already set
|
|
298
|
+
// TODO set input class
|
|
299
|
+
|
|
300
|
+
el.onload = (e) => { // need to wait for component to load before setting the values
|
|
301
|
+
// console.log('bwc loaded')
|
|
302
|
+
const valueType = c?.ui?.valueType // TODO transform value
|
|
303
|
+
if (c?.ui?.attrs?.multiple) { // can be array in column or join table
|
|
304
|
+
const val = this.mode === 'add' ? c.default : this.#record[k]
|
|
305
|
+
if (valueType === '') {
|
|
306
|
+
el.tags = val.split(',').map(item => ({ key: item, text: item })) || []
|
|
307
|
+
} else { // object
|
|
308
|
+
el.tags = val || []
|
|
309
|
+
}
|
|
310
|
+
} else { // single
|
|
311
|
+
const val = this.mode === 'add' ? c.default : this.#record[k]
|
|
312
|
+
if (valueType === '') {
|
|
313
|
+
el.value = val || ''
|
|
314
|
+
el.selected = val ? { key: val, text: val } : null
|
|
315
|
+
} else { // object
|
|
316
|
+
el.value = val.text || '' // key and text should be same
|
|
317
|
+
el.selected = val || null
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
} // onload end
|
|
321
|
+
|
|
322
|
+
el.onsearch = debounce(async (e) => {
|
|
323
|
+
// this.#xcols['state'].el.value // use this.#xcols to get latest values
|
|
324
|
+
// console.log(e.target.value, k, this.#record) // this.#record does not change until validated and submit
|
|
325
|
+
let parentVal = null
|
|
326
|
+
if (c?.options?.parentCol) {
|
|
327
|
+
const col = this.#xcols[c?.options?.parentCol]
|
|
328
|
+
if (col && col.el) parentVal = col.el.value
|
|
329
|
+
}
|
|
330
|
+
const res = await autocomplete(e.target.value, k, this.#record, parentVal)
|
|
331
|
+
el.items = res
|
|
332
|
+
}, 500)
|
|
333
|
+
el.onselect = (e) => { // onselect works (events handled by DOM), onselected need to use addEventListener
|
|
334
|
+
// TODO reset child value - may cascade down further
|
|
335
|
+
const childColName = c?.options?.childCol
|
|
336
|
+
if (childColName) {
|
|
337
|
+
const col = this.#xcols[childColName]
|
|
338
|
+
const childColObj = this.#config.cols[childColName]
|
|
339
|
+
if (col && col.el) {
|
|
340
|
+
if (childColObj?.ui?.attrs?.multiple) { // multiple
|
|
341
|
+
col.el.tags = []
|
|
342
|
+
} else {
|
|
343
|
+
col.el.value = ''
|
|
344
|
+
col.el.selected = null
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
console.log('t4t combobox onselect', e.detail)
|
|
349
|
+
}
|
|
350
|
+
} else { // input, textarea
|
|
351
|
+
if (this.mode === 'add') { // set the value
|
|
352
|
+
el.value = c.default || ''
|
|
353
|
+
} else if (this.mode === 'edit') {
|
|
354
|
+
// console.log('is FileList',this.#record[k] instanceof FileList, k, el.type === 'file')
|
|
355
|
+
el.value = el.type === 'file' ? '' : (this.#record[k] || '')
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
this.#xcols[k].el = el // set input element
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (errorLabel) {
|
|
363
|
+
this.#xcols[k].errorEl = el
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (className) el.className = className // set classes
|
|
367
|
+
|
|
368
|
+
// Bulma Specific Note (TODO tmprove this): if className has 'select' - it is bulma need to set is-multiple here if is multi select
|
|
369
|
+
if (node?.className && node.className.includes('select')) {
|
|
370
|
+
if (c?.ui?.attrs?.multiple) {
|
|
371
|
+
el.classList.add('is-multiple')
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (attrs) {
|
|
376
|
+
for (let key in attrs) {
|
|
377
|
+
el.setAttribute(key, attrs[key])
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
if (children) {
|
|
381
|
+
children.forEach(child => {
|
|
382
|
+
const childEl = this.formEl(child, k, c)
|
|
383
|
+
if (childEl) el.appendChild(childEl)
|
|
384
|
+
})
|
|
385
|
+
}
|
|
386
|
+
return el
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
_render() {
|
|
390
|
+
try {
|
|
391
|
+
// const el = this.querySelector('#form-wrapper')
|
|
392
|
+
const el = this.querySelector('.content-area')
|
|
393
|
+
if (!el) return // .content-area not found
|
|
394
|
+
el.innerHTML = ''
|
|
395
|
+
const { cols, auto, pk, required, multiKey } = this.#config
|
|
396
|
+
// console.log('this.#record', this.#record)
|
|
397
|
+
for (let col in cols) {
|
|
398
|
+
if (!auto.includes(col)) {
|
|
399
|
+
const c = cols[col]
|
|
400
|
+
// console.log('nonauto', c, this.mode)
|
|
401
|
+
if ((this.mode === 'add' && c.add !== 'hide') || (this.mode === 'edit' && c.edit !== 'hide')) {
|
|
402
|
+
const tagKey = c?.ui?.tag
|
|
403
|
+
if (tagKey) {
|
|
404
|
+
const fieldEl = this.formEl(framework[tagKey], col, c)
|
|
405
|
+
|
|
406
|
+
if (c?.ui?.attrs?.type === 'file' && this.mode === 'edit') { // field is file...
|
|
407
|
+
this.#xcols[col].errorEl.innerText = this.#record[col] || 'No Files Found'
|
|
408
|
+
// console.log(fieldEl, col)
|
|
409
|
+
}
|
|
410
|
+
el.appendChild(fieldEl)
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
// console.log('auto', col)
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const btnSubmit = this.querySelector('.btn-submit')
|
|
419
|
+
// btnSubmit.classList.add('button')
|
|
420
|
+
btnSubmit.onclick = (e) => {
|
|
421
|
+
let error = false
|
|
422
|
+
// console.log('submit clicked')
|
|
423
|
+
e.preventDefault() // e.stopPropagation()
|
|
424
|
+
|
|
425
|
+
// check validity
|
|
426
|
+
for (let col in this.#xcols) {
|
|
427
|
+
if (this.#xcols[col].el) {
|
|
428
|
+
if (this.#xcols[col]?.el?.checkValidity) {
|
|
429
|
+
const valid = this.#xcols[col].el.checkValidity()
|
|
430
|
+
if (!valid) error = true
|
|
431
|
+
if (this.#xcols[col].errorEl) this.#xcols[col].errorEl.innerText = valid ? '' : this.#xcols[col].el.validationMessage
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// console.log(this.#record)
|
|
437
|
+
if (!error) {
|
|
438
|
+
for (let col in this.#xcols) {
|
|
439
|
+
// console.log('this.#xcols', this.#xcols[col].el.tagName)
|
|
440
|
+
const inputEl = this.#xcols[col].el
|
|
441
|
+
if (inputEl) {
|
|
442
|
+
if (inputEl.tagName.toLowerCase() === 'select') {
|
|
443
|
+
// select options, [string] - done, [{ key, text }] - next
|
|
444
|
+
const selected = []
|
|
445
|
+
for (let opt of inputEl.selectedOptions) {
|
|
446
|
+
selected.push(opt.value)
|
|
447
|
+
}
|
|
448
|
+
this.#record[col] = selected.join(',')
|
|
449
|
+
} else if (inputEl.tagName.toLowerCase() === 'bwc-combobox') {
|
|
450
|
+
// TODO set the value
|
|
451
|
+
const c = this.#config.cols[col]
|
|
452
|
+
const val = c?.ui?.attrs?.multiple ? inputEl.tags : inputEl.selected
|
|
453
|
+
const valueType = c?.ui?.valueType
|
|
454
|
+
|
|
455
|
+
if (c?.ui?.attrs?.multiple) { // can be array in column or join table
|
|
456
|
+
if (valueType === '') {
|
|
457
|
+
this.#record[col] = val.map(item => item.text).join(',')
|
|
458
|
+
} else { // object
|
|
459
|
+
this.#record[col] = val
|
|
460
|
+
}
|
|
461
|
+
} else { // single
|
|
462
|
+
if (valueType === '') {
|
|
463
|
+
this.#record[col] = val.text
|
|
464
|
+
} else { // object
|
|
465
|
+
this.#record[col] = val
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
} else { // input, textarea
|
|
469
|
+
this.#record[col] = inputEl.value
|
|
470
|
+
if (inputEl.files) {
|
|
471
|
+
// console.log(inputEl.files instanceof FileList)
|
|
472
|
+
this.#record[col] = inputEl.files
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
// console.log('test submit', this.#record)
|
|
478
|
+
this.dispatchEvent(new CustomEvent('submit', { detail: { data: this.#record } }))
|
|
479
|
+
} else {
|
|
480
|
+
this.dispatchEvent(new CustomEvent('submit', { detail: { error } }))
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const btnCancel = this.querySelector('.btn-cancel')
|
|
485
|
+
// btnCancel.classList.add('button')
|
|
486
|
+
btnCancel.onclick = (e) => {
|
|
487
|
+
e.preventDefault()
|
|
488
|
+
this.dispatchEvent(new CustomEvent('cancel'))
|
|
489
|
+
}
|
|
490
|
+
} catch (e) {
|
|
491
|
+
console.log('bwc-t4t-form', e)
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
customElements.define('bwc-t4t-form', BwcT4tForm) // or bwc-form-t4t
|
|
497
|
+
|
|
498
|
+
/*
|
|
499
|
+
<template v-if="tableCfg.cols[col].input === 'link'">
|
|
500
|
+
<mwc-textfield
|
|
501
|
+
@click="router.push('/' + tableCfg.cols[col].options.to + '?keyval=' + recordObj[showForm].key + '&keycol=' + tableCfg.cols[col].options.relatedCol)"
|
|
502
|
+
disabled
|
|
503
|
+
class="field-item"
|
|
504
|
+
:key="col + index"
|
|
505
|
+
:label="tableCfg.cols[col].label"
|
|
506
|
+
outlined
|
|
507
|
+
type="text"
|
|
508
|
+
v-model="recordObj[showForm][col]"
|
|
509
|
+
></mwc-textfield>
|
|
510
|
+
</template>
|
|
511
|
+
*/
|