waibu-db 1.1.18 → 1.1.20
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/bajo/intl/en-US.json +3 -0
- package/bajo/intl/id.json +3 -0
- package/bajoTemplate/partial/crud/_add-attachment.html +3 -0
- package/bajoTemplate/partial/crud/_addons.html +1 -1
- package/bajoTemplate/partial/crud/_details-attachment.html +3 -0
- package/bajoTemplate/partial/crud/_details-btns.html +17 -5
- package/bajoTemplate/partial/crud/_edit-attachment.html +43 -0
- package/bajoTemplate/partial/crud/_edit-btns.html +16 -4
- package/bajoTemplate/partial/crud/_list-attachment.html +9 -0
- package/bajoTemplate/partial/crud/add-handler.html +3 -0
- package/bajoTemplate/partial/crud/details-handler.html +5 -1
- package/bajoTemplate/partial/crud/edit-handler.html +3 -0
- package/lib/crud/details-handler.js +7 -3
- package/lib/crud/edit-handler.js +31 -15
- package/lib/crud/helper/attachment-handler.js +7 -0
- package/package.json +1 -1
- package/plugin/method/get-schema-ext.js +60 -51
- package/waibuBootstrap/theme/component/factory/btn-details.js +2 -1
- package/waibuBootstrap/theme/component/factory/btn-edit.js +2 -1
- package/waibuBootstrap/theme/component/factory/form.js +5 -2
package/bajo/intl/en-US.json
CHANGED
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
"clonePrevious": "Clone previous",
|
|
30
30
|
"actionPermanentlyDisabled%s": "Sorry, action '%s' is permanently disabled at database level. For more information, please contact your Admin immediately, thank you!",
|
|
31
31
|
"dbModels": "Database Models",
|
|
32
|
+
"checkAll": "Check All",
|
|
33
|
+
"uncheckAll": "Uncheck All",
|
|
34
|
+
"attachment": "Attachment",
|
|
32
35
|
"op": {
|
|
33
36
|
"equals": "Equals",
|
|
34
37
|
"notEquals": "Not Equals",
|
package/bajo/intl/id.json
CHANGED
|
@@ -29,6 +29,9 @@
|
|
|
29
29
|
"clonePrevious": "Duplikasi sebelumnya",
|
|
30
30
|
"actionPermanentlyDisabled%s": "Sorry, action '%s' is permanently disabled at database level. For more information, please contact your Admin immediately, thank you!",
|
|
31
31
|
"dbModels": "Model Database",
|
|
32
|
+
"checkAll": "Cek Semua",
|
|
33
|
+
"uncheckAll": "Uncheck Semua",
|
|
34
|
+
"attachment": "Attachment",
|
|
32
35
|
"op": {
|
|
33
36
|
"equals": "Sama Dengan",
|
|
34
37
|
"notEquals": "Tidak Sama Dengan",
|
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
<c:grid-row gutter="2">
|
|
2
2
|
<c:grid-col col="6-lg">
|
|
3
|
-
|
|
3
|
+
<% if (!schema.view.control.noBackBtn) { %>
|
|
4
|
+
<c:wdb-btn-back href="<%= schema.view.control.backHref ?? 'undefined' %>" />
|
|
5
|
+
<% } %>
|
|
4
6
|
<% if (schema.disabled.includes('remove') && schema.disabled.includes('update')) { %>
|
|
5
|
-
|
|
7
|
+
<% if (!schema.view.control.noExportBtn) { %>
|
|
8
|
+
<c:wdb-btn-export selector="#main-form" handler="details" launch-margin="start-1" />
|
|
9
|
+
<% } %>
|
|
6
10
|
<% } else { %>
|
|
7
11
|
<c:btn-group margin="start-1">
|
|
8
|
-
|
|
9
|
-
<c:wdb-btn-
|
|
12
|
+
<% if (!schema.view.control.noEditBtn) { %>
|
|
13
|
+
<c:wdb-btn-edit href="<%= schema.view.control.editHref ?? 'undefined' %>" />
|
|
14
|
+
<% } %>
|
|
15
|
+
<% if (!schema.view.control.noCloneBtn) { %>
|
|
16
|
+
<c:wdb-btn-clone href="<%= schema.view.control.cloneHref ?? 'undefined' %>" />
|
|
17
|
+
<% } %>
|
|
18
|
+
<% if (!schema.view.control.noExportBtn) { %>
|
|
10
19
|
<c:wdb-btn-export selector="#main-form" handler="details" launch-on-end/>
|
|
20
|
+
<% } %>
|
|
11
21
|
</c:btn-group>
|
|
12
22
|
<% } %>
|
|
13
23
|
</c:grid-col>
|
|
14
24
|
<c:grid-col col="6-lg" flex="justify-content:end-lg align-items:center">
|
|
15
|
-
|
|
25
|
+
<% if (!schema.view.control.noDeleteBtn) { %>
|
|
26
|
+
<c:wdb-btn-delete href="<%= schema.view.control.deleteHref ?? 'undefined' %>" />
|
|
27
|
+
<% } %>
|
|
16
28
|
</c:grid-col>
|
|
17
29
|
</c:grid-row>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<c:fieldset id="attachment" t:legend="attachment" grid-gutter="3"
|
|
2
|
+
x-data="{
|
|
3
|
+
selected: [],
|
|
4
|
+
checkAll (check = true) {
|
|
5
|
+
if (!check) {
|
|
6
|
+
this.selected = []
|
|
7
|
+
return
|
|
8
|
+
}
|
|
9
|
+
const all = document.querySelectorAll('#attachment input[type=checkbox]')
|
|
10
|
+
this.selected = _.map(all, item => item.value)
|
|
11
|
+
},
|
|
12
|
+
toggleBtn () {
|
|
13
|
+
const el = this.$refs.removeatt
|
|
14
|
+
if (this.selected.length > 0) el.classList.remove('disabled')
|
|
15
|
+
else el.classList.add('disabled')
|
|
16
|
+
},
|
|
17
|
+
remove () {
|
|
18
|
+
this.$refs.action.value = 'removeatt'
|
|
19
|
+
this.$refs.value.value = JSON.stringify(this.selected)
|
|
20
|
+
document.getElementById('main-form').submit()
|
|
21
|
+
}
|
|
22
|
+
}"
|
|
23
|
+
x-init="$watch('selected', val => toggleBtn())"
|
|
24
|
+
<%= schema.view.card === false ? '' : 'card' %>
|
|
25
|
+
>
|
|
26
|
+
<input x-ref="action" type="hidden" name="_action" />
|
|
27
|
+
<input x-ref="value" type="hidden" name="_value" />
|
|
28
|
+
<c:grid-col col="12">
|
|
29
|
+
<c:grid-row gutter="3">
|
|
30
|
+
<c:grid-col col="8-md 12-sm">
|
|
31
|
+
<c:form-file name="file" multiple no-label <%= _.isString(schema.view.attachment) ? ('accept="' + schema.view.attachment + '"') : '' %> />
|
|
32
|
+
</c:grid-col>
|
|
33
|
+
<c:grid-col col="4-md 12-sm" flex="align-items:center">
|
|
34
|
+
<c:btn-group margin="end-2">
|
|
35
|
+
<c:btn size="sm" color="secondary-outline" t:content="checkAll" @click="checkAll()"/>
|
|
36
|
+
<c:btn size="sm" color="secondary-outline" t:content="uncheckAll" @click="checkAll(false)"/>
|
|
37
|
+
</c:btn-group>
|
|
38
|
+
<c:btn margin="end-2" size="sm" class="disabled" x-ref="removeatt" color="danger-outline" t:content="Remove" @click="remove()"/>
|
|
39
|
+
</c:grid-col>
|
|
40
|
+
</c:grid-row>
|
|
41
|
+
</c:grid-col>
|
|
42
|
+
<!-- include waibuDb.partial:/crud/_list-attachment.html -->
|
|
43
|
+
</c:fieldset>
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
<c:grid-row gutter="2">
|
|
2
2
|
<c:grid-col col="6-lg">
|
|
3
|
-
|
|
3
|
+
<% if (!schema.view.control.noBackBtn) { %>
|
|
4
|
+
<c:wdb-btn-back href="<%= schema.view.control.backHref ?? 'undefined' %>"/>
|
|
5
|
+
<% } %>
|
|
4
6
|
<c:btn-group margin="start-1">
|
|
5
|
-
|
|
6
|
-
<c:wdb-btn-
|
|
7
|
+
<% if (!schema.view.control.noDetailsBtn) { %>
|
|
8
|
+
<c:wdb-btn-details href="<%= schema.view.control.detailsHref ?? 'undefined' %>" />
|
|
9
|
+
<% } %>
|
|
10
|
+
<% if (!schema.view.control.noCloneBtn) { %>
|
|
11
|
+
<c:wdb-btn-clone href="<%= schema.view.control.cloneHref ?? 'undefined' %>" />
|
|
12
|
+
<% } %>
|
|
7
13
|
<c:wdb-btn-export selector="#main-form" handler="edit" launch-on-end/>
|
|
8
14
|
</c:btn-group>
|
|
9
15
|
</c:grid-col>
|
|
10
16
|
<c:grid-col col="6-lg" flex="justify-content:end-lg align-items:center">
|
|
11
|
-
|
|
17
|
+
<% if (!schema.view.control.noDeleteBtn) { %>
|
|
18
|
+
<c:wdb-btn-delete href="<%= schema.view.control.deleteHref ?? 'undefined' %>"/>
|
|
19
|
+
<% } %>
|
|
20
|
+
<% if (!schema.view.control.noResetBtn) { %>
|
|
12
21
|
<c:btn type="reset" color="secondary" t:content="reset" margin="start-2"/>
|
|
22
|
+
<% } %>
|
|
23
|
+
<% if (!schema.view.control.noSubmitBtn) { %>
|
|
13
24
|
<c:btn type="submit" color="primary" t:content="submit" margin="start-2"/>
|
|
25
|
+
<% } %>
|
|
14
26
|
</c:grid-col>
|
|
15
27
|
</c:grid-row>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<% for (const att of attachments) { %>
|
|
2
|
+
<c:grid-col col="4-lg 6-md">
|
|
3
|
+
<% if (attr.readonly) { %>
|
|
4
|
+
<a href="<%= decodeURI(att.url) %>" target="_blank"><%= att.fileName %></a>
|
|
5
|
+
<% } else { %>
|
|
6
|
+
<c:form-check x-model="selected" value="<%= att.fullPath %>" label="<a href='<%= att.url %>' target='_blank'><%= att.fileName %></a>" />
|
|
7
|
+
<% } %>
|
|
8
|
+
</c:grid-col>
|
|
9
|
+
<% } %>
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<c:wdb-form id="main-form" method="POST" enctype="multipart/form-data">
|
|
2
|
+
<% if (schema.view.attachment) { %>
|
|
3
|
+
<!-- include waibuDb.partial:/crud/_add-attachment.html -->
|
|
4
|
+
<% } %>
|
|
2
5
|
<!-- include waibuDb.partial:/crud/_add-btns.html -->
|
|
3
6
|
</c:wdb-form>
|
|
4
7
|
<!-- include waibuDb.partial:/crud/_addons.html -->
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
<c:wdb-form tag="div" id="main-form"
|
|
1
|
+
<c:wdb-form tag="div" id="main-form">
|
|
2
|
+
<% if (schema.view.attachment) { %>
|
|
3
|
+
<!-- include waibuDb.partial:/crud/_details-attachment.html -->
|
|
4
|
+
<% } %>
|
|
5
|
+
</c:wdb-form>
|
|
2
6
|
<!-- include waibuDb.partial:/crud/_details-btns.html -->
|
|
3
7
|
<!-- include waibuDb.partial:/crud/_addons.html -->
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<c:wdb-form id="main-form" method="POST" enctype="multipart/form-data">
|
|
2
|
+
<% if (schema.view.attachment) { %>
|
|
3
|
+
<!-- include waibuDb.partial:/crud/_edit-attachment.html -->
|
|
4
|
+
<% } %>
|
|
2
5
|
<!-- include waibuDb.partial:/crud/_edit-btns.html -->
|
|
3
6
|
</c:wdb-form>
|
|
4
7
|
<!-- include waibuDb.partial:/crud/_addons.html -->
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import attachmentHandler from './helper/attachment-handler.js'
|
|
2
|
+
|
|
3
|
+
async function detailsHandler ({ req, reply, model, params = {}, id, template, addOnsHandler, templateDisabled = 'waibuDb.template:/disabled.html' } = {}) {
|
|
2
4
|
const { pascalCase } = this.app.bajo
|
|
3
5
|
const { recordGet, getSchemaExt } = this.app.waibuDb
|
|
4
6
|
const { merge } = this.lib._
|
|
@@ -8,10 +10,12 @@ async function detailsHandler ({ req, reply, model, params = {}, template, addOn
|
|
|
8
10
|
if (schema.disabled.includes('get')) return reply.view(templateDisabled, { action: 'details' })
|
|
9
11
|
// req.query.attachment = true
|
|
10
12
|
options.fields = schema.view.fields
|
|
11
|
-
|
|
13
|
+
id = id ?? req.params.id ?? req.query.id
|
|
14
|
+
const resp = await recordGet({ model, req, id, options })
|
|
12
15
|
const form = resp.data
|
|
13
16
|
const addOns = addOnsHandler ? await addOnsHandler.call(this.app[req.ns], { req, reply, params, data: resp, schema }) : undefined
|
|
14
|
-
|
|
17
|
+
const attachments = await attachmentHandler.call(this, { schema, id })
|
|
18
|
+
merge(params, { form, schema, addOns, attachments })
|
|
15
19
|
return reply.view(template, params)
|
|
16
20
|
}
|
|
17
21
|
|
package/lib/crud/edit-handler.js
CHANGED
|
@@ -1,32 +1,48 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import attachmentHandler from './helper/attachment-handler.js'
|
|
2
|
+
|
|
3
|
+
async function editHandler ({ req, reply, model, id, params = {}, template, addOnsHandler, templateDisabled = 'waibuDb.template:/disabled.html' } = {}) {
|
|
4
|
+
const { pascalCase, getPluginDataDir } = this.app.bajo
|
|
3
5
|
const { recordUpdate, recordGet, getSchemaExt } = this.app.waibuDb
|
|
4
6
|
const { buildUrl } = this.app.waibuMpa
|
|
5
|
-
const {
|
|
7
|
+
const { fs } = this.lib
|
|
8
|
+
const { merge, defaultsDeep, isEmpty, omit } = this.lib._
|
|
6
9
|
const options = {}
|
|
10
|
+
let error
|
|
11
|
+
let resp
|
|
12
|
+
let form
|
|
7
13
|
model = model ?? pascalCase(req.params.model)
|
|
8
14
|
const { schema } = await getSchemaExt(model, 'edit', options, { params })
|
|
9
15
|
if (schema.disabled.includes('update')) return reply.view(templateDisabled, { action: 'edit' })
|
|
10
16
|
// req.query.attachment = true
|
|
11
17
|
options.fields = schema.view.fields
|
|
12
|
-
|
|
13
|
-
let resp
|
|
14
|
-
let form
|
|
18
|
+
id = id ?? req.params.id ?? req.query.id
|
|
15
19
|
if (req.method === 'GET') {
|
|
16
|
-
const old = await recordGet({ model, req, id
|
|
20
|
+
const old = await recordGet({ model, req, id, options })
|
|
17
21
|
form = defaultsDeep(req.body, old.data)
|
|
18
22
|
} else {
|
|
19
|
-
form = req.body
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
form = omit(req.body, ['_action', '_value'])
|
|
24
|
+
if (req.body._action === 'removeatt' && !isEmpty(req.body._value)) {
|
|
25
|
+
const root = `${getPluginDataDir('dobo')}/attachment`
|
|
26
|
+
for (const item of req.body._value) {
|
|
27
|
+
try {
|
|
28
|
+
const file = `${root}/${item}`
|
|
29
|
+
await fs.unlink(file)
|
|
30
|
+
} catch (err) {}
|
|
31
|
+
}
|
|
32
|
+
if (req && req.flash) req.flash('notify', req.t('attachmentRemoved'))
|
|
33
|
+
} else {
|
|
34
|
+
try {
|
|
35
|
+
resp = await recordUpdate({ model, req, id, reply, options })
|
|
36
|
+
form = resp.data
|
|
37
|
+
return reply.redirectTo(buildUrl({ url: req.url, base: req.params.base ?? req.query.base ?? 'list', params: { page: 1 }, exclude: ['id'] }))
|
|
38
|
+
} catch (err) {
|
|
39
|
+
error = err
|
|
40
|
+
}
|
|
26
41
|
}
|
|
27
42
|
}
|
|
28
43
|
const addOns = addOnsHandler ? await addOnsHandler.call(this.app[req.ns], { req, reply, params, data: resp, schema, error }) : undefined
|
|
29
|
-
|
|
44
|
+
const attachments = await attachmentHandler.call(this, { schema, id })
|
|
45
|
+
merge(params, { form, schema, error, addOns, attachments })
|
|
30
46
|
return reply.view(template, params)
|
|
31
47
|
}
|
|
32
48
|
|
package/package.json
CHANGED
|
@@ -5,32 +5,43 @@ const defReadonly = ['id', 'createdAt', 'updatedAt']
|
|
|
5
5
|
const defFormatter = {}
|
|
6
6
|
|
|
7
7
|
function getCommons (action, schema, ext, opts = {}) {
|
|
8
|
-
const {
|
|
8
|
+
const { defaultsDeep } = this.app.bajo
|
|
9
|
+
const { merge, map, get, set, without, uniq, pull } = this.lib._
|
|
9
10
|
const calcFields = get(ext, `view.${action}.calcFields`, get(ext, 'common.calcFields', []))
|
|
11
|
+
const forceVisible = get(ext, `view.${action}.forceVisible`, get(ext, 'common.forceVisible', []))
|
|
12
|
+
const widget = defaultsDeep(get(ext, `view.${action}.widget`), get(ext, 'common.widget', {}))
|
|
10
13
|
const noEscape = get(ext, `view.${action}.noEscape`, get(ext, 'common.noEscape', []))
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
+
const control = defaultsDeep(get(ext, `view.${action}.control`), get(ext, 'common.control', {}))
|
|
15
|
+
const valueFormatter = defaultsDeep(get(ext, `view.${action}.valueFormatter`), get(ext, 'common.valueFormatter', {}))
|
|
16
|
+
const formatter = defaultsDeep(get(ext, `view.${action}.formatter`), get(ext, 'common.formatter', {}))
|
|
14
17
|
const card = get(ext, `view.${action}.card`, get(ext, 'common.card', true))
|
|
15
|
-
|
|
18
|
+
let hidden = get(ext, `view.${action}.hidden`, get(ext, 'common.hidden', []))
|
|
16
19
|
const disabled = get(ext, `view.${action}.disabled`, get(ext, 'common.disabled', []))
|
|
17
|
-
const x = get(ext, `view.${action}.x
|
|
20
|
+
const x = defaultsDeep(get(ext, `view.${action}.x`), get(ext, 'common.x', {}))
|
|
18
21
|
const aggregate = get(ext, `view.${action}.stat.aggregate`, get(ext, 'common.stat.aggregate', []))
|
|
19
|
-
|
|
22
|
+
let attachment = get(ext, `view.${action}.attachment`, get(ext, 'common.attachment', false))
|
|
23
|
+
if (!schema.attachment || action === 'list') attachment = false
|
|
24
|
+
hidden.push('siteId', ...schema.hidden, ...(opts.hidden ?? []))
|
|
25
|
+
hidden = uniq(hidden)
|
|
26
|
+
pull(hidden, ...forceVisible)
|
|
20
27
|
const allFields = without(map(schema.properties, 'name'), ...hidden)
|
|
21
28
|
const forFields = get(ext, `view.${action}.fields`, get(ext, 'common.fields', allFields))
|
|
29
|
+
set(schema, 'view.attachment', attachment)
|
|
22
30
|
set(schema, 'view.calcFields', calcFields)
|
|
23
31
|
set(schema, 'view.noEscape', noEscape)
|
|
32
|
+
set(schema, 'view.widget', widget)
|
|
24
33
|
set(schema, 'view.valueFormatter', valueFormatter)
|
|
25
34
|
set(schema, 'view.formatter', merge({}, defFormatter, formatter))
|
|
26
35
|
set(schema, 'view.stat.aggregate', aggregate)
|
|
27
36
|
set(schema, 'view.disabled', disabled)
|
|
37
|
+
set(schema, 'view.control', control)
|
|
28
38
|
set(schema, 'view.x', x)
|
|
29
39
|
if (schema.disabled.length > 0) schema.view.disabled.push(...schema.disabled)
|
|
30
40
|
let fields = []
|
|
31
41
|
for (const f of forFields) {
|
|
32
|
-
if (allFields.includes(f)
|
|
42
|
+
if (allFields.includes(f)) fields.push(f)
|
|
33
43
|
}
|
|
44
|
+
if (calcFields.length > 0) fields.push(...map(calcFields, 'name'))
|
|
34
45
|
fields = uniq(without(fields, ...hidden))
|
|
35
46
|
|
|
36
47
|
if (action !== 'add' && !fields.includes('id')) fields.unshift('id')
|
|
@@ -38,59 +49,58 @@ function getCommons (action, schema, ext, opts = {}) {
|
|
|
38
49
|
if (noWrap === true) noWrap = fields
|
|
39
50
|
else if (noWrap === false) noWrap = []
|
|
40
51
|
set(schema, 'view.noWrap', noWrap)
|
|
41
|
-
return { fields, allFields,
|
|
52
|
+
return { fields, allFields, card, calcFields }
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
function autoLayout ({ action, schema, ext, layout
|
|
55
|
+
function autoLayout ({ action, schema, ext, layout }) {
|
|
56
|
+
const { forOwn, keys } = this.lib._
|
|
45
57
|
const matches = ['id', 'createdAt', 'updatedAt']
|
|
46
58
|
const meta = []
|
|
47
59
|
const general = []
|
|
48
|
-
|
|
49
|
-
if (matches.includes(
|
|
50
|
-
else general.push(
|
|
51
|
-
}
|
|
52
|
-
if (meta.length <= 1) layout.push({ name: '_common',
|
|
60
|
+
forOwn(schema.view.widget, (w, f) => {
|
|
61
|
+
if (matches.includes(f)) meta.push(f)
|
|
62
|
+
else general.push(f)
|
|
63
|
+
})
|
|
64
|
+
if (meta.length <= 1) layout.push({ name: '_common', fields: keys(schema.view.widget) })
|
|
53
65
|
else {
|
|
54
|
-
layout.push({ name: 'Meta',
|
|
55
|
-
layout.push({ name: 'General',
|
|
66
|
+
layout.push({ name: 'Meta', fields: meta })
|
|
67
|
+
layout.push({ name: 'General', fields: general })
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
70
|
|
|
59
|
-
function customLayout ({ action, schema, ext, layout,
|
|
60
|
-
const {
|
|
71
|
+
function customLayout ({ action, schema, ext, layout, readonly }) {
|
|
72
|
+
const { defaultsDeep } = this.app.bajo
|
|
73
|
+
const { isEmpty } = this.lib._
|
|
61
74
|
const items = [...layout]
|
|
62
|
-
layout.splice(0, layout.length)
|
|
63
75
|
for (const item of items) {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const widget = find(allWidgets, { name: f.name })
|
|
74
|
-
if (!widget && !f.component) continue
|
|
75
|
-
widget.attr = merge({}, widget.attr, omit(f, ['component', 'componentOpts']))
|
|
76
|
-
if (f.component && !readonly.includes(f.name) && action !== 'details') {
|
|
77
|
-
widget.component = f.component
|
|
78
|
-
widget.componentOpts = f.componentOpts
|
|
79
|
-
}
|
|
80
|
-
widgets.push(widget)
|
|
76
|
+
for (const idx in item.fields) {
|
|
77
|
+
const f = item.fields[idx]
|
|
78
|
+
const [name, col, label, component] = f.split(':')
|
|
79
|
+
item.fields[idx] = name
|
|
80
|
+
const w = { name, attr: {} }
|
|
81
|
+
w.attr.label = isEmpty(label) ? `field.${name}` : label
|
|
82
|
+
if (!isEmpty(col)) w.attr.col = col
|
|
83
|
+
if (!isEmpty(component)) w.component = component
|
|
84
|
+
schema.view.widget[name] = defaultsDeep(w, schema.view.widget[w.name])
|
|
81
85
|
}
|
|
82
|
-
if (widgets.length > 0) layout.push({ name: item.name, widgets })
|
|
83
86
|
}
|
|
84
87
|
}
|
|
85
88
|
|
|
86
89
|
function applyLayout (action, schema, ext) {
|
|
87
|
-
const {
|
|
88
|
-
const {
|
|
90
|
+
const { defaultsDeep } = this.app.bajo
|
|
91
|
+
const { set, get, isEmpty, find } = this.lib._
|
|
92
|
+
const { fields, card, calcFields } = getCommons.call(this, action, schema, ext)
|
|
89
93
|
const layout = get(ext, `view.${action}.layout`, get(ext, 'common.layout', []))
|
|
90
94
|
const readonly = get(ext, `view.${action}.readonly`, get(ext, 'common.readonly', defReadonly))
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
const widget = {}
|
|
96
|
+
for (const f of fields) {
|
|
97
|
+
let prop = find(schema.properties, { name: f })
|
|
98
|
+
if (!prop) prop = find(calcFields, { name: f })
|
|
99
|
+
if (!prop) continue
|
|
100
|
+
const result = schema.view.widget[f] ?? {}
|
|
101
|
+
result.name = result.name ?? f
|
|
102
|
+
result.component = result.component ?? 'form-input'
|
|
103
|
+
result.attr = defaultsDeep(result.attr, { col: '4-md', label: `field.${f}` })
|
|
94
104
|
if (['array', 'object', 'text'].includes(prop.type)) {
|
|
95
105
|
result.attr.col = '12'
|
|
96
106
|
result.component = 'form-textarea'
|
|
@@ -110,20 +120,20 @@ function applyLayout (action, schema, ext) {
|
|
|
110
120
|
if (['string', 'text'].includes(prop.type) && prop.maxLength) set(result, 'attr.maxlength', prop.maxLength)
|
|
111
121
|
if (readonly.includes(f)) result.component = 'form-plaintext'
|
|
112
122
|
}
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
123
|
+
widget[f] = result
|
|
124
|
+
}
|
|
125
|
+
set(schema, 'view.widget', widget)
|
|
126
|
+
if (isEmpty(layout)) autoLayout.call(this, { layout, schema, action, ext })
|
|
127
|
+
else customLayout.call(this, { layout, schema, action, ext, readonly })
|
|
117
128
|
set(schema, 'view.layout', layout)
|
|
118
129
|
set(schema, 'view.fields', fields)
|
|
119
|
-
set(schema, 'view.label', label)
|
|
120
130
|
set(schema, 'view.card', card)
|
|
121
131
|
}
|
|
122
132
|
|
|
123
133
|
const handler = {
|
|
124
134
|
list: async function (schema, ext, opts) {
|
|
125
135
|
const { get, set } = this.lib._
|
|
126
|
-
const { fields
|
|
136
|
+
const { fields } = getCommons.call(this, 'list', schema, ext, opts)
|
|
127
137
|
const qsFields = []
|
|
128
138
|
for (const f of get(schema, 'view.qs.fields', '').split(',')) {
|
|
129
139
|
if (fields.includes(f)) qsFields.push(f)
|
|
@@ -135,7 +145,6 @@ const handler = {
|
|
|
135
145
|
if (!['1', '-1'].includes(dir)) dir = '1'
|
|
136
146
|
set(schema, 'view.qs.sort', `${col}:${dir}`)
|
|
137
147
|
}
|
|
138
|
-
set(schema, 'view.label', label)
|
|
139
148
|
set(schema, 'view.fields', fields)
|
|
140
149
|
set(schema, 'view.qs.fields', qsFields.join(','))
|
|
141
150
|
},
|
|
@@ -159,7 +168,7 @@ async function getSchemaExt (model, view, opts) {
|
|
|
159
168
|
const base = path.basename(schema.file, path.extname(schema.file))
|
|
160
169
|
let ext = await readConfig(`${schema.ns}:/waibuDb/schema/${base}.*`, { ignoreError: true, opts })
|
|
161
170
|
const over = await readConfig(`main:/waibuDb/extend/${schema.ns}/schema/${base}.*`, { ignoreError: true, opts })
|
|
162
|
-
ext = defaultsDeep(over, ext)
|
|
171
|
+
ext = defaultsDeep(opts.schema ?? {}, over, ext)
|
|
163
172
|
await handler[view].call(this, schema, ext, opts)
|
|
164
173
|
schema = pick(schema, ['name', 'properties', 'indexes', 'disabled', 'attachment', 'sortables', 'view'])
|
|
165
174
|
return { schema, ext }
|
|
@@ -31,7 +31,8 @@ async function btnDetails () {
|
|
|
31
31
|
$refs.details.href = path + '&id=' + recId
|
|
32
32
|
`
|
|
33
33
|
} else {
|
|
34
|
-
this.params.attr.href
|
|
34
|
+
const prefix = this.params.attr.href.includes('?') ? '' : '?'
|
|
35
|
+
this.params.attr.href += prefix + '&id=' + req.query.id
|
|
35
36
|
}
|
|
36
37
|
this.params.html = await this.component.buildTag({ tag: 'btn', attr: this.params.attr, html: this.params.html })
|
|
37
38
|
}
|
|
@@ -58,7 +58,8 @@ async function btnEdit () {
|
|
|
58
58
|
this.params.html = await this.component.buildTag({ tag: 'dropdown', attr: this.params.attr, html: html.join('\n') })
|
|
59
59
|
}
|
|
60
60
|
} else {
|
|
61
|
-
this.params.attr.href
|
|
61
|
+
const prefix = this.params.attr.href.includes('?') ? '' : '?'
|
|
62
|
+
this.params.attr.href += prefix + '&id=' + req.query.id
|
|
62
63
|
this.params.html = await this.component.buildTag({ tag: 'btn', attr: this.params.attr, html: this.params.html })
|
|
63
64
|
}
|
|
64
65
|
}
|
|
@@ -13,8 +13,11 @@ async function form () {
|
|
|
13
13
|
const xOns = get(schema, 'view.x.on', [])
|
|
14
14
|
for (const l of schema.view.layout) {
|
|
15
15
|
body.push(`<c:fieldset ${schema.view.card === false ? '' : 'card'} ${l.name[0] !== '_' ? ('t:legend="' + l.name + '"') : ''} grid-gutter="2">`)
|
|
16
|
-
for (const
|
|
17
|
-
const
|
|
16
|
+
for (const f of l.fields) {
|
|
17
|
+
const w = schema.view.widget[f]
|
|
18
|
+
let prop = find(schema.properties, { name: f })
|
|
19
|
+
if (!prop) prop = find(schema.view.calcFields, { name: f })
|
|
20
|
+
if (!prop) continue
|
|
18
21
|
const attr = [`x-ref="${w.name}"`]
|
|
19
22
|
if (xModels.includes(w.name)) attr.push(`x-model="${w.name}"`)
|
|
20
23
|
forOwn(w.attr, (v, k) => {
|