waibu-db 1.1.11 → 1.1.13

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.
@@ -3,7 +3,7 @@ async function listHandler ({ req, reply, model, template, params = {}, addOnsHa
3
3
  const { recordFind, getSchemaExt } = this.app.waibuDb
4
4
  const { get, merge, isArray, upperFirst } = this.lib._
5
5
  const qsKey = this.app.waibu.config.qsKey
6
- const options = { count: true }
6
+ const options = { count: true, rels: '*' }
7
7
  model = model ?? pascalCase(req.params.model)
8
8
  const { schema } = await getSchemaExt(model, 'list', { params })
9
9
  if (schema.disabled.includes('find')) return reply.view(templateDisabled, { action: 'list' })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "1.1.11",
3
+ "version": "1.1.13",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,46 @@
1
+ async function formatRow ({ data, req, component, schema, options = {} }) {
2
+ const { get, find, isFunction, cloneDeep } = this.lib._
3
+ const { format, callHandler } = this.app.bajo
4
+ const fields = get(schema, 'view.fields', Object.keys(schema.properties))
5
+ const rec = cloneDeep(data)
6
+ for (const f of fields) {
7
+ if (f === '_rel') continue
8
+ let prop = find(schema.properties, { name: f })
9
+ if (!prop) prop = find(schema.view.calcFields, { name: f })
10
+ if (!prop) continue
11
+ const opts = {
12
+ lang: options.lang ?? (req ? req.lang : undefined),
13
+ longitude: ['lng', 'longitude'].includes(f),
14
+ latitude: ['lat', 'latitude'].includes(f),
15
+ speed: ['speed'].includes(f),
16
+ degree: ['course', 'heading'].includes(f),
17
+ distance: ['distance'].includes(f)
18
+ }
19
+ rec[f] = format(data[f], prop.type, opts)
20
+ const vf = get(schema, `view.valueFormatter.${f}`)
21
+ if (vf) {
22
+ if (isFunction(vf)) rec[f] = await vf.call(req ?? this, data[f], data)
23
+ else rec[f] = await callHandler(vf, req, data[f], data)
24
+ }
25
+ const formatter = get(schema, `view.formatter.${f}`)
26
+ if (formatter && component) {
27
+ if (isFunction(formatter)) rec[f] = await formatter.call(req ?? this, data[f], data)
28
+ else rec[f] = await callHandler(formatter, req, data[f], data)
29
+ rec[f] = await component.buildSentence(rec[f])
30
+ }
31
+ }
32
+ return rec
33
+ }
34
+
35
+ async function formatRecord ({ data, req, schema, component, options = {} }) {
36
+ const { isArray } = this.lib._
37
+ if (!isArray(data)) return await formatRow.call(this, { data, req, schema, component, options })
38
+ const items = []
39
+ for (const d of data) {
40
+ const item = await formatRow.call(this, { data: d, req, schema, component, options })
41
+ items.push(item)
42
+ }
43
+ return items
44
+ }
45
+
46
+ export default formatRecord
@@ -2,8 +2,14 @@ import path from 'path'
2
2
 
3
3
  const defReadonly = ['id', 'createdAt', 'updatedAt']
4
4
 
5
+ const defFormatter = {}
6
+
5
7
  function getCommons (action, schema, ext, opts = {}) {
6
- const { map, get, set, without, uniq } = this.lib._
8
+ const { merge, map, get, set, without, uniq } = this.lib._
9
+ const calcFields = get(ext, `view.${action}.calcFields`, get(ext, 'common.calcFields', []))
10
+ const noEscape = get(ext, `view.${action}.noEscape`, get(ext, 'common.noEscape', []))
11
+ const valueFormatter = get(ext, `view.${action}.valueFormatter`, get(ext, 'common.valueFormatter', {}))
12
+ const formatter = get(ext, `view.${action}.formatter`, get(ext, 'common.formatter', {}))
7
13
  const label = get(ext, `view.${action}.label`, get(ext, 'common.label', {}))
8
14
  const card = get(ext, `view.${action}.card`, get(ext, 'common.card', true))
9
15
  const hidden = get(ext, `view.${action}.hidden`, get(ext, 'common.hidden', []))
@@ -13,15 +19,20 @@ function getCommons (action, schema, ext, opts = {}) {
13
19
  hidden.push(...schema.hidden, ...(opts.hidden ?? []))
14
20
  const allFields = without(map(schema.properties, 'name'), ...hidden)
15
21
  const forFields = get(ext, `view.${action}.fields`, get(ext, 'common.fields', allFields))
22
+ set(schema, 'view.calcFields', calcFields)
23
+ set(schema, 'view.noEscape', noEscape)
24
+ set(schema, 'view.valueFormatter', valueFormatter)
25
+ set(schema, 'view.formatter', merge({}, defFormatter, formatter))
16
26
  set(schema, 'view.stat.aggregate', aggregate)
17
27
  set(schema, 'view.disabled', disabled)
18
28
  set(schema, 'view.x', x)
19
29
  if (schema.disabled.length > 0) schema.view.disabled.push(...schema.disabled)
20
30
  let fields = []
21
31
  for (const f of forFields) {
22
- if (allFields.includes(f)) fields.push(f)
32
+ if (allFields.includes(f) || map(calcFields, 'name').includes(f)) fields.push(f)
23
33
  }
24
34
  fields = uniq(without(fields, ...hidden))
35
+
25
36
  if (action !== 'add' && !fields.includes('id')) fields.unshift('id')
26
37
  let noWrap = get(ext, `view.${action}.noWrap`, get(ext, 'common.noWrap', true))
27
38
  if (noWrap === true) noWrap = fields
@@ -21,15 +21,17 @@ async function table () {
21
21
 
22
22
  build = async () => {
23
23
  const { req } = this.component
24
- const { callHandler } = this.plugin.app.bajo
25
24
  const { escape } = this.plugin.app.waibu
25
+ const { formatRecord } = this.plugin.app.waibuDb
26
26
  const { attrToArray, groupAttrs } = this.plugin.app.waibuMpa
27
- const { get, omit, set, find, isEmpty, without, isFunction, merge } = this.plugin.app.bajo.lib._
27
+ const { get, omit, set, find, isEmpty, without, merge } = this.plugin.app.bajo.lib._
28
28
  const group = groupAttrs(this.params.attr, ['body', 'head', 'foot'])
29
29
  this.params.attr = group._
30
30
  const prettyUrl = this.params.attr.prettyUrl
31
31
 
32
+ const schema = get(this, 'component.locals.schema', {})
32
33
  const data = get(this, 'component.locals.list.data', [])
34
+ const fdata = await formatRecord.call(this.plugin, { data, req, schema, component: this.component })
33
35
  const filter = get(this, 'component.locals.list.filter', {})
34
36
  const count = get(this, 'component.locals.list.count', 0)
35
37
  if (count === 0) {
@@ -38,7 +40,6 @@ async function table () {
38
40
  this.params.html = await this.component.buildSentence(alert)
39
41
  return
40
42
  }
41
- const schema = get(this, 'component.locals.schema', {})
42
43
  const disableds = get(schema, 'view.disabled', [])
43
44
  if (disableds.includes('find')) {
44
45
  this.params.html = ''
@@ -112,7 +113,9 @@ async function table () {
112
113
  html.push(await this.component.buildTag({ tag: 'thead', attr: group.head, html: header }))
113
114
  // body
114
115
  items = []
115
- for (const d of data) {
116
+ for (const idx in data) {
117
+ const d = data[idx]
118
+ const fd = fdata[idx]
116
119
  const lines = []
117
120
  if (selection) {
118
121
  const tag = selection === 'single' ? 'formRadio' : 'formCheck'
@@ -126,41 +129,29 @@ async function table () {
126
129
  let prop = find(schema.properties, { name: f })
127
130
  if (!prop) prop = find(schema.view.calcFields, { name: f })
128
131
  if (!prop) continue
129
- const opts = {}
130
- if (f === 'lng') opts.longitude = true
131
- else if (f === 'lat') opts.latitude = true
132
- let value = req.format(d[f], prop.type, opts)
133
- if (prop.type === 'boolean') {
134
- value = (await this.component.buildTag({ tag: 'icon', attr: { name: `circle${d[f] ? 'Check' : ''}` } })) +
135
- ' ' + (req.t(d[f] ? 'Yes' : 'No'))
136
- } else value = escape(value)
137
132
  let dataValue = d[f] ?? ''
138
133
  if (['datetime'].includes(prop.type)) dataValue = escape(dataValue.toISOString())
139
134
  if (['string', 'text'].includes(prop.type)) dataValue = escape(dataValue)
140
135
  if (['array', 'object'].includes(prop.type)) dataValue = escape(JSON.stringify(d[f]))
141
- const vf = get(schema, `view.valueFormatter.${f}`)
142
- if (vf) {
143
- if (isFunction(vf)) dataValue = escape(await vf(d[f], d))
144
- else dataValue = await callHandler(vf, req, d[f], d)
136
+ let value = fd[f]
137
+ if (prop.type === 'boolean') {
138
+ value = (await this.component.buildTag({ tag: 'icon', attr: { name: `circle${d[f] ? 'Check' : ''}` } })) +
139
+ ' ' + (req.t(d[f] ? 'Yes' : 'No'))
140
+ } else {
141
+ if (!get(schema, 'view.noEscape', []).includes(f)) value = escape(value)
145
142
  }
146
143
  const attr = { dataValue, dataKey: prop.name, dataType: prop.type }
147
144
  if (!disableds.includes('get')) attr.style = { cursor: 'pointer' }
148
145
  const cellFormatter = get(schema, `view.cellFormatter.${f}`)
149
- if (cellFormatter) merge(attr, await cellFormatter(dataValue, d))
146
+ if (cellFormatter) merge(attr, await cellFormatter.call(req, dataValue, d))
150
147
  const noWrap = this.isNoWrap(f, schema, group.body.nowrap) ? 'nowrap' : ''
151
148
  if (this.isRightAligned(f, schema)) attr.text = `align:end ${noWrap}`
152
149
  else attr.text = noWrap
153
150
  const lookup = get(schema, `view.lookup.${f}`)
154
151
  if (lookup) {
155
- const item = find(lookup.values, set({}, lookup.id ?? 'id', value))
152
+ const item = find(lookup.values, set({}, lookup.id ?? 'id', d[f]))
156
153
  if (item) value = req.t(item[lookup.field ?? 'name'])
157
154
  }
158
- const formatter = get(schema, `view.formatter.${f}`)
159
- if (formatter) {
160
- if (isFunction(formatter)) value = await formatter(dataValue, d)
161
- else value = await callHandler(formatter, req, dataValue, d)
162
- value = await this.component.buildSentence(value)
163
- }
164
155
  const line = await this.component.buildTag({ tag: 'td', attr, html: value })
165
156
  lines.push(line)
166
157
  }