waibu-db 2.18.4 → 2.20.0
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/extend/bajoTemplate/partial/crud/_details-attachment.html +1 -1
- package/extend/waibuBootstrap/theme/component/widget/btn-export.js +1 -1
- package/extend/waibuBootstrap/theme/component/widget/data-table.js +12 -9
- package/extend/waibuBootstrap/theme/component/widget/form.js +2 -2
- package/extend/waibuBootstrap/theme/component/widget/lookup-select.js +1 -1
- package/lib/crud/edit-handler.js +1 -4
- package/lib/method/get-schema-ext.js +26 -8
- package/lib/util.js +2 -1
- package/package.json +1 -1
- package/wiki/CHANGES.md +11 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<% if (schema && schema.attachment) { %>
|
|
1
|
+
<% if (schema && schema.options.attachment) { %>
|
|
2
2
|
<c:fieldset <%= schema.view.card === false ? '' : 'card' %> t:legend="attachment" grid-gutter="3">
|
|
3
3
|
<!-- include waibuDb.partial:/crud/_list-attachment.html|<%= JSON.stringify({ readonly: true }) %> -->
|
|
4
4
|
</c:fieldset>
|
|
@@ -51,7 +51,7 @@ async function btnExport () {
|
|
|
51
51
|
let item = {}
|
|
52
52
|
const els = document.querySelectorAll(selector + ' [data-value]')
|
|
53
53
|
for (const el of els) {
|
|
54
|
-
const value = this.options.includes('fvalue') ? el.
|
|
54
|
+
const value = this.options.includes('fvalue') ? el.innerText : wmpa.parseValue(el.dataset.value, el.dataset.type)
|
|
55
55
|
let key = el.getAttribute('name')
|
|
56
56
|
if (this.options.includes('fkey')) {
|
|
57
57
|
try {
|
|
@@ -25,6 +25,7 @@ async function table () {
|
|
|
25
25
|
const { groupAttrs } = this.app.waibuMpa
|
|
26
26
|
const { isHtmlLink } = this.app.bajoExtra
|
|
27
27
|
const { get, omit, set, find, isEmpty, without, merge } = this.app.lib._
|
|
28
|
+
const { isSet } = this.app.lib.aneka
|
|
28
29
|
const group = groupAttrs(this.params.attr, ['body', 'head', 'foot'])
|
|
29
30
|
this.params.attr = group._
|
|
30
31
|
const prettyUrl = this.params.attr.prettyUrl
|
|
@@ -56,13 +57,15 @@ async function table () {
|
|
|
56
57
|
let [sortCol, sortDir] = sort.split(':')
|
|
57
58
|
if (!['-1', '1'].includes(sortDir)) sortDir = '1'
|
|
58
59
|
|
|
59
|
-
let selection
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
let selection = this.params.attr.selection
|
|
61
|
+
if (!isSet(selection)) {
|
|
62
|
+
const canDelete = !disableds.includes('remove')
|
|
63
|
+
const canEdit = !disableds.includes('update')
|
|
64
|
+
const canDetails = !disableds.includes('get')
|
|
65
|
+
if (canEdit || canDetails) selection = 'single'
|
|
66
|
+
if (canDelete) selection = 'multi'
|
|
67
|
+
if (selection) this.params.attr.hover = true
|
|
68
|
+
} else if (!['single', 'multi'].includes(selection)) selection = false
|
|
66
69
|
|
|
67
70
|
this.params.noTag = true
|
|
68
71
|
const html = []
|
|
@@ -129,8 +132,7 @@ async function table () {
|
|
|
129
132
|
let dataValue = d[f]
|
|
130
133
|
if (['datetime'].includes(prop.type) && dataValue instanceof Date && !isNaN(dataValue)) dataValue = escape(dataValue.toISOString())
|
|
131
134
|
else if (['string', 'text', 'array', 'object'].includes(prop.type)) dataValue = escape(dataValue)
|
|
132
|
-
|
|
133
|
-
let value = this.getRefValue({ field: f, data: d, refName }) ?? get(d, `_fmt.${f}`, d[f])
|
|
135
|
+
let value = this.getRefValue({ field: f, data: d, refName: this.getRefName(f) }) ?? get(d, `_fmt.${f}`, d[f])
|
|
134
136
|
const attr = { dataValue, dataKey: prop.name, dataType: prop.type }
|
|
135
137
|
if (!disableds.includes('get')) attr.style = { cursor: 'pointer' }
|
|
136
138
|
const formatCell = get(schema, `view.formatCell.${f}`)
|
|
@@ -138,6 +140,7 @@ async function table () {
|
|
|
138
140
|
const noWrap = this.isNoWrap(f, schema, group.body.nowrap) ? 'nowrap' : ''
|
|
139
141
|
if (this.isRightAligned(f, schema)) attr.text = `align:end ${noWrap}`
|
|
140
142
|
else attr.text = `${noWrap}`
|
|
143
|
+
if (d._immutable) attr.text += ' color:body-tertiary'
|
|
141
144
|
const format = get(schema, `view.format.${f}`)
|
|
142
145
|
if (format) value = await format.call(this, value, d, { params: this.params, req })
|
|
143
146
|
if (!get(schema, 'view.noEscape', []).includes(f) && !isHtmlLink(value)) value = escape(value)
|
|
@@ -20,7 +20,7 @@ async function form () {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
build = async () => {
|
|
23
|
-
const { get, find, filter, forOwn, isEmpty } = this.app.lib._
|
|
23
|
+
const { get, find, filter, forOwn, isEmpty, omit } = this.app.lib._
|
|
24
24
|
const { base64JsonEncode } = this.app.waibu
|
|
25
25
|
const body = []
|
|
26
26
|
const xModels = get(this.schema, 'view.x.model', [])
|
|
@@ -40,7 +40,7 @@ async function form () {
|
|
|
40
40
|
name: widget.name
|
|
41
41
|
}
|
|
42
42
|
if (xModels.includes(widget.name)) attr['x-model'] = widget.name
|
|
43
|
-
forOwn(widget.attr, (v, k) => {
|
|
43
|
+
forOwn(omit(widget.attr, ['url', 'refUrl', 'refName']), (v, k) => {
|
|
44
44
|
if (v === true) attr[k] = true
|
|
45
45
|
else attr[k] = v
|
|
46
46
|
})
|
|
@@ -21,7 +21,7 @@ async function lookupSelect () {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
this.params.attr.url = this.params.attr.url ?? `waibuDb.restapi:/lookup/${kebabCase(ref.model)}`
|
|
24
|
-
const keys = ['url', 'searchField', 'labelField', 'valueField']
|
|
24
|
+
const keys = ['url', 'searchField', 'labelField', 'valueField', 'allowCreate']
|
|
25
25
|
const attr = omit(this.params.attr, keys)
|
|
26
26
|
for (const k of keys) {
|
|
27
27
|
attr[camelCase(`remote ${k}`)] = this.params.attr[k] ?? ref[k] ?? ref.field
|
package/lib/crud/edit-handler.js
CHANGED
|
@@ -5,7 +5,7 @@ async function editHandler ({ req, reply, model, id, params = {}, template, addO
|
|
|
5
5
|
const { updateRecord, getRecord, getSchemaExt } = this.app.waibuDb
|
|
6
6
|
const { buildUrl } = this.app.waibuMpa
|
|
7
7
|
const { defaultsDeep } = this.app.lib.aneka
|
|
8
|
-
const { merge, isEmpty, omit, cloneDeep
|
|
8
|
+
const { merge, isEmpty, omit, cloneDeep } = this.app.lib._
|
|
9
9
|
const opts = merge({}, options.modelOpts)
|
|
10
10
|
let error
|
|
11
11
|
let resp
|
|
@@ -22,9 +22,6 @@ async function editHandler ({ req, reply, model, id, params = {}, template, addO
|
|
|
22
22
|
if (isEmpty(old.data)) return await reply.view(notFoundTpl, params)
|
|
23
23
|
opts._data = old
|
|
24
24
|
const def = cloneDeep(old.data)
|
|
25
|
-
for (const k in def) {
|
|
26
|
-
if (isArray(def[k]) || isPlainObject(def[k])) def[k] = JSON.stringify(def[k])
|
|
27
|
-
}
|
|
28
25
|
form = defaultsDeep({}, req.body, def)
|
|
29
26
|
if (req.method !== 'GET') {
|
|
30
27
|
form = omit(form, ['_action', '_value'])
|
|
@@ -19,7 +19,7 @@ function getCommons (action, schema, ext, options = {}) {
|
|
|
19
19
|
const x = defaultsDeep(get(ext, `view.${action}.x`), get(ext, 'common.x', {}))
|
|
20
20
|
const aggregate = get(ext, `view.${action}.stat.aggregate`, get(ext, 'common.stat.aggregate', []))
|
|
21
21
|
let attachment = get(ext, `view.${action}.attachment`, get(ext, 'common.attachment', schema.attachment))
|
|
22
|
-
if (!schema.attachment || action === 'list') attachment = false
|
|
22
|
+
if (!schema.options.attachment || action === 'list') attachment = false
|
|
23
23
|
hidden.push('siteId', ...schema.hidden, ...(options.hidden ?? []))
|
|
24
24
|
hidden = uniq(hidden)
|
|
25
25
|
pull(hidden, ...forceVisible)
|
|
@@ -37,6 +37,7 @@ function getCommons (action, schema, ext, options = {}) {
|
|
|
37
37
|
if (schema.disabled.length > 0) schema.view.disabled.push(...schema.disabled)
|
|
38
38
|
let fields = []
|
|
39
39
|
for (const f of forFields) {
|
|
40
|
+
if (['_immutable'].includes(f)) continue
|
|
40
41
|
if (allFields.includes(f)) fields.push(f)
|
|
41
42
|
}
|
|
42
43
|
fields = uniq(without(fields, ...hidden))
|
|
@@ -95,26 +96,42 @@ function applyLayout (action, schema, ext) {
|
|
|
95
96
|
const prop = find(schema.properties, { name: f })
|
|
96
97
|
if (!prop) continue
|
|
97
98
|
const result = schema.view.widget[f] ?? {}
|
|
99
|
+
const orgCmp = result.component
|
|
98
100
|
result.name = result.name ?? f
|
|
99
101
|
result.attr = defaultsDeep(result.attr, { col: '4-md', label: `field.${f}` })
|
|
100
|
-
|
|
102
|
+
const orgCol = result.attr.col
|
|
103
|
+
if (!prop.ref && ['object', 'text'].includes(prop.type)) {
|
|
101
104
|
result.attr.col = '12'
|
|
102
105
|
result.component = 'form-textarea'
|
|
103
106
|
result.attr.rows = '3'
|
|
104
107
|
}
|
|
105
108
|
if (action === 'details') {
|
|
106
109
|
result.component = 'form-plaintext'
|
|
110
|
+
result.attr.col = orgCol
|
|
107
111
|
} else {
|
|
108
|
-
if (prop.
|
|
109
|
-
result.component =
|
|
112
|
+
if (prop.type === 'array') {
|
|
113
|
+
result.component = 'form-select-ext'
|
|
114
|
+
result.attr.multiple = true
|
|
115
|
+
result.attr.allowCreate = true
|
|
110
116
|
}
|
|
111
117
|
if (prop.type === 'boolean') {
|
|
112
|
-
result.component =
|
|
118
|
+
result.component = orgCmp ?? 'form-select'
|
|
113
119
|
result.attr.options = 'false:no;true:yes'
|
|
114
120
|
}
|
|
121
|
+
if (prop.ref) {
|
|
122
|
+
result.component = orgCmp ?? 'wdb-lookup-select'
|
|
123
|
+
if (prop.type === 'array') {
|
|
124
|
+
result.attr.multiple = true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
115
127
|
if (prop.values) {
|
|
116
|
-
const orgCmp = result.component
|
|
117
128
|
result.component = orgCmp ?? 'form-select'
|
|
129
|
+
if (prop.type === 'array') {
|
|
130
|
+
result.component = 'form-select-ext'
|
|
131
|
+
result.attr.multiple = true
|
|
132
|
+
result.attr.removeBtn = true
|
|
133
|
+
delete result.attr.allowCreate
|
|
134
|
+
}
|
|
118
135
|
if (typeof prop.values === 'string') result.attr.options = prop.values
|
|
119
136
|
else result.attr.options = prop.values.map(item => `${item.value}:${item.text}`).join(';')
|
|
120
137
|
if (result.attr.options.split(';').length > 8 && !orgCmp) result.component = 'form-select-ext'
|
|
@@ -181,8 +198,9 @@ async function getSchemaExt (modelName, view, options = {}) {
|
|
|
181
198
|
|
|
182
199
|
const model = isString(modelName) ? this.app.dobo.getModel(modelName) : modelName
|
|
183
200
|
const ns = model.plugin.ns
|
|
184
|
-
const schema = pick(model, ['name', 'properties', 'indexes', 'disabled', '
|
|
185
|
-
|
|
201
|
+
const schema = pick(model, ['name', 'properties', 'indexes', 'disabled', 'sortables', 'scanables', 'view', 'hidden', 'options'])
|
|
202
|
+
schema.ns = ns
|
|
203
|
+
const base = options.base ?? path.basename(model.options.file, path.extname(model.options.file))
|
|
186
204
|
const parserOpts = { args: options.args }
|
|
187
205
|
let ext = await readConfig(`${ns}:/extend/waibuDb/schema/${base}.*`, { ns, baseNs: 'waibuDb', parserOpts })
|
|
188
206
|
ext = defaultsDeep(options.schema ?? {}, ext)
|
package/lib/util.js
CHANGED
|
@@ -11,6 +11,7 @@ export async function prepCrud ({ model, id, req, reply, transaction, options =
|
|
|
11
11
|
|
|
12
12
|
const cfgWeb = this.app.waibu.getConfig()
|
|
13
13
|
const opts = cloneDeep(omit(options, ['trx']))
|
|
14
|
+
opts.throwNotFound = true
|
|
14
15
|
if (opts.suppressError === true) opts.suppressError = actions
|
|
15
16
|
else if (isString(opts.suppressError)) opts.suppressError = [opts.suppressError]
|
|
16
17
|
else opts.suppressError = opts.suppressError ?? []
|
|
@@ -77,7 +78,7 @@ export async function processHandler ({ action, model, handler, options } = {})
|
|
|
77
78
|
}
|
|
78
79
|
|
|
79
80
|
try {
|
|
80
|
-
if (options.trx === true) return await model.transaction(handler)
|
|
81
|
+
if (options.trx === true) return await model.transaction(handler, action, options)
|
|
81
82
|
return await handler()
|
|
82
83
|
} catch (err) {
|
|
83
84
|
if (options.suppressError.includes(action)) return suppressedReturn.call(this, err)
|
package/package.json
CHANGED
package/wiki/CHANGES.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changes
|
|
2
2
|
|
|
3
|
+
## 2026-05-16
|
|
4
|
+
|
|
5
|
+
- [2.20.0] Change to ```wdb-data-table``` widget to handle immutable rows
|
|
6
|
+
- [2.20.0] Change to ```wdb-lookup-select``` widget to allow new value creation
|
|
7
|
+
- [2.20.0] Change to ```getSchemaExt()``` to allow auto widget creation
|
|
8
|
+
|
|
9
|
+
## 2026-05-11
|
|
10
|
+
|
|
11
|
+
- [2.19.0] Updates to match ```dobo@2.23.0``` specs
|
|
12
|
+
- [2.19.0] Bug fix in ```wdb-btn-export``` widget
|
|
13
|
+
|
|
3
14
|
## 2026-05-03
|
|
4
15
|
|
|
5
16
|
- [2.18.3] Bug fix in ```wdb-data-table``` widget
|