waibu-db 2.12.4 → 2.12.5

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.
@@ -39,19 +39,20 @@
39
39
  "dataValue": "Data value",
40
40
  "suppressedError": "Error occured and suppressed. Please check error log for details",
41
41
  "op": {
42
- "equals": "Equals",
43
- "notEquals": "Not Equals",
44
- "greaterThan": "Greater Than",
45
- "greaterThanOrEquals": "Greater Than or Equals",
46
- "lessThan": "Less Than",
47
- "lessThanOrEquals": "Less Than or Equals",
48
- "in": "Includes",
49
- "notIn": "Not Includes",
50
- "contains": "Contains",
51
- "notContains": "Not Contains",
52
- "startsWith": "Starts With",
53
- "notStartsWith": "Not Starts With",
54
- "endsWith": "Ends With",
55
- "notEndsWith": "Not Ends With"
42
+ "eq": "=",
43
+ "neq": "",
44
+ "gt": ">",
45
+ "gte": "",
46
+ "lt": "<",
47
+ "lte": "",
48
+ "between": "between",
49
+ "in": "includes",
50
+ "!in": "not includes",
51
+ "contains": "contains",
52
+ "!contains": "not contains",
53
+ "starts": "starts with",
54
+ "!starts": "not starts with",
55
+ "ends": "ends with",
56
+ "!ends": "not ends with"
56
57
  }
57
58
  }
@@ -39,19 +39,20 @@
39
39
  "dataValue": "Nilai data",
40
40
  "suppressedError": "Kesalahan terjadi dan tidak ditampilkan. Silahkan cek log kesalahan untuk detilnya",
41
41
  "op": {
42
- "equals": "Sama Dengan",
43
- "notEquals": "Tidak Sama Dengan",
44
- "greaterThan": "Lebih Besar Dari",
45
- "greaterThanOrEquals": "Lebih Besar Dari atau Sama Dengan",
46
- "lessThan": "Lebih Kecil Dari",
47
- "lessThanOrEquals": "Lebih Kecil Dari atau Sama Dengan",
48
- "in": "Termasuk",
49
- "notIn": "Tidak Termasuk",
50
- "contains": "Mengandung",
51
- "notContains": "Tidak Mengandung",
52
- "startsWith": "Dimulai Dengan",
53
- "notStartsWith": "Tidak Dimulai Dengan",
54
- "endsWith": "Diakhiri Dengan",
55
- "notEndsWith": "Tidak Diakhiri Dengan"
42
+ "eq": "=",
43
+ "neq": "",
44
+ "gt": ">",
45
+ "gte": "",
46
+ "lt": "<",
47
+ "lte": "",
48
+ "between": "between",
49
+ "in": "termasuk",
50
+ "!in": "tidak termasuk",
51
+ "contains": "mengandung",
52
+ "!contains": "tidak mengandung",
53
+ "starts": "dimulai dengan",
54
+ "!starts": "tidak dimulai dengan",
55
+ "ends": "diakhiri dengan",
56
+ "!ends": "tidak diakhiri dengan"
56
57
  }
57
58
  }
@@ -49,7 +49,7 @@ async function btnColumns () {
49
49
  this.params.attr.autoClose = 'outside'
50
50
  this.params.attr.triggerColor = this.params.attr.color
51
51
  this.params.attr.menuDir = this.params.attr.menuDir ?? 'end'
52
- this.params.attr.menuMax = this.params.attr.menuMax ?? '10'
52
+ this.params.attr.menuMax = this.params.attr.menuMax ?? '20'
53
53
  const html = [...items]
54
54
  this.params.html = await this.component.buildTag({ tag: 'dropdown', attr: this.params.attr, html: html.join('\n') })
55
55
  this.params.noTag = true
@@ -27,7 +27,8 @@ async function pagination () {
27
27
  }
28
28
  let { count, limit, page } = attrToObject(this.params.attr.options)
29
29
  count = count ?? get(this, 'component.locals.list.count', 0)
30
- if (count === 0) {
30
+ const data = get(this, 'component.locals.list.data', [])
31
+ if (count === 0 || data.length === 0) {
31
32
  this.params.noTag = true
32
33
  this.params.html = ''
33
34
  return
@@ -5,6 +5,7 @@ async function query () {
5
5
 
6
6
  return class WdbQuery extends WdbBase {
7
7
  build = async () => {
8
+ const { req } = this.component
8
9
  const { generateId } = this.app.lib.aneka
9
10
  const { jsonStringify } = this.app.waibuMpa
10
11
  const { find, get, without, isEmpty, filter, upperFirst } = this.app.lib._
@@ -24,27 +25,37 @@ async function query () {
24
25
  if (!fields.includes(f)) continue
25
26
  const prop = find(schema.properties, { name: f })
26
27
  const ops = []
27
- if (['float', 'double', 'integer', 'smallint'].includes(prop.type)) ops.push('eq', 'neq', 'gt', 'gte', 'lt', 'lte')
28
- else if (['datetime', 'date', 'time'].includes(prop.type)) ops.push('eq', 'neq', 'gt', 'gte', 'lt', 'lte')
28
+ if (['float', 'double', 'integer', 'smallint'].includes(prop.type)) ops.push('eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'between')
29
+ else if (['datetime', 'date', 'time'].includes(prop.type)) ops.push('eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'between', 'in')
29
30
  else if (['boolean'].includes(prop.type)) ops.push('eq', 'neq')
30
31
  else ops.push('eq', 'neq', 'in', 'contains', 'starts', 'ends', '!in', '!contains', '!starts', '!ends')
31
32
  if (ops.length === 0) continue
32
- const sels = ops.map(o => `<c:option>${o}</c:option>`)
33
- models.push(`${f}Op: 'eq'`, `${f}Val: ''`)
33
+ const sels = ops.map(o => `<c:option value="${o}">${req.t('op.' + o)}</c:option>`)
34
+ models.push(`${f}Op: 'eq'`, `${f}Val: ''`, `${f}Val2: ''`)
34
35
  const label = this.component.req.t(get(schema, `view.label.${f}`, `field.${f}`))
35
- columns.push(`
36
+ const items = [`
36
37
  <c:grid-col col="4-md" flex="align-items:center">
37
38
  <c:form-check x-model="selected" t:label="${label}" value="${f}" />
38
39
  </c:grid-col>
39
- <c:grid-col col="3-md">
40
+ <c:grid-col col="2-md">
40
41
  <c:form-select x-model="${f}Op">
41
42
  ${sels.join('\n')}
42
43
  </c:form-select>
43
44
  </c:grid-col>
44
- <c:grid-col col="5-md">
45
- <c:form-input x-model="${f}Val" />
46
- </c:grid-col>
47
- `)
45
+ <c:grid-col col="6-md">
46
+ <c:div flex="justify-content:between">`]
47
+ if (prop.type === 'datetime') {
48
+ items.push(`<c:form-datetime x-model="${f}Val" />`)
49
+ } else {
50
+ items.push(`<c:form-input x-model="${f}Val" />`)
51
+ }
52
+ if (prop.type === 'datetime') {
53
+ items.push(`<c:form-datetime wrapper-x-show="${f}Op === 'between'" x-model="${f}Val2" wrapper-margin="start-2"/>`)
54
+ } else {
55
+ items.push(`<c:form-input wrapper-x-show="${f}Op === 'between'" x-model="${f}Val2" wrapper-margin="start-2" />`)
56
+ }
57
+ items.push('</c:div></c:grid-col>')
58
+ columns.push(items.join('\n'))
48
59
  }
49
60
  this.params.noTag = true
50
61
  const container = this.params.attr.modal ? 'modal' : 'drawer'
@@ -61,40 +72,50 @@ async function query () {
61
72
  ${models.join(',\n')},
62
73
  ops: { eq: ':', neq: ':-', gt: ':>', gte: ':>=', lt: ':<', lte: ':<=' },
63
74
  opsIn (v, neg) { return ':' + (neg ? '-' : '') + '[' + this.expandArray(v) + ']' },
75
+ opsBetween (v, v2, neg) { return ':' + (neg ? '-' : '') + '{' + this.expandArray(v) + ',' + this.expandArray(v2) + '}' },
64
76
  opsExt (v, neg, ext) {
65
77
  let prefix = (neg ? '-' : '') + '~'
66
78
  if (ext) prefix += ext
67
79
  return ':' + prefix + '\\'' + v + '\\''
68
80
  },
69
- initBuilder () {
81
+ parse () {
70
82
  this.builder = document.getElementById('${id}').value
71
83
  if (!this.builder.includes(':')) this.builder = ''
72
84
  if (_.isEmpty(this.builder)) return
73
85
  const tokens = _.merge({}, this.ops, {
74
86
  in: ':[',
87
+ between: ':{',
75
88
  contains: ':~',
76
89
  starts: ':~^',
77
90
  ends: ':~$$',
78
91
  '!in': ':-[',
92
+ '!between': ':-{',
79
93
  '!contains': ':-~',
80
94
  '!starts': ':-~^',
81
95
  '!ends': ':-~$$'
82
96
  })
83
97
  for (const part of this.builder.split('+')) {
84
- let [f, opv] = part.split(':')
85
- opv = ':' + opv
98
+ let [f, ...opv] = part.split(':')
99
+ opv = ':' + opv.join(':')
86
100
  this.selected.push(f)
87
101
  let op
88
102
  let val
89
103
  _.each(tokens, (v, k) => {
90
104
  if (opv.slice(0, v.length) === v) {
91
105
  op = k
92
- val = opv.slice(v.length).replaceAll('[', '').replaceAll(']', '').replaceAll('\\'', '')
106
+ val = opv.slice(v.length).replaceAll('[', '').replaceAll('{', '').replaceAll(']', '').replaceAll('}', '').replaceAll('\\'', '')
93
107
  }
94
108
  })
109
+ console.log(op, val)
95
110
  if (_.isEmpty(op)) continue
96
111
  this[f + 'Op'] = op
97
- this[f + 'Val'] = val
112
+ if (op === 'between') {
113
+ const vals = val.split(',')
114
+ this[f + 'Val'] = vals[0]
115
+ this[f + 'Val2'] = vals[1]
116
+ } else {
117
+ this[f + 'Val'] = val
118
+ }
98
119
  }
99
120
  },
100
121
  expandArray (val = '') {
@@ -109,10 +130,14 @@ async function query () {
109
130
  for (const sel of this.selected) {
110
131
  const key = this[sel + 'Op']
111
132
  let val = this[sel + 'Val']
133
+ let val2 = this[sel + 'Val2']
112
134
  if (_.isEmpty(val)) continue
135
+ if (key === 'between' && _.isEmpty(val2)) continue
113
136
  let item
114
137
  if (key === 'in') item = this.opsIn(val)
115
138
  else if (key === '!in') item = this.opsIn(val, true)
139
+ else if (key === 'between') item = this.opsBetween(val, val2, false)
140
+ else if (key === '!between') item = this.opsBetween(val, val2, true)
116
141
  else if (key === 'contains') item = this.opsExt(val)
117
142
  else if (key === '!contains') item = this.opsExt(val, true)
118
143
  else if (key === 'starts') item = this.opsExt(val, false, '^')
@@ -137,12 +162,13 @@ async function query () {
137
162
  instance.hide()
138
163
  }
139
164
  }" x-init="
140
- initBuilder()
165
+ parse()
141
166
  const ops = _.map(fields, f => (f + 'Op'))
142
167
  const vals = _.map(fields, f => (f + 'Val'))
143
- const watcher = ['selected', ...ops, ...vals].join(',')
168
+ const vals2 = _.map(fields, f => (f + 'Val2'))
169
+ const watcher = ['selected', ...ops, ...vals, ...vals2].join(',')
144
170
  $watch(watcher, v => rebuild())
145
- ">
171
+ " ${this.params.attr.modal ? '' : 'style="width:600px;"'}>
146
172
  <c:grid-row gutter="2">
147
173
  <c:grid-col col="12">
148
174
  <c:form-textarea x-model="builder" readonly rows="4"/>
@@ -17,7 +17,8 @@ async function recsInfo () {
17
17
  }
18
18
  let { count, limit, page, pages } = attrToObject(this.params.attr.options)
19
19
  count = count ?? get(this, 'component.locals.list.count', 0)
20
- if (count === 0) {
20
+ const data = get(this, 'component.locals.list.data', [])
21
+ if (count === 0 || data.length === 0) {
21
22
  this.params.noTag = true
22
23
  this.params.html = ''
23
24
  return
@@ -61,7 +61,7 @@ async function table () {
61
61
  for (const prop of schema.properties) {
62
62
  if (typeof prop.values === 'string') this.propValues[prop.name] = await callHandler(prop.values)
63
63
  }
64
- if (count === 0) {
64
+ if (count === 0 || data.length === 0) {
65
65
  const alert = '<c:alert color="warning" t:content="noRecordFound" margin="top-4"/>'
66
66
  this.params.noTag = true
67
67
  this.params.html = await this.component.buildSentence(alert)
@@ -24,6 +24,9 @@ async function editHandler ({ req, reply, model, id, params = {}, template, addO
24
24
  form = defaultsDeep(req.body, old.data)
25
25
  if (req.method !== 'GET') {
26
26
  form = omit(form, ['_action', '_value'])
27
+ try {
28
+ req.body._value = JSON.parse(req.body._value)
29
+ } catch (err) {}
27
30
  if (req.body._action === 'removeatt' && !isEmpty(req.body._value)) {
28
31
  const root = `${getPluginDataDir('dobo')}/attachment`
29
32
  for (const item of req.body._value) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "waibu-db",
3
- "version": "2.12.4",
3
+ "version": "2.12.5",
4
4
  "description": "DB Helper",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/wiki/CHANGES.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changes
2
2
 
3
+ ## 2026-04-01
4
+
5
+ - [2.12.4] Bug fix in ```wdb-btn-column``` widget
6
+ - [2.12.4] Bug fix in ```wdb-pagination``` widget
7
+ - [2.12.4] Bug fix in ```wdb-query``` widget
8
+ - [2.12.4] Bug fix in ```wdb-recs-info``` widget
9
+ - [2.12.4] Bug fix in ```wdb-table``` widget
10
+ - [2.12.4] Bug fix in remove attachment
11
+
3
12
  ## 2026-03-30
4
13
 
5
14
  - [2.12.3] Bug fix in transaction supports