waibu-db 2.19.0 → 2.20.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.
@@ -5,11 +5,12 @@ async function btnColumns () {
5
5
 
6
6
  return class WdbBtnColumns extends WdbBase {
7
7
  build = async () => {
8
- const { find, get, isEmpty, without } = this.app.lib._
8
+ const { find, get, isEmpty, without, intersection } = this.app.lib._
9
9
  const { jsonStringify } = this.app.waibuMpa
10
10
  const { req } = this.component
11
11
  const qsKey = this.app.waibu.config.qsKey
12
12
  const schema = get(this, 'component.locals.schema', {})
13
+ const data = get(this, 'component.locals.list.data', [])
13
14
  const count = get(this, 'component.locals.list.count', 0)
14
15
  if (count === 0) this.params.attr.triggerDisabled = true
15
16
  if (schema.view.disabled.includes('find')) {
@@ -18,12 +19,13 @@ async function btnColumns () {
18
19
  }
19
20
  let fields = without(get(this, `component.locals._meta.query.${qsKey.fields}`, '').split(','), '')
20
21
  if (isEmpty(fields)) fields = without(schema.view.fields, 'id')
22
+ const allFields = data.length > 0 ? intersection(schema.view.fields, Object.keys(data[0])) : []
21
23
  const items = []
22
24
  this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
23
25
  if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('columns')
24
26
  for (const f of schema.view.fields) {
25
- let prop = find(schema.properties, { name: f })
26
- if (!prop) prop = find(schema.view.calcFields, { name: f })
27
+ if (allFields.length > 0 && !allFields.includes(f)) continue
28
+ const prop = find(schema.properties, { name: f })
27
29
  if (!prop) continue
28
30
  const attr = { 'x-model': 'selected', label: req.t(get(schema, `view.label.${f}`, `field.${f}`)), value: f, labelText: 'nowrap' }
29
31
  if (fields.includes(f)) attr.checked = true
@@ -24,7 +24,8 @@ async function table () {
24
24
  const { escape, attrToArray } = this.app.waibu
25
25
  const { groupAttrs } = this.app.waibuMpa
26
26
  const { isHtmlLink } = this.app.bajoExtra
27
- const { get, omit, set, find, isEmpty, without, merge } = this.app.lib._
27
+ const { getTruncated } = this.app.bajoTemplate
28
+ const { get, omit, set, find, isEmpty, without, merge, intersection } = this.app.lib._
28
29
  const { isSet } = this.app.lib.aneka
29
30
  const group = groupAttrs(this.params.attr, ['body', 'head', 'foot'])
30
31
  this.params.attr = group._
@@ -48,6 +49,9 @@ async function table () {
48
49
  const qsKey = this.app.waibu.config.qsKey
49
50
  let fields = without(get(this, `component.locals._meta.query.${qsKey.fields}`, '').split(','), '')
50
51
  if (isEmpty(fields)) fields = without(schema.view.fields, 'id')
52
+ if (data.length > 0) {
53
+ fields = intersection(fields, Object.keys(data[0]))
54
+ }
51
55
  let sort = this.params.attr.sort ? attrToArray(this.params.attr.sort) : get(this, `component.locals._meta.query.${qsKey.sort}`, '')
52
56
  if (isEmpty(sort) && filter.sort) {
53
57
  const keys = Object.keys(filter.sort)
@@ -140,8 +144,10 @@ async function table () {
140
144
  const noWrap = this.isNoWrap(f, schema, group.body.nowrap) ? 'nowrap' : ''
141
145
  if (this.isRightAligned(f, schema)) attr.text = `align:end ${noWrap}`
142
146
  else attr.text = `${noWrap}`
147
+ if (d._immutable) attr.text += ' color:body-tertiary'
143
148
  const format = get(schema, `view.format.${f}`)
144
149
  if (format) value = await format.call(this, value, d, { params: this.params, req })
150
+ if (['object', 'array'].includes(prop.type) && !isHtmlLink(value)) value = getTruncated(value, 20) // TODO: should be handle by css instead
145
151
  if (!get(schema, 'view.noEscape', []).includes(f) && !isHtmlLink(value)) value = escape(value)
146
152
  const line = await this.component.buildTag({ tag: 'td', attr, html: value })
147
153
  lines.push(line)
@@ -4,8 +4,8 @@ async function form () {
4
4
  const WdbBase = await wdbBase.call(this)
5
5
 
6
6
  return class WdbForm extends WdbBase {
7
- static async handleRo ({ attr = {}, prop = {} } = {}) {
8
- return await this.component.buildTag({ tag: 'formPlaintext', attr, selfCosing: true, noEscape: true })
7
+ static async handleRo ({ attr = {}, prop = {}, widget = {} } = {}) {
8
+ return await this.component.buildTag({ tag: 'formPlaintext', attr, selfCosing: true, noEscape: true }, { prop, widget })
9
9
  }
10
10
 
11
11
  static async handleRw ({ attr = {}, prop = {}, widget = {} } = {}) {
@@ -44,6 +44,7 @@ async function form () {
44
44
  if (v === true) attr[k] = true
45
45
  else attr[k] = v
46
46
  })
47
+ if (['array', 'object'].includes(prop.type)) attr.col = '12-md'
47
48
  attr.label = this.component.req.t(attr.label)
48
49
  const xon = filter(xOns, { field: widget.name })
49
50
  for (const o of xon) {
@@ -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/index.js CHANGED
@@ -129,9 +129,14 @@ async function factory (pkgName) {
129
129
  menu.push({
130
130
  title: req.t(k),
131
131
  children: map(items, item => {
132
+ const params = {
133
+ model: kebabCase(item.name),
134
+ action: 'list'
135
+ }
132
136
  return {
133
137
  title: camelCase(item.name.slice(plugin.alias.length)),
134
- href: `waibuAdmin:/${prefix}/${kebabCase(item.name)}/list`
138
+ href: `waibuAdmin:/${prefix}/:model/:action`,
139
+ params
135
140
  }
136
141
  })
137
142
  })
@@ -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,10 +96,11 @@ 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
101
- if (!prop.ref && ['array', 'object', 'text'].includes(prop.type)) {
103
+ if (!prop.ref && ['object', 'text'].includes(prop.type)) {
102
104
  result.attr.col = '12'
103
105
  result.component = 'form-textarea'
104
106
  result.attr.rows = '3'
@@ -107,26 +109,28 @@ function applyLayout (action, schema, ext) {
107
109
  result.component = 'form-plaintext'
108
110
  result.attr.col = orgCol
109
111
  } else {
112
+ if (prop.type === 'array') {
113
+ result.component = 'form-select-ext'
114
+ result.attr.multiple = true
115
+ result.attr.allowCreate = true
116
+ }
117
+ if (prop.type === 'boolean') {
118
+ result.component = orgCmp ?? 'form-select'
119
+ result.attr.options = 'false:no;true:yes'
120
+ }
110
121
  if (prop.ref) {
111
- result.component = result.component ?? 'wdb-lookup-select'
122
+ result.component = orgCmp ?? 'wdb-lookup-select'
112
123
  if (prop.type === 'array') {
113
124
  result.attr.multiple = true
114
- result.attr.removeBtn = true
115
125
  }
116
126
  }
117
- if (prop.type === 'boolean') {
118
- result.component = result.component ?? 'form-select'
119
- result.attr.options = 'false:no;true:yes'
120
- }
121
127
  if (prop.values) {
122
- const orgCmp = result.component
123
128
  result.component = orgCmp ?? 'form-select'
124
129
  if (prop.type === 'array') {
125
130
  result.component = 'form-select-ext'
126
131
  result.attr.multiple = true
127
- result.attr.col = orgCol
128
132
  result.attr.removeBtn = true
129
- delete result.attr.rows
133
+ delete result.attr.allowCreate
130
134
  }
131
135
  if (typeof prop.values === 'string') result.attr.options = prop.values
132
136
  else result.attr.options = prop.values.map(item => `${item.value}:${item.text}`).join(';')
package/lib/util.js CHANGED
@@ -78,7 +78,7 @@ export async function processHandler ({ action, model, handler, options } = {})
78
78
  }
79
79
 
80
80
  try {
81
- if (options.trx === true) return await model.transaction(handler)
81
+ if (options.trx === true) return await model.transaction(handler, action, options)
82
82
  return await handler()
83
83
  } catch (err) {
84
84
  if (options.suppressError.includes(action)) return suppressedReturn.call(this, err)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "2.19.0",
3
+ "version": "2.20.1",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-05-22
4
+
5
+ - [2.20.1] Bug fix in admin menu
6
+ - [2.20.1] Bug fix in ```wdb-btn-columns``` widget
7
+ - [2.20.1] Bug fix in ```wdb-data-table``` widget
8
+ - [2.20.1] Bug fix in ```wdb-form``` widget
9
+
10
+ ## 2026-05-16
11
+
12
+ - [2.20.0] Change to ```wdb-data-table``` widget to handle immutable rows
13
+ - [2.20.0] Change to ```wdb-lookup-select``` widget to allow new value creation
14
+ - [2.20.0] Change to ```getSchemaExt()``` to allow auto widget creation
15
+
3
16
  ## 2026-05-11
4
17
 
5
18
  - [2.19.0] Updates to match ```dobo@2.23.0``` specs