sumba 2.16.0 → 2.18.0

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.
Files changed (34) hide show
  1. package/extend/bajo/intl/en-US.json +5 -0
  2. package/extend/bajo/intl/id.json +5 -0
  3. package/extend/dobo/feature/country.js +3 -3
  4. package/extend/dobo/feature/email.js +2 -2
  5. package/extend/dobo/feature/lat-lng.js +8 -8
  6. package/extend/dobo/feature/lat.js +2 -2
  7. package/extend/dobo/feature/lng.js +2 -2
  8. package/extend/dobo/feature/phone.js +2 -2
  9. package/extend/dobo/feature/site-id.js +2 -2
  10. package/extend/dobo/feature/slug.js +14 -14
  11. package/extend/dobo/feature/status.js +7 -4
  12. package/extend/dobo/feature/team-id.js +4 -2
  13. package/extend/dobo/feature/ts.js +2 -2
  14. package/extend/dobo/feature/url.js +4 -4
  15. package/extend/dobo/feature/user-id.js +3 -1
  16. package/extend/dobo/model/ticket.json +14 -1
  17. package/extend/waibuDb/schema/download.js +1 -1
  18. package/extend/waibuDb/schema/site.js +1 -30
  19. package/extend/waibuDb/schema/team-setting.js +1 -1
  20. package/extend/waibuDb/schema/team-user.js +3 -25
  21. package/extend/waibuDb/schema/ticket.json +16 -0
  22. package/extend/waibuDb/schema/user-setting.js +1 -1
  23. package/extend/waibuDb/schema/user.js +1 -1
  24. package/extend/waibuMpa/extend/waibuAdmin/route/site.js +45 -1
  25. package/extend/waibuMpa/route/help/trouble-tickets/details/@id.js +1 -1
  26. package/extend/waibuMpa/route/help/trouble-tickets/list.js +1 -1
  27. package/extend/waibuRestApi/route/manage/ticket-cat/model-builder.json +4 -0
  28. package/index.js +5 -16
  29. package/lib/util.js +2 -2
  30. package/package.json +1 -1
  31. package/wiki/CHANGES.md +9 -0
  32. /package/extend/waibuMpa/extend/waibuAdmin/route/{_is_/site → all-sites}/@action.js +0 -0
  33. /package/extend/waibuMpa/extend/waibuAdmin/route/{_is_/cache → cache}/@action.js +0 -0
  34. /package/extend/waibuMpa/extend/waibuAdmin/route/{_is_/session → session}/@action.js +0 -0
@@ -131,6 +131,11 @@
131
131
  "protectedArea": "Protected Area",
132
132
  "pleaseAuthenticate": "Please authenticate yourself, thank you!",
133
133
  "manageAllSite": "Manage All Sites",
134
+ "statusEnabled": "Enabled",
135
+ "statusDisabled": "Disabled",
136
+ "statusOpen": "Open",
137
+ "statusClosed": "Closed",
138
+ "allSites": "All Sites",
134
139
  "field": {
135
140
  "currentPassword": "Current Password",
136
141
  "newPassword": "New Password",
@@ -132,6 +132,11 @@
132
132
  "protectedArea": "Wilayah Dilindungi",
133
133
  "pleaseAuthenticate": "Silahkan melakukan otentikasi terlebih dahulu, terima kasih!",
134
134
  "manageAllSite": "Kelola Semua Situs",
135
+ "statusEnabled": "Dihidupkan",
136
+ "statusDisabled": "Dimatikan",
137
+ "statusOpen": "Terbuka",
138
+ "statusClosed": "Tertutup",
139
+ "allSites": "Semua Situs",
135
140
  "field": {
136
141
  "currentPassword": "Kata Sandi Saat Ini",
137
142
  "newPassword": "Kata Sandi Baru",
@@ -1,8 +1,8 @@
1
1
  async function country (opts = {}) {
2
- opts.fieldName = opts.fieldName ?? 'country'
2
+ opts.field = opts.field ?? 'country'
3
3
  return {
4
4
  properties: [{
5
- name: opts.fieldName,
5
+ name: opts.field,
6
6
  type: 'string',
7
7
  maxLength: 2,
8
8
  index: opts.index ?? true,
@@ -10,7 +10,7 @@ async function country (opts = {}) {
10
10
  rules: ['uppercase', { rule: 'length', params: 2 }],
11
11
  rulesMsg: { 'any.only': 'validCountryCodeRequired' }
12
12
  }],
13
- rules: [{ rule: 'trim', fields: [opts.fieldName] }]
13
+ rules: [{ rule: 'trim', fields: [opts.field] }]
14
14
  }
15
15
  }
16
16
 
@@ -1,8 +1,8 @@
1
1
  async function email (opts = {}) {
2
- opts.fieldName = opts.fieldName ?? 'email'
2
+ opts.field = opts.field ?? 'email'
3
3
  return {
4
4
  properties: [{
5
- name: opts.fieldName ?? 'email',
5
+ name: opts.field ?? 'email',
6
6
  type: 'string',
7
7
  maxLength: 50,
8
8
  rules: ['email']
@@ -2,20 +2,20 @@ import { latLngHook } from '../../../lib/util.js'
2
2
 
3
3
  async function latLng (opts = {}) {
4
4
  const { merge } = this.app.lib._
5
- opts.fieldNameLat = opts.fieldNameLat ?? 'lat'
6
- opts.fieldNameLng = opts.fieldNameLng ?? 'lng'
5
+ opts.fieldLat = opts.fieldLat ?? 'lat'
6
+ opts.fieldLng = opts.fieldLng ?? 'lng'
7
7
  opts.scale = opts.scale ?? 5
8
8
  opts.precision = opts.precision ?? 8
9
9
  return {
10
10
  properties: [{
11
- name: opts.fieldNameLat,
11
+ name: opts.fieldLat,
12
12
  type: 'double',
13
13
  required: opts.required ?? true,
14
14
  index: opts.required ?? true,
15
15
  precision: opts.precision,
16
16
  scale: opts.scale
17
17
  }, {
18
- name: opts.fieldNameLng,
18
+ name: opts.fieldLng,
19
19
  type: 'double',
20
20
  required: opts.required ?? true,
21
21
  index: opts.required ?? true,
@@ -24,12 +24,12 @@ async function latLng (opts = {}) {
24
24
  }],
25
25
  hook: {
26
26
  beforeCreate: async function (body) {
27
- await latLngHook.call(this, body, merge({}, opts, { lat: opts.fieldNameLat }))
28
- await latLngHook.call(this, body, merge({}, opts, { lng: opts.fieldNameLng }))
27
+ await latLngHook.call(this, body, merge({}, opts, { lat: opts.fieldLat }))
28
+ await latLngHook.call(this, body, merge({}, opts, { lng: opts.fieldLng }))
29
29
  },
30
30
  beforeUpdate: async function (body) {
31
- await latLngHook.call(this, body, merge({}, opts, { lat: opts.fieldNameLat }))
32
- await latLngHook.call(this, body, merge({}, opts, { lng: opts.fieldNameLng }))
31
+ await latLngHook.call(this, body, merge({}, opts, { lat: opts.fieldLat }))
32
+ await latLngHook.call(this, body, merge({}, opts, { lng: opts.fieldLng }))
33
33
  }
34
34
  }
35
35
  }
@@ -1,12 +1,12 @@
1
1
  import { latLngHook } from '../../../lib/util.js'
2
2
 
3
3
  async function lat (opts = {}) {
4
- opts.fieldName = opts.fieldName ?? 'lat'
4
+ opts.field = opts.field ?? 'lat'
5
5
  opts.scale = opts.scale ?? 5
6
6
  opts.precision = opts.precision ?? 8
7
7
  return {
8
8
  properties: [{
9
- name: opts.fieldName,
9
+ name: opts.field,
10
10
  type: 'double',
11
11
  required: opts.required ?? true,
12
12
  index: opts.required ?? true,
@@ -1,12 +1,12 @@
1
1
  import { latLngHook } from '../../../lib/util.js'
2
2
 
3
3
  async function lng (opts = {}) {
4
- opts.fieldName = opts.fieldName ?? 'lng'
4
+ opts.field = opts.field ?? 'lng'
5
5
  opts.scale = opts.scale ?? 5
6
6
  opts.precision = opts.precision ?? 8
7
7
  return {
8
8
  properties: [{
9
- name: opts.fieldName,
9
+ name: opts.field,
10
10
  type: 'double',
11
11
  required: opts.required ?? true,
12
12
  index: opts.required ?? true,
@@ -1,8 +1,8 @@
1
1
  async function phone (opts = {}) {
2
- opts.fieldName = opts.fieldName ?? 'phone'
2
+ opts.field = opts.field ?? 'phone'
3
3
  return {
4
4
  properties: [{
5
- name: opts.fieldName ?? 'phone',
5
+ name: opts.field ?? 'phone',
6
6
  type: 'string',
7
7
  maxLength: 50
8
8
  }]
@@ -5,9 +5,9 @@ async function siteId (opts = {}) {
5
5
  type: 'string',
6
6
  maxLength: 50,
7
7
  ref: {
8
- site: {
8
+ siteDetail: {
9
9
  model: 'SumbaSite',
10
- propName: 'id',
10
+ field: 'id',
11
11
  type: '1:1'
12
12
  }
13
13
  },
@@ -2,36 +2,36 @@ import slug from 'slug'
2
2
 
3
3
  async function autoInc (body, opts) {
4
4
  const { set, last } = this.app.lib._
5
- const query = set({}, opts.fieldName, { $regex: new RegExp('^' + body[opts.fieldName]) })
6
- const sort = set({}, opts.fieldName, -1)
5
+ const query = set({}, opts.field, { $regex: new RegExp('^' + body[opts.field]) })
6
+ const sort = set({}, opts.field, -1)
7
7
  const options = { noHook: true, skipCache: true, thrownNotFound: false }
8
8
  const resp = await this.findOneRecord({ query, sort }, options)
9
- if (resp) return body[opts.fieldName]
10
- const rslugs = resp[opts.fieldName].split('-')
11
- const slugs = body[opts.fieldName].split('-')
9
+ if (resp) return body[opts.field]
10
+ const rslugs = resp[opts.field].split('-')
11
+ const slugs = body[opts.field].split('-')
12
12
  let num
13
- if (Number(last(rslugs)) && body[opts.fieldName] === rslugs.slice(0, rslugs.length - 1).join('-')) {
13
+ if (Number(last(rslugs)) && body[opts.field] === rslugs.slice(0, rslugs.length - 1).join('-')) {
14
14
  num = Number(rslugs.pop()) + 1
15
- body[opts.fieldName] = `${rslugs.join('-')}-${num}`
15
+ body[opts.field] = `${rslugs.join('-')}-${num}`
16
16
  } else {
17
17
  const idx = slugs.length - 1
18
18
  num = Number(slugs[idx])
19
- if (!num) body[opts.fieldName] += '-1'
19
+ if (!num) body[opts.field] += '-1'
20
20
  else {
21
21
  slugs[idx] = num + 1
22
- body[opts.fieldName] = slugs.join('-')
22
+ body[opts.field] = slugs.join('-')
23
23
  }
24
24
  }
25
25
  return await autoInc.call(this, body, opts)
26
26
  }
27
27
 
28
28
  async function mainFn (opts = {}) {
29
- opts.fieldName = opts.fieldName ?? 'slug'
29
+ opts.field = opts.field ?? 'slug'
30
30
  opts.fieldSource = opts.fieldSource ?? ['name']
31
31
  opts.autoInc = true
32
32
  return {
33
33
  properties: [{
34
- name: opts.fieldName ?? 'slug',
34
+ name: opts.field ?? 'slug',
35
35
  type: 'string',
36
36
  maxLength: 255,
37
37
  index: 'unique'
@@ -40,7 +40,7 @@ async function mainFn (opts = {}) {
40
40
  beforeCreate: async function (body) {
41
41
  const { error } = this.app.bajo
42
42
  const { isEmpty, isString } = this.app.lib._
43
- if (isEmpty(body[opts.fieldName])) {
43
+ if (isEmpty(body[opts.field])) {
44
44
  if (isString(opts.fieldSource)) opts.fieldSource = [opts.fieldSource]
45
45
  const source = []
46
46
  opts.fieldSource.forEach(s => {
@@ -50,9 +50,9 @@ async function mainFn (opts = {}) {
50
50
  const details = [{ field: opts.fieldSource.join(', '), error: 'required' }]
51
51
  throw error('\'%s\' is required', opts.fieldSource.join(', '), { details })
52
52
  }
53
- body[opts.fieldName] = slug(source.join(' '))
53
+ body[opts.field] = slug(source.join(' '))
54
54
  }
55
- if (opts.autoInc) body[opts.fieldName] = await autoInc.call(this, body, opts)
55
+ if (opts.autoInc) body[opts.field] = await autoInc.call(this, body, opts)
56
56
  }
57
57
  }
58
58
  }
@@ -1,17 +1,20 @@
1
1
  async function status (opts = {}) {
2
- opts.fieldName = opts.fieldName ?? 'status'
2
+ opts.field = opts.field ?? 'status'
3
+ opts.required = opts.required ?? true
4
+ opts.values = opts.values ?? ['UNVERIFIED', 'ACTIVE', 'INACTIVE']
3
5
  return {
4
6
  properties: [{
5
- name: opts.fieldName ?? 'status',
7
+ name: opts.field ?? 'status',
6
8
  type: 'string',
7
9
  maxLength: 50,
8
10
  index: true,
9
- values: opts.values ?? ['UNVERIFIED', 'ACTIVE', 'INACTIVE']
11
+ required: opts.required,
12
+ values: opts.values
10
13
  }],
11
14
  hook: {
12
15
  beforeCreate: async function (body) {
13
16
  const { isSet } = this.app.lib.aneka
14
- if (!isSet(body[opts.fieldName])) body[opts.fieldName] = opts.default
17
+ if (!isSet(body[opts.field])) body[opts.field] = opts.default
15
18
  }
16
19
  }
17
20
  }
@@ -8,14 +8,16 @@ async function teamId (opts = {}) {
8
8
  ref: {
9
9
  site: {
10
10
  model: 'SumbaSite',
11
- propName: 'id',
11
+ field: 'id',
12
12
  type: '1:1',
13
13
  fields: ['id', 'alias', 'hostname', 'title']
14
14
  },
15
15
  team: {
16
16
  model: 'SumbaTeam',
17
- propName: 'id',
17
+ field: 'id',
18
18
  type: '1:1',
19
+ labelField: 'name',
20
+ searchField: 'name',
19
21
  fields: ['id', 'name']
20
22
  }
21
23
  },
@@ -1,8 +1,8 @@
1
1
  async function ts (opts = {}) {
2
- opts.fieldName = opts.fieldName ?? 'ts'
2
+ opts.field = opts.field ?? 'ts'
3
3
  return {
4
4
  properties: [{
5
- name: opts.fieldName ?? 'ts',
5
+ name: opts.field ?? 'ts',
6
6
  type: 'timestamp',
7
7
  required: opts.required ?? true,
8
8
  index: opts.index ?? true
@@ -1,18 +1,18 @@
1
1
  async function hook (body, options) {
2
2
  const { isSet } = this.app.lib.aneka
3
- let val = body[options.fieldName]
3
+ let val = body[options.field]
4
4
  if (!isSet(val)) return
5
5
  const [, ...params] = val.split('://')
6
6
  if (params.length === 0) val = options.defProto + '://' + val
7
- body[options.fieldName] = val
7
+ body[options.field] = val
8
8
  }
9
9
 
10
10
  async function url (opts = {}) {
11
- opts.fieldName = opts.fieldName ?? 'url'
11
+ opts.field = opts.field ?? 'url'
12
12
  opts.defProto = opts.defProto ?? 'http'
13
13
  return {
14
14
  properties: [{
15
- name: opts.fieldName ?? 'url',
15
+ name: opts.field ?? 'url',
16
16
  type: 'string'
17
17
  }],
18
18
  hook: {
@@ -7,7 +7,9 @@ async function userId (opts = {}) {
7
7
  ref: {
8
8
  user: {
9
9
  model: 'SumbaUser',
10
- propName: 'id',
10
+ field: 'id',
11
+ labelField: 'username',
12
+ searchField: 'username',
11
13
  type: '1:1'
12
14
  }
13
15
  },
@@ -1,7 +1,20 @@
1
1
  {
2
2
  "properties": [
3
3
  "subject,,255,true,true",
4
- "cat,,50,true",
4
+ {
5
+ "name": "cat",
6
+ "type": "string",
7
+ "maxLength": 50,
8
+ "index": true,
9
+ "required": true,
10
+ "ref": {
11
+ "cat": {
12
+ "model": "SumbaTicketCat",
13
+ "searchField": "name",
14
+ "labelField": "name"
15
+ }
16
+ }
17
+ },
5
18
  "message,text,,,true"
6
19
  ],
7
20
  "features": [
@@ -2,7 +2,7 @@ async function download () {
2
2
  return {
3
3
  common: {
4
4
  disabled: ['create', 'update', 'get'],
5
- formatter: {
5
+ format: {
6
6
  description: async function (val, rec) {
7
7
  const sentence = `<c:a target="_blank" href="sumba:/your-stuff/download/get/${rec.file}" content="${val}" @click.stop />`
8
8
  return await this.component.buildSentence(sentence)
@@ -1,24 +1,4 @@
1
1
  async function site (req = {}) {
2
- const isInterSite = (req.url ?? '').includes('/_is_/')
3
- let details
4
- let edit
5
- if (!isInterSite) {
6
- details = {
7
- control: {
8
- noBackBtn: true,
9
- noCloneBtn: true,
10
- editHref: 'waibuAdmin:/site/site?edit=true'
11
- }
12
- }
13
- edit = {
14
- control: {
15
- noBackBtn: true,
16
- noCloneBtn: true,
17
- detailsHref: 'waibuAdmin:/site/site'
18
- },
19
- readonly: ['id', 'createdAt', 'updatedAt']
20
- }
21
- }
22
2
  const result = {
23
3
  common: {
24
4
  attachment: true,
@@ -28,16 +8,7 @@ async function site (req = {}) {
28
8
  { name: 'personInCharge', fields: ['picName:3-md 6-sm:Name', 'picRole:3-md 6-sm:Role', 'picPhone:3-md 6-sm:Phone', 'picEmail:3-md 6-sm:Email'] },
29
9
  { name: 'address', fields: ['address1:12', 'address2:12', 'city:6-md 8-sm', 'zipCode:2-md 4-sm', 'provinceState:4-md', 'country:6-md', 'phone:6-md', 'website:12'] },
30
10
  { name: 'socialMedia', fields: ['socX:3-md 6-sm', 'socInstagram:3-md 6-sm', 'socFacebook:3-md 6-sm', 'socLinkedIn:3-md 6-sm'] }
31
- ],
32
- widget: {
33
- country: {
34
- component: 'form-select-ext'
35
- }
36
- }
37
- },
38
- view: {
39
- details,
40
- edit
11
+ ]
41
12
  }
42
13
  }
43
14
  return result
@@ -8,7 +8,7 @@ async function teamUser () {
8
8
  calcFields: [
9
9
  { name: 'team', type: 'string' }
10
10
  ],
11
- valueFormatter: {
11
+ formatValue: {
12
12
  team: (val, rec) => {
13
13
  return rec._ref.team.name
14
14
  }
@@ -5,44 +5,22 @@ async function teamUser () {
5
5
  { name: 'meta', fields: ['id', 'createdAt', 'updatedAt'] },
6
6
  { name: 'general', fields: ['userId:6-md', 'teamId:6-md'] }
7
7
  ],
8
- calcFields: [
9
- { name: 'user', type: 'string' },
10
- { name: 'team', type: 'string' }
11
- ],
12
- valueFormatter: {
13
- user: (val, rec) => {
14
- return rec._ref.user.username
15
- },
16
- team: (val, rec) => {
17
- return rec._ref.team.name
18
- }
19
- },
20
8
  widget: {
21
9
  userId: {
22
- component: 'form-select-ext',
23
10
  attr: {
24
- remoteUrl: 'sumba.restapi:/manage/user',
25
- remoteSearchField: 'username',
26
- remoteLabelField: 'username',
27
- remoteApiKey: true,
28
- ref: 'user:username'
11
+ url: 'sumba.restapi:/manage/user'
29
12
  }
30
13
  },
31
14
  teamId: {
32
- component: 'form-select-ext',
33
15
  attr: {
34
- remoteUrl: 'sumba.restapi:/manage/team',
35
- remoteSearchField: 'name',
36
- remoteLabelField: 'name',
37
- remoteApiKey: true,
38
- ref: 'team:name'
16
+ url: 'sumba.restapi:/manage/team'
39
17
  }
40
18
  }
41
19
  }
42
20
  },
43
21
  view: {
44
22
  list: {
45
- fields: ['user', 'team', 'createdAt', 'updatedAt'],
23
+ fields: ['userId', 'teamId', 'createdAt', 'updatedAt'],
46
24
  stat: {
47
25
  aggregate: [
48
26
  { fields: ['userId'], group: 'userId', aggregate: ['count'] },
@@ -0,0 +1,16 @@
1
+ {
2
+ "common": {
3
+ "widget": {
4
+ "cat": {
5
+ "attr": {
6
+ "url": "sumba.restapi:/manage/ticket-cat"
7
+ }
8
+ },
9
+ "userId": {
10
+ "attr": {
11
+ "url": "sumba.restapi:/manage/user"
12
+ }
13
+ }
14
+ }
15
+ }
16
+ }
@@ -8,7 +8,7 @@ async function teamUser ({ req } = {}) {
8
8
  calcFields: [
9
9
  { name: 'user', type: 'string' }
10
10
  ],
11
- valueFormatter: {
11
+ formatValue: {
12
12
  user: (val, rec) => {
13
13
  return rec._ref.user.name
14
14
  }
@@ -7,7 +7,7 @@ async function user ({ req } = {}) {
7
7
  { name: 'address', fields: ['address1:12', 'address2:12', 'city:6-md 8-sm', 'zipCode:2-md 4-sm', 'provinceState:4-md', 'country:6-md', 'phone:6-md', 'website:12'] },
8
8
  { name: 'socialMedia', fields: ['socX:3-md 6-sm', 'socInstagram:3-md 6-sm', 'socFacebook:3-md 6-sm', 'socLinkedIn:3-md 6-sm'] }
9
9
  ],
10
- valueFormatter: {
10
+ formatValue: {
11
11
  token: async function (val, rec) {
12
12
  const { hash } = this.app.bajoExtra
13
13
  return await hash(rec.salt)
@@ -11,7 +11,51 @@ const manageSite = {
11
11
  req.params.id = req.site.id
12
12
  req.query.id = req.site.id
13
13
  req.params.base = ''
14
- return await action.call(this, { req, reply, model, template })
14
+ const options = {
15
+ modelOpts: {
16
+ formatValue: true,
17
+ retainOriginalValue: true
18
+ },
19
+ schema: {
20
+ view: {
21
+ details: {
22
+ control: {
23
+ wdbBtnBack: {
24
+ disabled: true
25
+ },
26
+ wdbBtnClone: {
27
+ disabled: true
28
+ },
29
+ wdbBtnDelete: {
30
+ disabled: true
31
+ },
32
+ wdbBtnEdit: {
33
+ href: 'waibuAdmin:/site/site?edit=true'
34
+ }
35
+ }
36
+ },
37
+ edit: {
38
+ control: {
39
+ wdbBtnBack: {
40
+ disabled: true
41
+ },
42
+ wdbBtnClone: {
43
+ disabled: true
44
+ },
45
+ wdbBtnDelete: {
46
+ disabled: true
47
+ },
48
+ wdbBtnDetails: {
49
+ href: 'waibuAdmin:/site/site'
50
+ }
51
+ },
52
+ readonly: ['id', 'createdAt', 'updatedAt']
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ return await action.call(this, { req, reply, model, template, options })
15
59
  }
16
60
  }
17
61
 
@@ -26,7 +26,7 @@ const id = {
26
26
  schema.view.disabled = ['update', 'remove']
27
27
  schema.view.fields = ['createdAt']
28
28
  schema.view.label = { createdAt: 'conversation' }
29
- schema.view.formatter = {
29
+ schema.view.format = {
30
30
  createdAt: async function (val, rec) {
31
31
  const message = this.app.bajoMarkdown ? this.app.bajoMarkdown.parseContent(rec.message) : rec.message
32
32
  const isMe = rec.userId === req.user.id
@@ -11,7 +11,7 @@ const list = {
11
11
  schema.view.disabled = ['update', 'remove']
12
12
  schema.view.fields = ['createdAt', 'subject', 'status']
13
13
  schema.view.label = { subject: 'Your Message' }
14
- schema.view.formatter = {
14
+ schema.view.format = {
15
15
  subject: (val, rec) => {
16
16
  return `<strong>${val}</strong><br />${getExcerpt(rec.message, 35)}`
17
17
  }
@@ -0,0 +1,4 @@
1
+ {
2
+ "model": "SumbaTicketCat",
3
+ "disabled": ["create", "update", "remove"]
4
+ }
package/index.js CHANGED
@@ -209,7 +209,8 @@ async function factory (pkgName) {
209
209
  title: 'manageSite',
210
210
  children: [
211
211
  { title: 'siteProfile', href: `waibuAdmin:/${prefix}/site` },
212
- { title: 'siteSetting', href: `waibuAdmin:/${prefix}/site-setting/list` }
212
+ { title: 'siteSetting', href: `waibuAdmin:/${prefix}/site-setting/list` },
213
+ { title: 'allSites', href: `waibuAdmin:/${prefix}/all-sites/list` }
213
214
  ]
214
215
  }, {
215
216
  title: 'manageUser',
@@ -236,25 +237,13 @@ async function factory (pkgName) {
236
237
  }, {
237
238
  title: 'misc',
238
239
  children: [
239
- { title: 'manageDownload', href: `waibuAdmin:/${prefix}/download/list` }
240
- ]
241
- }, {
242
- title: 'manageAllSite',
243
- interSite: true,
244
- href: `waibuAdmin:/${prefix}/_is_/site/list`
245
- }, {
246
- title: '-',
247
- interSite: true
248
- }, {
249
- title: 'misc',
250
- interSite: true,
251
- children: [
252
- { title: 'userSession', href: `waibuAdmin:/${prefix}/_is_/session/list` }
240
+ { title: 'manageDownload', href: `waibuAdmin:/${prefix}/download/list` },
241
+ { title: 'userSession', href: `waibuAdmin:/${prefix}/session/list` }
253
242
  ]
254
243
  }]
255
244
  if (this.app.bajoCache) {
256
245
  const item = items.find(i => i.title === 'misc')
257
- if (item) item.children.push({ title: 'cacheStorage', href: `waibuAdmin:/${prefix}/_is_/cache/list` })
246
+ if (item) item.children.push({ title: 'cacheStorage', href: `waibuAdmin:/${prefix}/cache/list` })
258
247
  }
259
248
  return items
260
249
  }
package/lib/util.js CHANGED
@@ -178,8 +178,8 @@ export async function checkUserId (req, reply, source) {
178
178
  export async function latLngHook (body, options) {
179
179
  const { isSet } = this.app.lib.aneka
180
180
  const { round } = this.app.lib.aneka
181
- if (!isSet(body[options.fieldName])) return
182
- body[options.fieldName] = round(body[options.fieldName], options.scale)
181
+ if (!isSet(body[options.field])) return
182
+ body[options.field] = round(body[options.field], options.scale)
183
183
  }
184
184
 
185
185
  export async function checkinterSite (req, reply) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sumba",
3
- "version": "2.16.0",
3
+ "version": "2.18.0",
4
4
  "description": "Biz Suite for Bajo Framework",
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-11
4
+
5
+ - [2.18.0] Some major rewrites :/
6
+
7
+ ## 2026-04-07
8
+
9
+ - [2.17.0] Change all ```opts.fieldName``` to ```opts.field``` in features
10
+ - [2.17.0] Rewrite necessary changes on model reference to match the new architecture
11
+
3
12
  ## 2026-04-02
4
13
 
5
14
  - [2.16.0] Add ```SumbaUserSetting``` model and necessary handlings