waibu-db 1.0.7 → 1.0.9

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.
@@ -4,6 +4,7 @@ const defReadonly = ['id', 'createdAt', 'updatedAt']
4
4
 
5
5
  function getCommons (action, schema, ext, opts = {}) {
6
6
  const { map, get, set, without, uniq } = this.app.bajo.lib._
7
+ const label = get(ext, `view.${action}.label`, get(ext, 'common.label', {}))
7
8
  const hidden = get(ext, `view.${action}.hidden`, get(ext, 'common.hidden', []))
8
9
  hidden.push(...schema.hidden, ...(opts.hidden ?? []))
9
10
  const allFields = without(map(schema.properties, 'name'), ...hidden)
@@ -17,7 +18,7 @@ function getCommons (action, schema, ext, opts = {}) {
17
18
  }
18
19
  fields = uniq(without(fields, ...hidden))
19
20
  if (action !== 'add' && !fields.includes('id')) fields.unshift('id')
20
- return { fields, allFields }
21
+ return { fields, allFields, label }
21
22
  }
22
23
 
23
24
  function autoLayout ({ action, schema, ext, layout, allWidgets }) {
@@ -58,7 +59,7 @@ function customLayout ({ action, schema, ext, layout, allWidgets, readonly }) {
58
59
 
59
60
  function applyLayout (action, schema, ext) {
60
61
  const { set, get, isEmpty, map, find } = this.app.bajo.lib._
61
- const { fields } = getCommons.call(this, action, schema, ext)
62
+ const { fields, label } = getCommons.call(this, action, schema, ext)
62
63
  const layout = get(ext, `view.${action}.layout`, get(ext, 'common.layout', []))
63
64
  const readonly = get(ext, `view.${action}.readonly`, get(ext, 'common.readonly', defReadonly))
64
65
  const allWidgets = map(fields, f => {
@@ -89,12 +90,13 @@ function applyLayout (action, schema, ext) {
89
90
  else customLayout.call(this, { layout, allWidgets, schema, action, ext, readonly })
90
91
  set(schema, 'view.layout', layout)
91
92
  set(schema, 'view.fields', fields)
93
+ set(schema, 'view.label', label)
92
94
  }
93
95
 
94
96
  const handler = {
95
97
  list: async function (schema, ext, opts) {
96
98
  const { get, set } = this.app.bajo.lib._
97
- const { fields } = getCommons.call(this, 'list', schema, ext, opts)
99
+ const { fields, label } = getCommons.call(this, 'list', schema, ext, opts)
98
100
  const qsFields = []
99
101
  for (const f of get(schema, 'view.qs.fields', '').split(',')) {
100
102
  if (fields.includes(f)) qsFields.push(f)
@@ -102,6 +104,7 @@ const handler = {
102
104
  let [col, dir] = get(schema, 'view.qs.sort', '').split(':')
103
105
  if (!fields.includes(col) || !col) col = 'id'
104
106
  if (!['1', '-1'].includes(dir)) dir = '1'
107
+ set(schema, 'view.label', label)
105
108
  set(schema, 'view.fields', fields)
106
109
  set(schema, 'view.qs.fields', qsFields.join(','))
107
110
  set(schema, 'view.qs.sort', `${col}:${dir}`)
@@ -2,17 +2,13 @@ import prepCrud from '../../../lib/prep-crud.js'
2
2
 
3
3
  async function find ({ model, req, reply, options = {} }) {
4
4
  const { recordFindOne, attachmentFind } = this.app.dobo
5
- const { parseFilter } = this.app.waibu
6
- const { name, opts } = prepCrud.call(this, { model, req, options, args: ['model'] })
7
- const cfgWeb = this.app.waibu.config
8
- opts.bboxLatField = req.query[cfgWeb.qsKey.bboxLatField]
9
- opts.bboxLngField = req.query[cfgWeb.qsKey.bboxLngField]
10
- const filter = parseFilter(req)
5
+ const { name, opts, filter } = prepCrud.call(this, { model, req, options, args: ['model'] })
11
6
  const ret = await recordFindOne(name, filter, opts)
12
- ret.filter = filter
13
7
  const { attachment, stats, mimeType } = req.query
14
8
  if (attachment) {
15
- ret.data._attachment = await attachmentFind(name, ret.data.id, { stats, mimeType })
9
+ for (const d of ret.data) {
10
+ d._attachment = await attachmentFind(name, d.id, { stats, mimeType })
11
+ }
16
12
  }
17
13
  return ret
18
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -24,7 +24,7 @@ async function btnColumns () {
24
24
  items.push(await this.component.buildTag({ tag: 'formCheck', attr: { checked: true, label: req.t('ID'), value: f, disabled: true } }))
25
25
  continue
26
26
  }
27
- const attr = { 'x-model': 'selected', label: req.t(`field.${f}`), value: f }
27
+ const attr = { 'x-model': 'selected', label: req.t(get(schema, `view.label.${f}`, `field.${f}`)), value: f }
28
28
  if (fields.includes(f)) attr.checked = true
29
29
  items.push(await this.component.buildTag({ tag: 'formCheck', attr }))
30
30
  }
@@ -46,6 +46,7 @@ async function btnColumns () {
46
46
  html.push('</form>')
47
47
  this.params.attr.autoClose = 'outside'
48
48
  this.params.attr.triggerColor = this.params.attr.color
49
+ this.params.attr.menudir = this.params.attr.menudir ?? 'end'
49
50
  this.params.html = await this.component.buildTag({ tag: 'dropdown', attr: this.params.attr, html: html.join('\n') })
50
51
  this.params.noTag = true
51
52
  }
@@ -22,6 +22,7 @@ async function btnDelete () {
22
22
  this.params.attr['x-data'] = `{
23
23
  selected: [],
24
24
  remove (modalId, ids) {
25
+ ids = JSON.parse(wmpa.fromBase64(ids)).join(',')
25
26
  wmpa.postForm({ ids }, '${this.component.buildUrl({ base: 'delete' })}')
26
27
  }
27
28
  }`
@@ -32,9 +32,10 @@ async function query () {
32
32
  if (ops.length === 0) continue
33
33
  const sels = ops.map(o => `<c:option>${o}</c:option>`)
34
34
  models.push(`${f}Op: 'eq'`, `${f}Val: ''`)
35
+ const label = this.component.req.t(get(schema, `view.label.${f}`, `field.${f}`))
35
36
  columns.push(`
36
37
  <c:grid-col col="4-md" flex="align-items:center">
37
- <c:form-check x-model="selected" t:label="field.${f}" value="${f}" />
38
+ <c:form-check x-model="selected" t:label="${label}" value="${f}" />
38
39
  </c:grid-col>
39
40
  <c:grid-col col="3-md">
40
41
  <c:form-select x-model="${f}Op">
@@ -6,9 +6,10 @@ async function table () {
6
6
  return class WdbTable extends WdbBase {
7
7
  isRightAligned (field, schema) {
8
8
  const { get, find } = this.plugin.app.bajo.lib._
9
- const type = find(schema.properties, { name: field }).type
9
+ const prop = find(schema.properties, { name: field })
10
+ if (!prop) return false
10
11
  let value = get(schema, 'view.alignEnd', []).includes(field)
11
- if (!value) value = ['smallint', 'integer', 'float', 'double'].includes(type)
12
+ if (!value) value = ['smallint', 'integer', 'float', 'double'].includes(prop.type)
12
13
  return value
13
14
  }
14
15
 
@@ -19,15 +20,18 @@ async function table () {
19
20
 
20
21
  async build () {
21
22
  const { req } = this.component
23
+ const { callHandler } = this.plugin.app.bajo
22
24
  const { escape } = this.plugin.app.waibu
23
25
  const { attrToArray, groupAttrs } = this.plugin.app.waibuMpa
24
- const { get, omit, set, find, isEmpty, without } = this.plugin.app.bajo.lib._
26
+ const { get, omit, set, find, isEmpty, without, isFunction } = this.plugin.app.bajo.lib._
25
27
  const group = groupAttrs(this.params.attr, ['body', 'head', 'foot'])
26
28
  this.params.attr = group._
29
+ const prettyUrl = this.params.attr.prettyUrl
27
30
 
28
31
  const data = get(this, 'component.locals.list.data', [])
29
32
  const schema = get(this, 'component.locals.schema', {})
30
- if (schema.view.disabled.includes('find')) {
33
+ const disableds = get(schema, 'view.disabled', [])
34
+ if (disableds.includes('find')) {
31
35
  this.params.html = ''
32
36
  return
33
37
  }
@@ -40,8 +44,8 @@ async function table () {
40
44
  if (!['-1', '1'].includes(sortDir)) sortDir = '1'
41
45
 
42
46
  let selection
43
- const canDelete = !schema.view.disabled.includes('remove')
44
- const canEdit = !schema.view.disabled.includes('update')
47
+ const canDelete = !disableds.includes('remove')
48
+ const canEdit = !disableds.includes('update')
45
49
  if (canEdit) selection = 'single'
46
50
  if (canDelete) selection = 'multi'
47
51
  if (selection) this.params.attr.hover = true
@@ -53,7 +57,8 @@ async function table () {
53
57
  for (const f of schema.view.fields) {
54
58
  if (!fields.includes(f)) continue
55
59
  const prop = find(schema.properties, { name: f })
56
- let head = req.t(`field.${f}`)
60
+ if (!prop) continue
61
+ let head = req.t(get(schema, `view.label.${f}`, `field.${f}`))
57
62
  if (!this.params.attr.noSort && (schema.sortables ?? []).includes(f)) {
58
63
  let sortItem = `${f}:-1`
59
64
  let icon = this.params.attr.sortUpIcon ?? 'caretUp'
@@ -65,7 +70,7 @@ async function table () {
65
70
  const href = this.component.buildUrl({ params: item })
66
71
  const attr = this.isRightAligned(f, schema) ? { text: 'align:end' } : {}
67
72
  const content = [
68
- await this.component.buildTag({ tag: 'div', attr, html: req.t(`field.${f}`) }),
73
+ await this.component.buildTag({ tag: 'div', attr, html: head }),
69
74
  await this.component.buildTag({ tag: 'a', attr: { icon, href }, prepend: '<div class="ms-1">', append: '</div>' })
70
75
  ]
71
76
  head = await this.component.buildTag({ tag: 'div', attr: { flex: 'justify-content:between align-items:end' }, html: content.join('\n') })
@@ -95,11 +100,14 @@ async function table () {
95
100
  if (selection) {
96
101
  const tag = selection === 'single' ? 'formRadio' : 'formCheck'
97
102
  const attr = { 'x-model': 'selected', name: '_rt', value: d.id, noLabel: true, noWrapper: true }
98
- lines.push(await this.component.buildTag({ tag, attr, prepend: '<td>', append: '</td>' }))
103
+ const type = find(schema.properties, { name: 'id' }).type
104
+ const prepend = `<td data-value="${d.id}" data-key="id" data-type="${type}">`
105
+ lines.push(await this.component.buildTag({ tag, attr, prepend, append: '</td>' }))
99
106
  }
100
107
  for (const f of schema.view.fields) {
101
- const prop = find(schema.properties, { name: f })
102
108
  if (!fields.includes(f)) continue
109
+ const prop = find(schema.properties, { name: f })
110
+ if (!prop) continue
103
111
  const opts = {}
104
112
  if (f === 'lng') opts.longitude = true
105
113
  else if (f === 'lat') opts.latitude = true
@@ -111,27 +119,31 @@ async function table () {
111
119
  let dataValue = d[f] ?? ''
112
120
  if (['string', 'text'].includes(prop.type)) dataValue = escape(dataValue)
113
121
  if (['array', 'object'].includes(prop.type)) dataValue = escape(JSON.stringify(d[f]))
114
- const attr = { dataValue }
122
+ const attr = { dataValue, dataKey: prop.name, dataType: prop.type }
115
123
  if (!['object', 'array'].includes(prop.type)) {
116
124
  const noWrap = this.isNoWrap(f, schema) ? 'nowrap' : ''
117
125
  if (this.isRightAligned(f, schema)) attr.text = `align:end ${noWrap}`
118
126
  else attr.text = noWrap
119
127
  }
120
128
  const formatter = get(schema, `formatter.${f}`)
121
- if (formatter) value = await this.component.buildSentence(formatter(value, d))
129
+ if (formatter) {
130
+ if (isFunction(formatter)) value = await formatter(dataValue, d)
131
+ else value = await callHandler(formatter, req, dataValue, d)
132
+ value = await this.component.buildSentence(value)
133
+ }
122
134
  const line = await this.component.buildTag({ tag: 'td', attr, html: value })
123
135
  lines.push(line)
124
136
  }
125
137
  const attr = {}
126
- if (!schema.view.disabled.includes('update') || !schema.view.disabled.includes('remove')) attr['@click'] = `toggle('${d.id}')`
127
- if (!schema.view.disabled.includes('get')) attr['@dblclick'] = `goDetails('${d.id}')`
138
+ if (!disableds.includes('update') || !disableds.includes('remove')) attr['@click'] = `toggle('${d.id}')`
139
+ if (!disableds.includes('get')) attr['@dblclick'] = `goDetails('${d.id}')`
128
140
  items.push(await this.component.buildTag({ tag: 'tr', attr, html: lines.join('\n') }))
129
141
  }
130
142
  html.push(await this.component.buildTag({ tag: 'tbody', attr: group.body, html: items.join('\n') }))
131
143
  this.params.attr = omit(this.params.attr, ['sortUpIcon', 'sortDownIcon', 'noSort', 'selection', 'headerNowrap'])
132
144
  const goDetails = `
133
145
  goDetails (id) {
134
- window.location.href = '${this.component.buildUrl({ base: 'details' })}&id=' + id
146
+ window.location.href = '${this.component.buildUrl({ base: 'details', prettyUrl })}&id=' + id
135
147
  }
136
148
  `
137
149
  if (selection === 'multi') {
@@ -0,0 +1,8 @@
1
+ <c:grid-row gutter="3" margin="top-2">
2
+ <c:grid-col col="6-lg">
3
+ <c:wdb-recs-info pages recs-per-page recs-per-page-values="10 15 25 50" />
4
+ </c:grid-col>
5
+ <c:grid-col col="6-lg" flex="justify-content:end-lg">
6
+ <c:wdb-pagination />
7
+ </c:grid-col>
8
+ </c:grid-row>
@@ -15,12 +15,5 @@
15
15
  </c:grid-col>
16
16
  </c:grid-row>
17
17
  <c:wdb-table id="main-table" border body-divider strip responsive />
18
- <c:grid-row gutter="3" margin="top-2">
19
- <c:grid-col col="6-lg">
20
- <c:wdb-recs-info pages recs-per-page recs-per-page-values="10 15 25 50" />
21
- </c:grid-col>
22
- <c:grid-col col="6-lg" flex="justify-content:end-lg">
23
- <c:wdb-pagination />
24
- </c:grid-col>
25
- </c:grid-row>
18
+ <c:include resource="waibuDb.partial:/crud/_list-footer.html" />
26
19
  <c:include resource="waibuDb.partial:/crud/_addons.html" />