waibu-db 2.18.0 → 2.18.2
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/waibuBootstrap/theme/component/widget/data-table.js +7 -4
- package/extend/waibuBootstrap/theme/component/widget/form.js +5 -5
- package/index.js +0 -43
- package/lib/crud/edit-handler.js +4 -6
- package/lib/method/get-schema-ext.js +13 -12
- package/package.json +1 -1
- package/wiki/CHANGES.md +5 -0
|
@@ -23,7 +23,7 @@ async function table () {
|
|
|
23
23
|
const { req } = this.component
|
|
24
24
|
const { escape, attrToArray } = this.app.waibu
|
|
25
25
|
const { groupAttrs } = this.app.waibuMpa
|
|
26
|
-
const { get, omit, set, find, isEmpty, without, merge } = this.app.lib._
|
|
26
|
+
const { get, omit, set, find, isEmpty, without, merge, isString } = this.app.lib._
|
|
27
27
|
const group = groupAttrs(this.params.attr, ['body', 'head', 'foot'])
|
|
28
28
|
this.params.attr = group._
|
|
29
29
|
const prettyUrl = this.params.attr.prettyUrl
|
|
@@ -123,17 +123,20 @@ async function table () {
|
|
|
123
123
|
}
|
|
124
124
|
for (const f of schema.view.fields) {
|
|
125
125
|
if (!fields.includes(f)) continue
|
|
126
|
-
|
|
127
|
-
if (!prop) prop = find(schema.view.calcFields, { name: f })
|
|
126
|
+
const prop = find(schema.properties, { name: f })
|
|
128
127
|
if (!prop) continue
|
|
129
128
|
let dataValue = d[f]
|
|
130
129
|
if (['datetime'].includes(prop.type) && dataValue instanceof Date && !isNaN(dataValue)) dataValue = escape(dataValue.toISOString())
|
|
131
130
|
else if (['string', 'text'].includes(prop.type)) dataValue = escape(dataValue)
|
|
132
131
|
else if (['array', 'object'].includes(prop.type)) dataValue = escape(JSON.stringify(dataValue))
|
|
133
132
|
const refName = get(schema, `view.widget.${f}.attr.refName`)
|
|
134
|
-
let value = this.getRefValue({ field: f, data: d, refName }) ?? get(d, `_fmt.${f}
|
|
133
|
+
let value = this.getRefValue({ field: f, data: d, refName }) ?? get(d, `_fmt.${f}`, d[f])
|
|
135
134
|
if (!get(schema, 'view.noEscape', []).includes(f)) value = escape(value)
|
|
136
135
|
const attr = { dataValue, dataKey: prop.name, dataType: prop.type }
|
|
136
|
+
if (isString(d[f]) && d[f].startsWith('<a ')) {
|
|
137
|
+
delete attr.dataValue
|
|
138
|
+
value = d[f]
|
|
139
|
+
}
|
|
137
140
|
if (!disableds.includes('get')) attr.style = { cursor: 'pointer' }
|
|
138
141
|
const formatCell = get(schema, `view.formatCell.${f}`)
|
|
139
142
|
if (formatCell) merge(attr, await formatCell.call(this, value, d, { params: this.params, req }))
|
|
@@ -12,11 +12,11 @@ async function form () {
|
|
|
12
12
|
const { get, has } = this.app.lib._
|
|
13
13
|
const { stringifyAttribs } = this.app.waibuMpa
|
|
14
14
|
attr.dataType = prop.type
|
|
15
|
-
const cmp = prop.ref ? 'wdb-lookup-select' : widget.component
|
|
16
15
|
if (has(attr, 'name') && !has(attr, 'value')) {
|
|
17
|
-
attr.value =
|
|
16
|
+
attr.value = widget.component === 'form-plaintext' ? get(this, `oldData.${attr.name}`, attr.dataValue) : attr.dataValue
|
|
18
17
|
}
|
|
19
|
-
|
|
18
|
+
if (prop.virtual) widget.component = 'form-plaintext'
|
|
19
|
+
return `<c:${widget.component} ${stringifyAttribs(attr)} />`
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
build = async () => {
|
|
@@ -31,9 +31,9 @@ async function form () {
|
|
|
31
31
|
body.push(`<c:fieldset ${this.schema.view.card === false ? '' : 'card'} ${l.name[0] !== '_' ? ('t:legend="' + l.name + '"') : ''} grid-gutter="2">`)
|
|
32
32
|
for (const f of fields) {
|
|
33
33
|
const widget = this.schema.view.widget[f]
|
|
34
|
-
|
|
35
|
-
if (!prop) prop = find(this.schema.view.calcFields, { name: f })
|
|
34
|
+
const prop = find(this.schema.properties, { name: f })
|
|
36
35
|
if (!prop) continue
|
|
36
|
+
if (['dobo:image'].includes(prop.feature)) continue
|
|
37
37
|
const attr = {
|
|
38
38
|
'x-ref': widget.name,
|
|
39
39
|
labelFloating: true,
|
package/index.js
CHANGED
|
@@ -167,49 +167,6 @@ async function factory (pkgName) {
|
|
|
167
167
|
return await this.findAllRecord({ model, req, options })
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
formatRecord = async ({ data, req, schema, options = {} }) => {
|
|
171
|
-
const { isArray } = this.app.lib._
|
|
172
|
-
if (!isArray(data)) return await this.formatRow({ data, req, schema, options })
|
|
173
|
-
const items = []
|
|
174
|
-
for (const d of data) {
|
|
175
|
-
const item = await this.formatRow({ data: d, req, schema, options })
|
|
176
|
-
items.push(item)
|
|
177
|
-
}
|
|
178
|
-
return items
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
formatRow = async ({ data, req, schema, options = {} }) => {
|
|
182
|
-
const { get, find, isFunction, cloneDeep } = this.app.lib._
|
|
183
|
-
const { format, callHandler } = this.app.bajo
|
|
184
|
-
const { escape } = this.app.waibu
|
|
185
|
-
const fields = get(schema, 'view.fields', Object.keys(schema.properties))
|
|
186
|
-
const rec = cloneDeep(data)
|
|
187
|
-
const lang = get(req, 'lang')
|
|
188
|
-
const unitSys = get(req, 'site.setting.sumba.unitSys')
|
|
189
|
-
const timeZone = get(req, 'site.setting.sumba.timeZone', this.app.bajo.config.intl.format.datetime.timeZone)
|
|
190
|
-
for (const f of fields) {
|
|
191
|
-
if (f === '_ref') continue
|
|
192
|
-
let prop = find(schema.properties, { name: f })
|
|
193
|
-
if (!prop) prop = find(schema.view.calcFields, { name: f })
|
|
194
|
-
if (!prop) continue
|
|
195
|
-
const opts = {
|
|
196
|
-
lang: options.lang ?? lang,
|
|
197
|
-
longitude: ['lng', 'longitude'].includes(f),
|
|
198
|
-
latitude: ['lat', 'latitude'].includes(f),
|
|
199
|
-
speed: ['speed'].includes(f),
|
|
200
|
-
degree: ['course', 'heading'].includes(f),
|
|
201
|
-
distance: ['distance'].includes(f),
|
|
202
|
-
unitSys: options.unitSys ?? unitSys,
|
|
203
|
-
datetime: options.datetime ?? { timeZone },
|
|
204
|
-
date: options.date ?? { timeZone },
|
|
205
|
-
time: options.time ?? { timeZone }
|
|
206
|
-
}
|
|
207
|
-
rec[f] = format(data[f], prop.type, opts)
|
|
208
|
-
if (['string', 'text'].includes(prop.type)) rec[f] = escape(rec[f])
|
|
209
|
-
}
|
|
210
|
-
return rec
|
|
211
|
-
}
|
|
212
|
-
|
|
213
170
|
countRecord = countRecord
|
|
214
171
|
createAggregate = createAggregate
|
|
215
172
|
createHistogram = createHistogram
|
package/lib/crud/edit-handler.js
CHANGED
|
@@ -2,10 +2,8 @@ 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
|
|
5
|
-
const { getPluginDataDir } = this.app.bajo
|
|
6
5
|
const { updateRecord, getRecord, getSchemaExt } = this.app.waibuDb
|
|
7
6
|
const { buildUrl } = this.app.waibuMpa
|
|
8
|
-
const { fs } = this.app.lib
|
|
9
7
|
const { defaultsDeep } = this.app.lib.aneka
|
|
10
8
|
const { merge, isEmpty, omit, cloneDeep, isArray, isPlainObject } = this.app.lib._
|
|
11
9
|
const opts = merge({}, options.modelOpts)
|
|
@@ -34,12 +32,12 @@ async function editHandler ({ req, reply, model, id, params = {}, template, addO
|
|
|
34
32
|
req.body._value = JSON.parse(req.body._value)
|
|
35
33
|
} catch (err) {}
|
|
36
34
|
if (req.body._action === 'removeatt' && !isEmpty(req.body._value)) {
|
|
37
|
-
const root = `${getPluginDataDir('dobo')}/attachment`
|
|
38
35
|
for (const item of req.body._value) {
|
|
39
36
|
try {
|
|
40
|
-
const
|
|
41
|
-
await
|
|
42
|
-
} catch (err) {
|
|
37
|
+
const [,,, field, fname] = item.split('/')
|
|
38
|
+
await mdl.removeAttachment(id, field, fname)
|
|
39
|
+
} catch (err) {
|
|
40
|
+
}
|
|
43
41
|
}
|
|
44
42
|
if (req && req.flash) req.flash('notify', req.t('attachmentRemoved'))
|
|
45
43
|
} else {
|
|
@@ -7,7 +7,6 @@ const defFormatter = {}
|
|
|
7
7
|
function getCommons (action, schema, ext, options = {}) {
|
|
8
8
|
const { defaultsDeep } = this.app.lib.aneka
|
|
9
9
|
const { merge, map, get, set, without, uniq, pull } = this.app.lib._
|
|
10
|
-
const calcFields = get(ext, `view.${action}.calcFields`, get(ext, 'common.calcFields', []))
|
|
11
10
|
const forceVisible = get(ext, `view.${action}.forceVisible`, get(ext, 'common.forceVisible', []))
|
|
12
11
|
const widget = defaultsDeep(get(ext, `view.${action}.widget`), get(ext, 'common.widget', {}))
|
|
13
12
|
const noEscape = get(ext, `view.${action}.noEscape`, get(ext, 'common.noEscape', []))
|
|
@@ -19,7 +18,7 @@ function getCommons (action, schema, ext, options = {}) {
|
|
|
19
18
|
const disabled = get(ext, `view.${action}.disabled`, get(ext, 'common.disabled', []))
|
|
20
19
|
const x = defaultsDeep(get(ext, `view.${action}.x`), get(ext, 'common.x', {}))
|
|
21
20
|
const aggregate = get(ext, `view.${action}.stat.aggregate`, get(ext, 'common.stat.aggregate', []))
|
|
22
|
-
let attachment = get(ext, `view.${action}.attachment`, get(ext, 'common.attachment',
|
|
21
|
+
let attachment = get(ext, `view.${action}.attachment`, get(ext, 'common.attachment', schema.attachment))
|
|
23
22
|
if (!schema.attachment || action === 'list') attachment = false
|
|
24
23
|
hidden.push('siteId', ...schema.hidden, ...(options.hidden ?? []))
|
|
25
24
|
hidden = uniq(hidden)
|
|
@@ -27,7 +26,6 @@ function getCommons (action, schema, ext, options = {}) {
|
|
|
27
26
|
const allFields = without(map(schema.properties, 'name'), ...hidden)
|
|
28
27
|
const forFields = get(ext, `view.${action}.fields`, get(ext, 'common.fields', allFields))
|
|
29
28
|
set(schema, 'view.attachment', attachment)
|
|
30
|
-
set(schema, 'view.calcFields', calcFields)
|
|
31
29
|
set(schema, 'view.noEscape', noEscape)
|
|
32
30
|
set(schema, 'view.widget', widget)
|
|
33
31
|
set(schema, 'view.formatCell', formatCell)
|
|
@@ -38,9 +36,8 @@ function getCommons (action, schema, ext, options = {}) {
|
|
|
38
36
|
set(schema, 'view.x', x)
|
|
39
37
|
if (schema.disabled.length > 0) schema.view.disabled.push(...schema.disabled)
|
|
40
38
|
let fields = []
|
|
41
|
-
const calcFieldNames = map(calcFields, 'name')
|
|
42
39
|
for (const f of forFields) {
|
|
43
|
-
if (
|
|
40
|
+
if (allFields.includes(f)) fields.push(f)
|
|
44
41
|
}
|
|
45
42
|
fields = uniq(without(fields, ...hidden))
|
|
46
43
|
|
|
@@ -50,7 +47,7 @@ function getCommons (action, schema, ext, options = {}) {
|
|
|
50
47
|
if (noWrap === true) noWrap = fields
|
|
51
48
|
else if (noWrap === false) noWrap = []
|
|
52
49
|
set(schema, 'view.noWrap', noWrap)
|
|
53
|
-
return { fields, allFields, card
|
|
50
|
+
return { fields, allFields, card }
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
function autoLayout ({ action, schema, ext, layout }) {
|
|
@@ -89,14 +86,13 @@ function customLayout ({ action, schema, ext, layout, readonly }) {
|
|
|
89
86
|
|
|
90
87
|
function applyLayout (action, schema, ext) {
|
|
91
88
|
const { defaultsDeep } = this.app.lib.aneka
|
|
92
|
-
const { set, get, isEmpty, find
|
|
93
|
-
const { fields, card
|
|
89
|
+
const { set, get, isEmpty, find } = this.app.lib._
|
|
90
|
+
const { fields, card } = getCommons.call(this, action, schema, ext)
|
|
94
91
|
const layout = get(ext, `view.${action}.layout`, get(ext, 'common.layout', []))
|
|
95
92
|
const readonly = get(ext, `view.${action}.readonly`, get(ext, 'common.readonly', defReadonly))
|
|
96
93
|
const widget = {}
|
|
97
94
|
for (const f of fields) {
|
|
98
|
-
|
|
99
|
-
if (!prop) prop = find(calcFields, { name: f })
|
|
95
|
+
const prop = find(schema.properties, { name: f })
|
|
100
96
|
if (!prop) continue
|
|
101
97
|
const result = schema.view.widget[f] ?? {}
|
|
102
98
|
result.name = result.name ?? f
|
|
@@ -109,8 +105,11 @@ function applyLayout (action, schema, ext) {
|
|
|
109
105
|
if (action === 'details') {
|
|
110
106
|
result.component = 'form-plaintext'
|
|
111
107
|
} else {
|
|
108
|
+
if (prop.ref) {
|
|
109
|
+
result.component = result.component ?? 'wdb-lookup-select'
|
|
110
|
+
}
|
|
112
111
|
if (prop.type === 'boolean') {
|
|
113
|
-
result.component = 'form-select'
|
|
112
|
+
result.component = result.component ?? 'form-select'
|
|
114
113
|
result.attr.options = 'false:no;true:yes'
|
|
115
114
|
}
|
|
116
115
|
if (prop.values) {
|
|
@@ -124,6 +123,7 @@ function applyLayout (action, schema, ext) {
|
|
|
124
123
|
if (readonly.includes(f)) result.component = 'form-plaintext'
|
|
125
124
|
if (!result.component) result.component = 'form-input'
|
|
126
125
|
}
|
|
126
|
+
/*
|
|
127
127
|
for (const k in result.attr ?? {}) {
|
|
128
128
|
const newKey = kebabCase(k)
|
|
129
129
|
if (k !== newKey) {
|
|
@@ -131,6 +131,7 @@ function applyLayout (action, schema, ext) {
|
|
|
131
131
|
delete result.attr[k]
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
|
+
*/
|
|
134
135
|
widget[f] = result
|
|
135
136
|
}
|
|
136
137
|
set(schema, 'view.widget', widget)
|
|
@@ -180,7 +181,7 @@ async function getSchemaExt (modelName, view, options = {}) {
|
|
|
180
181
|
|
|
181
182
|
const model = isString(modelName) ? this.app.dobo.getModel(modelName) : modelName
|
|
182
183
|
const ns = model.plugin.ns
|
|
183
|
-
const schema = pick(model, ['name', 'properties', 'indexes', 'disabled', 'attachment', 'sortables', 'scanables', 'view', 'hidden'])
|
|
184
|
+
const schema = pick(model, ['name', 'properties', 'indexes', 'disabled', 'attachment', 'sortables', 'scanables', 'view', 'hidden', 'attachment'])
|
|
184
185
|
const base = options.base ?? path.basename(model.file, path.extname(model.file))
|
|
185
186
|
const parserOpts = { args: options.args }
|
|
186
187
|
let ext = await readConfig(`${ns}:/extend/waibuDb/schema/${base}.*`, { ns, baseNs: 'waibuDb', parserOpts })
|
package/package.json
CHANGED