waibu-db 1.1.4 → 1.1.6
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 +29 -0
- package/bajo/intl/id.json +28 -21
- package/bajoTemplate/partial/crud/_list-footer.html +1 -1
- package/bajoTemplate/partial/crud/add-handler.html +4 -4
- package/bajoTemplate/partial/crud/edit-handler.html +2 -2
- package/bajoTemplate/template/crud/add.html +1 -1
- package/bajoTemplate/template/crud/details.html +1 -1
- package/bajoTemplate/template/crud/edit.html +1 -1
- package/bajoTemplate/template/crud/list.html +1 -1
- package/bajoTemplate/template/disabled.html +1 -2
- package/package.json +1 -1
- package/plugin/method/admin-menu.js +2 -2
- package/plugin/method/record/get.js +6 -6
- package/waibuBootstrap/theme/component/factory/btn-add.js +1 -1
- package/waibuBootstrap/theme/component/factory/btn-back.js +1 -1
- package/waibuBootstrap/theme/component/factory/btn-clone.js +1 -1
- package/waibuBootstrap/theme/component/factory/btn-columns.js +2 -2
- package/waibuBootstrap/theme/component/factory/btn-delete.js +2 -2
- package/waibuBootstrap/theme/component/factory/btn-details.js +1 -1
- package/waibuBootstrap/theme/component/factory/btn-edit.js +2 -2
- package/waibuBootstrap/theme/component/factory/btn-export.js +29 -18
- package/waibuBootstrap/theme/component/factory/query.js +6 -6
- package/waibuBootstrap/theme/component/factory/recs-info.js +3 -3
- package/waibuBootstrap/theme/component/factory/table.js +18 -4
package/bajo/intl/en-US.json
CHANGED
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
+
"pageOfPages%s%s": "Page %s of %s pages",
|
|
3
|
+
"recsFound%s": "%s record(s) found",
|
|
4
|
+
"recsPerPage": "recs per page",
|
|
5
|
+
"addAsNewClone": "Add as New Clone",
|
|
6
|
+
"details": "Details",
|
|
7
|
+
"clone": "Clone",
|
|
8
|
+
"delivery": "Delivery",
|
|
9
|
+
"saveAsFile": "Save as File",
|
|
10
|
+
"formattedField": "Formatted Field",
|
|
11
|
+
"formattedValue": "Formatted Value",
|
|
12
|
+
"zipped": "Zipped",
|
|
13
|
+
"fileType": "File Type",
|
|
14
|
+
"aboutToRemoveRecord": "You're about to remove one or more records. Are you really sure to do this?",
|
|
15
|
+
"columns": "Kolom",
|
|
16
|
+
"noStatYet": "Maaf, belum ada statistik",
|
|
17
|
+
"%s - %s": "%s - %s",
|
|
18
|
+
"list": "List ",
|
|
19
|
+
"add": "Add ",
|
|
20
|
+
"edit": "Edit",
|
|
21
|
+
"yes": "Yes",
|
|
22
|
+
"no": "No",
|
|
23
|
+
"db": "DB",
|
|
24
|
+
"excelXlsx": "Excel XLSX",
|
|
25
|
+
"csv": "CSV",
|
|
26
|
+
"xml": "XML",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"addMoreAfterSubmit": "Add more after submit",
|
|
29
|
+
"clonePrevious": "Clone previous",
|
|
30
|
+
"actionPermanentlyDisabled%s": "Sorry, action '%s' is permanently disabled at database level. For more information, please contact your Admin immediately, thank you!",
|
|
2
31
|
"op": {
|
|
3
32
|
"equals": "Equals",
|
|
4
33
|
"notEquals": "Not Equals",
|
package/bajo/intl/id.json
CHANGED
|
@@ -1,26 +1,33 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"%s
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
2
|
+
"pageOfPages%s%s": "Hal %s dari %s",
|
|
3
|
+
"recsFound%s": "Ditemukan %s data",
|
|
4
|
+
"recsPerPage": "data per halaman",
|
|
5
|
+
"addAsNewClone": "Tambah sbg Duplikat",
|
|
6
|
+
"details": "Detil",
|
|
7
|
+
"clone": "Gandakan",
|
|
8
|
+
"delivery": "Penyampaian",
|
|
9
|
+
"saveAsFile": "Simpan sbg Berkas",
|
|
10
|
+
"formattedField": "Kolom Terformat",
|
|
11
|
+
"formattedValue": "Nilai Terformat",
|
|
12
|
+
"zipped": "Di kompres",
|
|
13
|
+
"fileType": "Tipe Berkas",
|
|
14
|
+
"aboutToRemoveRecord": "Anda akan menghapus satu atau lebih data. Anda yakin akan melakukannya?",
|
|
15
|
+
"columns": "Kolom",
|
|
16
|
+
"noStatYet": "Maaf, belum ada statistik",
|
|
17
17
|
"%s - %s": "%s - %s",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
18
|
+
"list": "Daftar",
|
|
19
|
+
"add": "Tambah",
|
|
20
|
+
"edit": "Ubah",
|
|
21
|
+
"yes": "Ya",
|
|
22
|
+
"no": "Tidak",
|
|
23
|
+
"db": "DB",
|
|
24
|
+
"excelXlsx": "Excel XLSX",
|
|
25
|
+
"csv": "CSV",
|
|
26
|
+
"xml": "XML",
|
|
27
|
+
"json": "JSON",
|
|
28
|
+
"addMoreAfterSubmit": "Tambah lagi setelah kirim",
|
|
29
|
+
"clonePrevious": "Duplikasi sebelumnya",
|
|
30
|
+
"actionPermanentlyDisabled%s": "Sorry, action '%s' is permanently disabled at database level. For more information, please contact your Admin immediately, thank you!",
|
|
24
31
|
"op": {
|
|
25
32
|
"equals": "Sama Dengan",
|
|
26
33
|
"notEquals": "Tidak Sama Dengan",
|
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
</c:grid-col>
|
|
7
7
|
<c:grid-col col="6-md">
|
|
8
8
|
<c:div flex="justify-content:end-md align-items:center">
|
|
9
|
-
<c:btn type="reset" color="secondary" t:content="
|
|
10
|
-
<c:btn type="submit" color="primary" t:content="
|
|
9
|
+
<c:btn type="reset" color="secondary" t:content="reset" />
|
|
10
|
+
<c:btn type="submit" color="primary" t:content="submit" margin="start-2"/>
|
|
11
11
|
</c:div>
|
|
12
12
|
</c:grid-col>
|
|
13
13
|
<c:grid-col col="12" margin="top-4">
|
|
14
|
-
<c:form-switch name="_addmore" t:label="
|
|
15
|
-
<c:form-switch name="_cloneprev" t:label="
|
|
14
|
+
<c:form-switch name="_addmore" t:label="addMoreAfterSubmit"/>
|
|
15
|
+
<c:form-switch name="_cloneprev" t:label="clonePrevious"/>
|
|
16
16
|
</c:grid-col>
|
|
17
17
|
</c:grid-row>
|
|
18
18
|
</c:form>
|
|
@@ -11,8 +11,8 @@
|
|
|
11
11
|
</c:grid-col>
|
|
12
12
|
<c:grid-col col="6-lg" flex="justify-content:end-lg align-items:center">
|
|
13
13
|
<c:wdb-btn-delete/>
|
|
14
|
-
<c:btn type="reset" color="secondary" t:content="
|
|
15
|
-
<c:btn type="submit" color="primary" t:content="
|
|
14
|
+
<c:btn type="reset" color="secondary" t:content="reset" margin="start-2"/>
|
|
15
|
+
<c:btn type="submit" color="primary" t:content="submit" margin="start-2"/>
|
|
16
16
|
</c:grid-col>
|
|
17
17
|
</c:grid-row>
|
|
18
18
|
</c:form>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('
|
|
1
|
+
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('add') %>" />
|
|
2
2
|
<!-- include waibuDb.partial:/crud/add-handler.html -->
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('
|
|
1
|
+
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('details') %>" />
|
|
2
2
|
<!-- include waibuDb.partial:/crud/details-handler.html -->
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('
|
|
1
|
+
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('edit') %>" />
|
|
2
2
|
<!-- include waibuDb.partial:/crud/edit-handler.html -->
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('
|
|
1
|
+
<c:heading move-to="#fullTitle" type="5" t:content="%s - %s|<%= page.modelTitle %>|<%= _t('list') %>" />
|
|
2
2
|
<!-- include waibuDb.partial:/crud/list-handler.html -->
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
<c:div margin="top-5">
|
|
2
2
|
<c:heading type="3-display" t:content="Action Disabled" margin="bottom-5"/>
|
|
3
3
|
<c:div>
|
|
4
|
-
<c:t value="<%= action %>">
|
|
5
|
-
please contact your Admin immediately, thank you!</c:t>
|
|
4
|
+
<c:t value="<%= action %>">actionPermanentlyDisabled%s</c:t>
|
|
6
5
|
</c:t>
|
|
7
6
|
</c:div>
|
|
8
7
|
</c:div>
|
package/package.json
CHANGED
|
@@ -26,10 +26,10 @@ function modelsMenu (locals, req) {
|
|
|
26
26
|
const items = omenu[k]
|
|
27
27
|
const plugin = this.app[items[0].ns]
|
|
28
28
|
menu.push({
|
|
29
|
-
|
|
29
|
+
title: k,
|
|
30
30
|
children: map(items, item => {
|
|
31
31
|
return {
|
|
32
|
-
|
|
32
|
+
title: camelCase(item.name.slice(plugin.alias.length)),
|
|
33
33
|
href: `waibuAdmin:/${prefix}/${kebabCase(item.name)}/list`
|
|
34
34
|
}
|
|
35
35
|
})
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import prepCrud from '../../../lib/prep-crud.js'
|
|
2
2
|
|
|
3
3
|
async function get ({ model, req, reply, id, options = {} }) {
|
|
4
|
-
const {
|
|
5
|
-
const {
|
|
6
|
-
|
|
7
|
-
opts.
|
|
8
|
-
const ret = await
|
|
9
|
-
if (attachment) ret.data._attachment = await attachmentFind(name, id, { stats, mimeType })
|
|
4
|
+
const { recordFindOne, attachmentFind } = this.app.dobo
|
|
5
|
+
const { name, filter, opts, attachment, stats, mimeType } = prepCrud.call(this, { model, req, reply, id, options, args: ['model', 'id'] })
|
|
6
|
+
filter.query = { $and: [filter.query ?? {}, { id: id ?? req.params.id }] }
|
|
7
|
+
opts.dataOnly = true
|
|
8
|
+
const ret = await recordFindOne(name, filter, opts)
|
|
9
|
+
if (attachment) ret.data._attachment = await attachmentFind(name, ret.id, { stats, mimeType })
|
|
10
10
|
return ret
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -13,7 +13,7 @@ async function btnAdd () {
|
|
|
13
13
|
this.params.html = ''
|
|
14
14
|
return
|
|
15
15
|
}
|
|
16
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
16
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('add')
|
|
17
17
|
this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
|
|
18
18
|
if (!this.params.attr.href) this.params.attr.href = this.component.buildUrl({ base: 'add' })
|
|
19
19
|
this.params.html = await this.component.buildTag({ tag: 'btn', attr: this.params.attr, html: this.params.html })
|
|
@@ -9,7 +9,7 @@ async function btnBack () {
|
|
|
9
9
|
const { attrToArray } = this.plugin.app.waibuMpa
|
|
10
10
|
const { req } = this.component
|
|
11
11
|
this.params.noTag = true
|
|
12
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
12
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('back')
|
|
13
13
|
if (isEmpty(this.params.attr.icon)) this.params.attr.icon = 'arrowStart'
|
|
14
14
|
this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
|
|
15
15
|
this.params.attr.excludeQs = ['mode', 'id', ...attrToArray(this.params.attr.excludeQs ?? '')]
|
|
@@ -13,7 +13,7 @@ async function btnClone () {
|
|
|
13
13
|
this.params.html = ''
|
|
14
14
|
return
|
|
15
15
|
}
|
|
16
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
16
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('clone')
|
|
17
17
|
this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
|
|
18
18
|
if (!this.params.attr.href) this.params.attr.href = this.component.buildUrl({ base: 'add', exclude: ['id'] }) + '&mode=clone'
|
|
19
19
|
if (this.params.attr.onList) {
|
|
@@ -20,7 +20,7 @@ async function btnColumns () {
|
|
|
20
20
|
if (isEmpty(fields)) fields = schema.view.fields
|
|
21
21
|
const items = []
|
|
22
22
|
this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
|
|
23
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
23
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('columns')
|
|
24
24
|
for (const f of schema.view.fields) {
|
|
25
25
|
if (f === 'id') {
|
|
26
26
|
items.push(await this.component.buildTag({ tag: 'formCheck', attr: { checked: true, label: req.t('ID'), value: f, disabled: true } }))
|
|
@@ -44,7 +44,7 @@ async function btnColumns () {
|
|
|
44
44
|
">`)
|
|
45
45
|
html.push(...items)
|
|
46
46
|
const attr = { size: 'sm', 'x-ref': 'apply', margin: 'top-2', color: this.params.attr.applyColor ?? 'primary', icon: this.params.attr.applyIcon ?? 'arrowsStartEnd', href }
|
|
47
|
-
html.push(await this.component.buildTag({ tag: 'btn', attr, html: req.t('
|
|
47
|
+
html.push(await this.component.buildTag({ tag: 'btn', attr, html: req.t('apply') }))
|
|
48
48
|
html.push('</form>')
|
|
49
49
|
this.params.attr.autoClose = 'outside'
|
|
50
50
|
this.params.attr.triggerColor = this.params.attr.color
|
|
@@ -14,7 +14,7 @@ async function btnDelete () {
|
|
|
14
14
|
this.params.html = ''
|
|
15
15
|
return
|
|
16
16
|
}
|
|
17
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
17
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('delete')
|
|
18
18
|
this.params.attr.color = this.params.attr.color ?? 'danger-outline'
|
|
19
19
|
this.params.attr.id = generateId('alpha')
|
|
20
20
|
if (this.params.attr.onList) {
|
|
@@ -41,7 +41,7 @@ async function btnDelete () {
|
|
|
41
41
|
}
|
|
42
42
|
}`
|
|
43
43
|
}
|
|
44
|
-
const msg = '
|
|
44
|
+
const msg = 'aboutToRemoveRecord'
|
|
45
45
|
this.params.attr['@click'] = `
|
|
46
46
|
await wbs.confirmation(\`${req.t(msg)}\`, { ok: '${this.params.attr.id}:remove', close: 'y', opts: selected })
|
|
47
47
|
`
|
|
@@ -14,7 +14,7 @@ async function btnDetails () {
|
|
|
14
14
|
this.params.html = ''
|
|
15
15
|
return
|
|
16
16
|
}
|
|
17
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
17
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('details')
|
|
18
18
|
this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
|
|
19
19
|
this.params.attr.id = generateId('alpha')
|
|
20
20
|
if (!this.params.attr.href) this.params.attr.href = this.component.buildUrl({ base: 'details', exclude: ['id'] })
|
|
@@ -14,7 +14,7 @@ async function btnEdit () {
|
|
|
14
14
|
this.params.html = ''
|
|
15
15
|
return
|
|
16
16
|
}
|
|
17
|
-
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('
|
|
17
|
+
if (isEmpty(this.params.attr.content)) this.params.attr.content = req.t('edit')
|
|
18
18
|
this.params.attr.color = this.params.attr.color ?? 'secondary-outline'
|
|
19
19
|
this.params.attr.id = generateId('alpha')
|
|
20
20
|
if (!this.params.attr.href) this.params.attr.href = this.component.buildUrl({ base: 'edit', exclude: ['id'] })
|
|
@@ -52,7 +52,7 @@ async function btnEdit () {
|
|
|
52
52
|
}
|
|
53
53
|
`
|
|
54
54
|
const html = [
|
|
55
|
-
await this.component.buildTag({ tag: 'dropdownItem', attr: { content: req.t('
|
|
55
|
+
await this.component.buildTag({ tag: 'dropdownItem', attr: { content: req.t('addAsNewClone') } })
|
|
56
56
|
]
|
|
57
57
|
this.params.attr.triggerColor = this.params.attr.color
|
|
58
58
|
this.params.html = await this.component.buildTag({ tag: 'dropdown', attr: this.params.attr, html: html.join('\n') })
|
|
@@ -4,6 +4,10 @@ async function btnExport () {
|
|
|
4
4
|
const WdbBase = await wdbBase.call(this)
|
|
5
5
|
|
|
6
6
|
return class WdbBtnExport extends WdbBase {
|
|
7
|
+
static scripts = [...super.scripts,
|
|
8
|
+
'waibuMpa.virtual:/json2csv/json2csv.js'
|
|
9
|
+
]
|
|
10
|
+
|
|
7
11
|
build = async () => {
|
|
8
12
|
const { isEmpty, get } = this.plugin.app.bajo.lib._
|
|
9
13
|
const { req } = this.component
|
|
@@ -15,9 +19,9 @@ async function btnExport () {
|
|
|
15
19
|
this.params.html = ''
|
|
16
20
|
return
|
|
17
21
|
}
|
|
18
|
-
if (isEmpty(this.params.attr.trigger)) this.params.attr.trigger = req.t('
|
|
22
|
+
if (isEmpty(this.params.attr.trigger)) this.params.attr.trigger = req.t('export')
|
|
19
23
|
this.params.attr.triggerColor = this.params.attr.triggerColor ?? 'secondary-outline'
|
|
20
|
-
this.params.attr.title = req.t('
|
|
24
|
+
this.params.attr.title = req.t('dataExport')
|
|
21
25
|
const html = await this.component.buildSentence(`
|
|
22
26
|
<c:div x-data="{
|
|
23
27
|
delivery: 'clipboard',
|
|
@@ -71,8 +75,15 @@ async function btnExport () {
|
|
|
71
75
|
for (const el of els) {
|
|
72
76
|
let data = []
|
|
73
77
|
_.each(el.children, (v, i) => {
|
|
74
|
-
|
|
75
|
-
|
|
78
|
+
i = i + ''
|
|
79
|
+
if (i === '0' && checker) return undefined
|
|
80
|
+
if (this.options.includes('fvalue')) data.push(v.innerText)
|
|
81
|
+
else {
|
|
82
|
+
const type = types[parseInt(i)]
|
|
83
|
+
let val = wmpa.parseValue(v.dataset.value, type)
|
|
84
|
+
if (['datetime', 'date', 'time'].includes(type)) val = val.toISOString()
|
|
85
|
+
data.push(val)
|
|
86
|
+
}
|
|
76
87
|
})
|
|
77
88
|
const item = {}
|
|
78
89
|
for (const i in keys) {
|
|
@@ -105,28 +116,28 @@ async function btnExport () {
|
|
|
105
116
|
">
|
|
106
117
|
<c:grid-row gutter="2">
|
|
107
118
|
<c:grid-col col="6-md">
|
|
108
|
-
<c:fieldset t:legend="
|
|
109
|
-
<c:form-radio x-model="delivery" value="file" t:label="
|
|
110
|
-
<c:form-radio x-model="delivery" value="clipboard" t:label="
|
|
119
|
+
<c:fieldset t:legend="delivery" legend-type="6">
|
|
120
|
+
<c:form-radio x-model="delivery" value="file" t:label="saveAsFile" />
|
|
121
|
+
<c:form-radio x-model="delivery" value="clipboard" t:label="copyClipboard" />
|
|
111
122
|
</c:fieldset>
|
|
112
|
-
<c:fieldset t:legend="
|
|
113
|
-
<c:form-check x-ref="fkey" x-model="options" value="fkey" t:label="
|
|
114
|
-
<c:form-check x-ref="fvalue" x-model="options" value="fvalue" t:label="
|
|
115
|
-
<c:form-check x-ref="zip" x-model="options" value="zip" t:label="
|
|
123
|
+
<c:fieldset t:legend="options" legend-type="6" margin="top-2">
|
|
124
|
+
<c:form-check x-ref="fkey" x-model="options" value="fkey" t:label="formattedField" />
|
|
125
|
+
<c:form-check x-ref="fvalue" x-model="options" value="fvalue" t:label="formattedValue" />
|
|
126
|
+
<c:form-check x-ref="zip" x-model="options" value="zip" t:label="zipped" />
|
|
116
127
|
</c:fieldset>
|
|
117
128
|
</c:grid-col>
|
|
118
129
|
<c:grid-col col="6-md">
|
|
119
|
-
<c:fieldset t:legend="
|
|
120
|
-
<c:form-radio x-ref="xlsx" x-model="ftype" value="xlsx" t:label="
|
|
121
|
-
<c:form-radio x-ref="csv" x-model="ftype" value="csv" t:label="
|
|
122
|
-
<c:form-radio x-ref="xml" x-model="ftype" value="xml" t:label="
|
|
123
|
-
<c:form-radio x-ref="json" x-model="ftype" value="json" t:label="
|
|
130
|
+
<c:fieldset t:legend="fileType" legend-type="6">
|
|
131
|
+
<c:form-radio x-ref="xlsx" x-model="ftype" value="xlsx" t:label="excelXlsx" />
|
|
132
|
+
<c:form-radio x-ref="csv" x-model="ftype" value="csv" t:label="csv" />
|
|
133
|
+
<c:form-radio x-ref="xml" x-model="ftype" value="xml" t:label="xml" />
|
|
134
|
+
<c:form-radio x-ref="json" x-model="ftype" value="json" t:label="json" />
|
|
124
135
|
</c:fieldset />
|
|
125
136
|
</c:grid-col>
|
|
126
137
|
</c:grid-row>
|
|
127
138
|
<c:div flex="justify-content:end" margin="top-3">
|
|
128
|
-
<c:btn color="secondary" t:content="
|
|
129
|
-
<c:btn color="primary" t:content="
|
|
139
|
+
<c:btn color="secondary" t:content="close" dismiss />
|
|
140
|
+
<c:btn color="primary" t:content="submit" margin="start-2" @click="await submit()" />
|
|
130
141
|
</c:div>
|
|
131
142
|
</c:div>
|
|
132
143
|
`)
|
|
@@ -51,12 +51,12 @@ async function query () {
|
|
|
51
51
|
this.params.noTag = true
|
|
52
52
|
const container = this.params.attr.modal ? 'modal' : 'drawer'
|
|
53
53
|
this.params.html = await this.component.buildSentence(`
|
|
54
|
-
<c:form-input ${count === 0 ? 'disabled' : ''} type="search" t:placeholder="
|
|
54
|
+
<c:form-input ${count === 0 ? 'disabled' : ''} type="search" t:placeholder="query" id="${id}" x-data="{ query: '' }" x-init="
|
|
55
55
|
const url = new URL(window.location.href)
|
|
56
56
|
query = url.searchParams.get('${qsKey.query}') ?? ''
|
|
57
57
|
" x-model="query" @on-query.window="query = $event.detail ?? ''" @keyup.enter="$dispatch('on-submit')">
|
|
58
58
|
<c:form-input-addon>
|
|
59
|
-
<c:${container} ${count === 0 ? 'trigger-disabled' : ''} trigger-icon="${this.params.attr.icon ?? 'dotsThree'}" trigger-on-end t:title="
|
|
59
|
+
<c:${container} ${count === 0 ? 'trigger-disabled' : ''} trigger-icon="${this.params.attr.icon ?? 'dotsThree'}" trigger-on-end t:title="queryBuilder" x-ref="query" x-data="{
|
|
60
60
|
fields: ${jsonStringify(fields, true)},
|
|
61
61
|
builder: '',
|
|
62
62
|
selected: [],
|
|
@@ -151,14 +151,14 @@ async function query () {
|
|
|
151
151
|
${columns.join('\n')}
|
|
152
152
|
</c:grid-row>
|
|
153
153
|
<c:div flex="justify-content:end" margin="top-3">
|
|
154
|
-
<c:btn color="secondary" t:content="
|
|
155
|
-
<c:btn color="primary" t:content="
|
|
156
|
-
<c:btn color="primary" t:content="
|
|
154
|
+
<c:btn color="secondary" t:content="close" dismiss="${container}" />
|
|
155
|
+
<c:btn color="primary" t:content="apply" margin="start-2" @click="submit()" />
|
|
156
|
+
<c:btn color="primary" t:content="submitQuery" margin="start-2" @click="submit(true)" />
|
|
157
157
|
</c:div>
|
|
158
158
|
</c:${container}>
|
|
159
159
|
</c:form-input-addon>
|
|
160
160
|
<c:form-input-addon>
|
|
161
|
-
<c:btn ${count === 0 ? 'disabled' : ''} t:content="
|
|
161
|
+
<c:btn ${count === 0 ? 'disabled' : ''} t:content="submit" x-data="{
|
|
162
162
|
submit () {
|
|
163
163
|
const val = document.getElementById('${id}').value ?? ''
|
|
164
164
|
const url = new URL(window.location.href)
|
|
@@ -30,10 +30,10 @@ async function recsInfo () {
|
|
|
30
30
|
if (!this.params.attr.dropdown) this.params.attr.dropdown = true
|
|
31
31
|
const group = groupAttrs(this.params.attr, ['dropdown'])
|
|
32
32
|
const html = []
|
|
33
|
-
if (this.params.attr.count) html.push(req.t('%s
|
|
33
|
+
if (this.params.attr.count) html.push(req.t('recsFound%s', req.format(count, 'integer')))
|
|
34
34
|
if (this.params.attr.pages) {
|
|
35
35
|
if (!isEmpty(html)) html[html.length - 1] += '.'
|
|
36
|
-
html.push(req.t('
|
|
36
|
+
html.push(req.t('pageOfPages%s%s', req.format(page, 'integer'), req.format(pages, 'integer')))
|
|
37
37
|
}
|
|
38
38
|
if (this.params.attr.recsPerPage) {
|
|
39
39
|
this.params.attr.recsPerPageValues = this.params.attr.recsPerPageValues ?? '10 25 50'
|
|
@@ -48,7 +48,7 @@ async function recsInfo () {
|
|
|
48
48
|
attr.content = limit + ''
|
|
49
49
|
attr.color = attr.color ?? 'secondary-outline'
|
|
50
50
|
html.push(await this.component.buildTag({ tag: 'dropdown', attr, html: items.join('\n') }))
|
|
51
|
-
html.push(' ', req.t('
|
|
51
|
+
html.push(' ', req.t('recsPerPage'))
|
|
52
52
|
}
|
|
53
53
|
this.params.attr = omit(this.params.attr, ['count', 'pages', 'recsPerPage', 'dropdown', 'recsPerPageValues'])
|
|
54
54
|
this.params.html = html.map(h => `<div class="me-1">${h}</div>`).join('\n')
|
|
@@ -29,9 +29,10 @@ async function table () {
|
|
|
29
29
|
const prettyUrl = this.params.attr.prettyUrl
|
|
30
30
|
|
|
31
31
|
const data = get(this, 'component.locals.list.data', [])
|
|
32
|
+
const filter = get(this, 'component.locals.list.filter', {})
|
|
32
33
|
const count = get(this, 'component.locals.list.count', 0)
|
|
33
34
|
if (count === 0) {
|
|
34
|
-
const alert = '<c:alert color="warning" t:content="
|
|
35
|
+
const alert = '<c:alert color="warning" t:content="noRecordFound" margin="top-4"/>'
|
|
35
36
|
this.params.noTag = true
|
|
36
37
|
this.params.html = await this.component.buildSentence(alert)
|
|
37
38
|
return
|
|
@@ -45,7 +46,11 @@ async function table () {
|
|
|
45
46
|
const qsKey = this.plugin.app.waibu.config.qsKey
|
|
46
47
|
let fields = without(get(this, `component.locals._meta.query.${qsKey.fields}`, '').split(','), '')
|
|
47
48
|
if (isEmpty(fields)) fields = schema.view.fields
|
|
48
|
-
|
|
49
|
+
let sort = this.params.attr.sort ? attrToArray(this.params.attr.sort) : get(this, `component.locals._meta.query.${qsKey.sort}`, '')
|
|
50
|
+
if (isEmpty(sort)) {
|
|
51
|
+
const keys = Object.keys(filter.sort)
|
|
52
|
+
if (keys.length > 0) sort = `${keys[0]}:${filter.sort[keys[0]]}`
|
|
53
|
+
}
|
|
49
54
|
|
|
50
55
|
let [sortCol, sortDir] = sort.split(':')
|
|
51
56
|
if (!['-1', '1'].includes(sortDir)) sortDir = '1'
|
|
@@ -63,7 +68,8 @@ async function table () {
|
|
|
63
68
|
// head
|
|
64
69
|
for (const f of schema.view.fields) {
|
|
65
70
|
if (!fields.includes(f)) continue
|
|
66
|
-
|
|
71
|
+
let prop = find(schema.properties, { name: f })
|
|
72
|
+
if (!prop) prop = find(schema.view.calcFields, { name: f })
|
|
67
73
|
if (!prop) continue
|
|
68
74
|
let head = req.t(get(schema, `view.label.${f}`, `field.${f}`))
|
|
69
75
|
if (!this.params.attr.noSort && (schema.sortables ?? []).includes(f)) {
|
|
@@ -113,7 +119,8 @@ async function table () {
|
|
|
113
119
|
}
|
|
114
120
|
for (const f of schema.view.fields) {
|
|
115
121
|
if (!fields.includes(f)) continue
|
|
116
|
-
|
|
122
|
+
let prop = find(schema.properties, { name: f })
|
|
123
|
+
if (!prop) prop = find(schema.view.calcFields, { name: f })
|
|
117
124
|
if (!prop) continue
|
|
118
125
|
const opts = {}
|
|
119
126
|
if (f === 'lng') opts.longitude = true
|
|
@@ -124,8 +131,14 @@ async function table () {
|
|
|
124
131
|
' ' + (req.t(d[f] ? 'Yes' : 'No'))
|
|
125
132
|
} else value = escape(value)
|
|
126
133
|
let dataValue = d[f] ?? ''
|
|
134
|
+
if (['datetime'].includes(prop.type)) dataValue = escape(dataValue.toISOString())
|
|
127
135
|
if (['string', 'text'].includes(prop.type)) dataValue = escape(dataValue)
|
|
128
136
|
if (['array', 'object'].includes(prop.type)) dataValue = escape(JSON.stringify(d[f]))
|
|
137
|
+
const vf = get(schema, `view.valueFormatter.${f}`)
|
|
138
|
+
if (vf) {
|
|
139
|
+
if (isFunction(vf)) dataValue = escape(await vf(d[f], d))
|
|
140
|
+
else dataValue = await callHandler(vf, req, d[f], d)
|
|
141
|
+
}
|
|
129
142
|
const attr = { dataValue, dataKey: prop.name, dataType: prop.type, style: { cursor: 'pointer' } }
|
|
130
143
|
const cellFormatter = get(schema, `view.cellFormatter.${f}`)
|
|
131
144
|
if (cellFormatter) merge(attr, await cellFormatter(dataValue, d))
|
|
@@ -158,6 +171,7 @@ async function table () {
|
|
|
158
171
|
const goDetails = `
|
|
159
172
|
goDetails (id) {
|
|
160
173
|
let url = '${this.params.attr.detailsHref ?? this.component.buildUrl({ base: 'details', prettyUrl })}'
|
|
174
|
+
if (url === '#') return
|
|
161
175
|
if (url.indexOf('/:id') > -1) url = url.replace('/:id', '/' + id)
|
|
162
176
|
else url += '&id=' + id
|
|
163
177
|
window.location.href = url
|