waibu-db 2.8.1 → 2.9.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.
@@ -0,0 +1 @@
1
+ <c:alert color="warning" t:content="noRecordFound" margin="top-4"/>
@@ -0,0 +1,2 @@
1
+ <c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('details') %>" />
2
+ <!-- include waibuDb.partial:/crud/not-found.html -->
@@ -17,21 +17,14 @@ async function btnColumns () {
17
17
  return
18
18
  }
19
19
  let fields = without(get(this, `component.locals._meta.query.${qsKey.fields}`, '').split(','), '')
20
- if (isEmpty(fields)) fields = schema.view.fields
20
+ if (isEmpty(fields)) fields = without(schema.view.fields, 'id')
21
21
  const items = []
22
22
  this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
23
23
  if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('columns')
24
24
  for (const f of schema.view.fields) {
25
- if (!fields.includes(f)) continue
26
25
  let prop = find(schema.properties, { name: f })
27
26
  if (!prop) prop = find(schema.view.calcFields, { name: f })
28
27
  if (!prop) continue
29
- /*
30
- if (f === 'id') {
31
- items.push(await this.component.buildTag({ tag: 'formCheck', attr: { checked: true, label: req.t('ID'), value: f, disabled: true } }))
32
- continue
33
- }
34
- */
35
28
  const attr = { 'x-model': 'selected', label: req.t(get(schema, `view.label.${f}`, `field.${f}`)), value: f }
36
29
  if (fields.includes(f)) attr.checked = true
37
30
  items.push(await this.component.buildTag({ tag: 'formCheck', attr }))
@@ -74,7 +74,7 @@ async function table () {
74
74
  }
75
75
  const qsKey = this.app.waibu.config.qsKey
76
76
  let fields = without(get(this, `component.locals._meta.query.${qsKey.fields}`, '').split(','), '')
77
- if (isEmpty(fields)) fields = schema.view.fields
77
+ if (isEmpty(fields)) fields = without(schema.view.fields, 'id')
78
78
  let sort = this.params.attr.sort ? attrToArray(this.params.attr.sort) : get(this, `component.locals._meta.query.${qsKey.sort}`, '')
79
79
  if (isEmpty(sort) && filter.sort) {
80
80
  const keys = Object.keys(filter.sort)
@@ -1,5 +1,4 @@
1
- import buildParams from './helper/build-params.js'
2
- import addOnsHandler from './helper/add-ons-handler.js'
1
+ import { buildParams, addOnsHandler } from './helper.js'
3
2
 
4
3
  import addHandler from './add-handler.js'
5
4
  import deleteHandler from './delete-handler.js'
@@ -1,9 +1,9 @@
1
- import attachmentHandler from './helper/attachment-handler.js'
1
+ import { attachmentHandler, notFoundTpl } from './helper.js'
2
2
 
3
3
  async function detailsHandler ({ req, reply, model, params = {}, id, template, addOnsHandler, templateDisabled = 'waibuDb.template:/disabled.html', options = {} } = {}) {
4
4
  const { pascalCase } = this.app.lib.aneka
5
5
  const { getRecord, getSchemaExt } = this.app.waibuDb
6
- const { merge } = this.app.lib._
6
+ const { merge, isEmpty } = this.app.lib._
7
7
  const opts = merge({ refs: '*' }, options.modelOpts)
8
8
  model = pascalCase(model ?? req.params.model)
9
9
  const { schema } = await getSchemaExt(model, 'details', merge({}, { params }, options))
@@ -13,6 +13,7 @@ async function detailsHandler ({ req, reply, model, params = {}, id, template, a
13
13
  id = id ?? req.params.id ?? req.query.id
14
14
  delete req.query.query
15
15
  const resp = await getRecord({ model, req, id, options: opts })
16
+ if (isEmpty(resp.data)) return await reply.view(notFoundTpl, params)
16
17
  const form = resp.data
17
18
  const addOns = addOnsHandler ? await addOnsHandler.call(this.app[req.ns], { req, reply, params, data: resp, schema, options }) : undefined
18
19
  const attachments = await attachmentHandler.call(this, { schema, id, options })
@@ -1,4 +1,4 @@
1
- import attachmentHandler from './helper/attachment-handler.js'
1
+ import { attachmentHandler, notFoundTpl } from './helper.js'
2
2
 
3
3
  async function editHandler ({ req, reply, model, id, params = {}, template, addOnsHandler, templateDisabled = 'waibuDb.template:/disabled.html', options = {} } = {}) {
4
4
  const { pascalCase } = this.app.lib.aneka
@@ -20,6 +20,7 @@ async function editHandler ({ req, reply, model, id, params = {}, template, addO
20
20
  id = id ?? req.params.id ?? req.query.id
21
21
  delete req.query.query
22
22
  const old = await getRecord({ model, req, id, options: opts })
23
+ if (isEmpty(old.data)) return await reply.view(notFoundTpl, params)
23
24
  form = defaultsDeep(req.body, old.data)
24
25
  if (req.method !== 'GET') {
25
26
  form = omit(form, ['_action', '_value'])
@@ -1,47 +1,66 @@
1
- async function addOnsHandler ({ req, reply, data, schema, options = {} }) {
2
- const { escape } = this.app.waibu
3
- const { base64JsonEncode } = this.app.waibu
4
- const { createAggregate } = this.app.waibuDb
5
- const { get, map, pick, pullAt } = this.app.lib._
6
- const opts = map(get(schema, 'view.stat.aggregate', []), item => {
7
- const dbOpts = pick(item, ['fields', 'group', 'aggregate'])
8
- const name = item.name ?? `field.${item.fields[0]}`
9
- return { name, dbOpts }
10
- })
11
- if (opts.length === 0) return []
12
- const dropped = []
13
- for (const idx in opts) {
14
- const o = opts[idx]
15
- try {
16
- const resp = await createAggregate({ model: schema.name, req, reply, options: o.dbOpts })
17
- const data = []
18
- for (const d of resp.data) {
19
- const key = o.dbOpts.fields[0]
20
- data.push({
21
- name: escape(d[key]),
22
- value: d[key + 'Count']
23
- })
24
- }
25
- opts[idx].chartOpts = base64JsonEncode({
26
- tooltip: {
27
- trigger: 'item'
28
- },
29
- series: [{
30
- type: 'pie',
31
- data
32
- }]
33
- })
34
- } catch (err) {
35
- dropped.push(idx)
36
- }
37
- }
38
- if (dropped.length > 0) pullAt(opts, dropped)
39
- return map(opts, o => {
40
- return {
41
- data: { setting: o.chartOpts, name: o.name },
42
- resource: 'waibuDb.partial:/crud/~echarts-window.html'
43
- }
44
- })
45
- }
46
-
47
- export default addOnsHandler
1
+ export async function addOnsHandler ({ req, reply, data, schema, options = {} }) {
2
+ const { escape } = this.app.waibu
3
+ const { base64JsonEncode } = this.app.waibu
4
+ const { createAggregate } = this.app.waibuDb
5
+ const { get, map, pick, pullAt } = this.app.lib._
6
+ const opts = map(get(schema, 'view.stat.aggregate', []), item => {
7
+ const dbOpts = pick(item, ['fields', 'group', 'aggregate'])
8
+ const name = item.name ?? `field.${item.fields[0]}`
9
+ return { name, dbOpts }
10
+ })
11
+ if (opts.length === 0) return []
12
+ const dropped = []
13
+ for (const idx in opts) {
14
+ const o = opts[idx]
15
+ try {
16
+ const resp = await createAggregate({ model: schema.name, req, reply, options: o.dbOpts })
17
+ const data = []
18
+ for (const d of resp.data) {
19
+ const key = o.dbOpts.fields[0]
20
+ data.push({
21
+ name: escape(d[key]),
22
+ value: d[key + 'Count']
23
+ })
24
+ }
25
+ opts[idx].chartOpts = base64JsonEncode({
26
+ tooltip: {
27
+ trigger: 'item'
28
+ },
29
+ series: [{
30
+ type: 'pie',
31
+ data
32
+ }]
33
+ })
34
+ } catch (err) {
35
+ dropped.push(idx)
36
+ }
37
+ }
38
+ if (dropped.length > 0) pullAt(opts, dropped)
39
+ return map(opts, o => {
40
+ return {
41
+ data: { setting: o.chartOpts, name: o.name },
42
+ resource: 'waibuDb.partial:/crud/~echarts-window.html'
43
+ }
44
+ })
45
+ }
46
+
47
+ export async function attachmentHandler ({ schema, id, options = {} }) {
48
+ if (!schema.view.attachment) return []
49
+ const model = this.app.dobo.getModel(schema.name)
50
+ return await model.listAttachment({ id })
51
+ }
52
+
53
+ export function buildParams ({ model, req, reply, action, options = {} }) {
54
+ const { camelCase, kebabCase, map, upperFirst, get } = this.app.lib._
55
+ const [, ...names] = map(kebabCase(model).split('-'), n => upperFirst(n))
56
+ const mdl = this.app.dobo.getModel(model)
57
+ const prefix = this.app.waibuMpa ? this.app.waibuMpa.getPluginTitle(mdl.plugin.ns, req) : mdl.plugin.ns
58
+ const modelTitle = req.t(prefix) + ': ' + req.t(camelCase(names.join(' ')))
59
+ const page = {
60
+ title: req.t(get(req, 'routeOptions.config.title', this.app[mdl.plugin.ns].title)),
61
+ modelTitle
62
+ }
63
+ return { page }
64
+ }
65
+
66
+ export const notFoundTpl = 'waibuDb.template:/crud/not-found.html'
@@ -175,7 +175,7 @@ async function getSchemaExt (modelName, view, options = {}) {
175
175
 
176
176
  const model = isString(modelName) ? this.app.dobo.getModel(modelName) : modelName
177
177
  const schema = pick(model, ['name', 'properties', 'indexes', 'disabled', 'attachment', 'sortables', 'view', 'hidden'])
178
- const base = path.basename(model.file, path.extname(model.file))
178
+ const base = options.base ?? path.basename(model.file, path.extname(model.file))
179
179
  let ext = await readConfig(`${model.plugin.ns}:/extend/waibuDb/schema/${base}.*`, { ignoreError: true, options })
180
180
  const over = await readConfig(`main:/extend/waibuDb/extend/${model.plugin.ns}/schema/${base}.*`, { ignoreError: true, options })
181
181
  ext = defaultsDeep(options.schema ?? {}, over, ext)
package/lib/util.js CHANGED
@@ -57,7 +57,7 @@ export async function getOneRecord (model, id, filter, options) {
57
57
  const { cloneDeep } = this.app.lib._
58
58
  let query = cloneDeep(filter.query || {})
59
59
  query = { $and: [query, { id }] }
60
- const data = await model.findOneRecord({ query }, { dataOnly: true, noHook: true, noDynHook: true, noModelHook: true, forceNoHidden: options.forceNoHidden, trx: options.trx })
60
+ const data = await model.findOneRecord({ query }, { dataOnly: true, forceNoHidden: options.forceNoHidden, trx: options.trx, req: options.req })
61
61
  if (!data && options.throwNotFound) throw this.error('_notFound')
62
62
  return data
63
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "2.8.1",
3
+ "version": "2.9.0",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,8 +1,16 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-03-15
4
+
5
+ - [2.9.0] Add ability to overwrite ```base``` through ```options```
6
+ - [2.9.0] Bug fix in ```wdb-btn-columns``` widget
7
+ - [2.9.0] Bug fix in ```wdb-table``` widget
8
+
3
9
  ## 2026-03-08
4
10
 
5
11
  - [2.8.1] Bug fix in ```build-params.js```
12
+ - [2.8.2] Bug fixes for record not found
13
+ - [2.8.3] Compine all helpers into one single file ```helper.js```
6
14
 
7
15
  ## 2026-03-05
8
16
 
@@ -1,7 +0,0 @@
1
- async function attachmentHandler ({ schema, id, options = {} }) {
2
- if (!schema.view.attachment) return []
3
- const model = this.app.dobo.getModel(schema.name)
4
- return await model.listAttachment({ id })
5
- }
6
-
7
- export default attachmentHandler
@@ -1,14 +0,0 @@
1
- function buildParams ({ model, req, reply, action, options = {} }) {
2
- const { camelCase, kebabCase, map, upperFirst, get } = this.app.lib._
3
- const [, ...names] = map(kebabCase(model).split('-'), n => upperFirst(n))
4
- const mdl = this.app.dobo.getModel(model)
5
- const prefix = this.app.waibuMpa ? this.app.waibuMpa.getPluginTitle(mdl.plugin.ns, req) : mdl.plugin.ns
6
- const modelTitle = req.t(prefix) + ': ' + req.t(camelCase(names.join(' ')))
7
- const page = {
8
- title: req.t(get(req, 'routeOptions.config.title', this.app[mdl.plugin.ns].title)),
9
- modelTitle
10
- }
11
- return { page }
12
- }
13
-
14
- export default buildParams