@ditojs/admin 1.11.0 → 1.13.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/admin",
3
- "version": "1.11.0",
3
+ "version": "1.13.0",
4
4
  "type": "module",
5
5
  "description": "Dito.js Admin is a schema based admin interface for Dito.js Server, featuring auto-generated views and forms and built with Vue.js",
6
6
  "repository": "https://github.com/ditojs/dito/tree/master/packages/admin",
@@ -17,12 +17,14 @@
17
17
  },
18
18
  "files": [
19
19
  "src/",
20
- "dist/"
20
+ "dist/",
21
+ "types/"
21
22
  ],
22
23
  "scripts": {
23
24
  "build": "vite build",
24
25
  "watch": "yarn build --mode 'development' --watch",
25
- "prepare": "yarn build"
26
+ "prepare": "yarn build",
27
+ "types": "tsc --noEmit types/index.d.ts"
26
28
  },
27
29
  "engines": {
28
30
  "node": ">= 18.0.0",
@@ -35,8 +37,8 @@
35
37
  "not ie_mob > 0"
36
38
  ],
37
39
  "dependencies": {
38
- "@ditojs/ui": "^1.11.0",
39
- "@ditojs/utils": "^1.11.0",
40
+ "@ditojs/ui": "^1.13.0",
41
+ "@ditojs/utils": "^1.13.0",
40
42
  "codeflask": "^1.4.1",
41
43
  "filesize": "^10.0.5",
42
44
  "filesize-parser": "^1.5.0",
@@ -58,11 +60,14 @@
58
60
  "vuedraggable": "^2.24.3"
59
61
  },
60
62
  "devDependencies": {
61
- "@ditojs/build": "^1.11.0",
63
+ "@ditojs/build": "^1.13.0",
62
64
  "pug": "^3.0.2",
63
65
  "sass": "1.55.0",
66
+ "type-fest": "^3.1.0",
67
+ "typescript": "^4.8.4",
64
68
  "vite": "^3.2.2",
65
69
  "vite-plugin-vue2": "^2.0.2"
66
70
  },
67
- "gitHead": "cc2a838ccf15a75f435844f3087698c4efaf44e4"
71
+ "types": "types",
72
+ "gitHead": "b65d7d15871b0d11579565df92780536ef2926da"
68
73
  }
package/src/DitoAdmin.js CHANGED
@@ -39,8 +39,8 @@ export default class DitoAdmin {
39
39
  api.locale ||= 'en-US'
40
40
  api.formats = merge({}, defaultFormats, api.formats)
41
41
  api.request ||= options => request(api, options)
42
- api.getApiUrl ||= path => getApiUrl(api, path)
43
- api.isApiRequest ||= url => isApiRequest(api, url)
42
+ api.getApiUrl ||= options => getApiUrl(api, options)
43
+ api.isApiUrl ||= url => isApiUrl(api, url)
44
44
  // Setting `api.normalizePaths = true (plural) sets both:
45
45
  // `api.normalizePath = hyphenate` and `api.denormalizePath = camelize`
46
46
  api.normalizePath ||= api.normalizePaths ? hyphenate : val => val
@@ -199,8 +199,8 @@ class RequestError extends Error {
199
199
  async function request(api, {
200
200
  url,
201
201
  method = 'get',
202
- // TODO: `params` was deprecated in favor of `query` on 2022-11-01, remove
203
- // once not in use anywhere anymore.
202
+ // TODO: `request.params` was deprecated in favor of `query` on 2022-11-01,
203
+ // remove once not in use anywhere anymore.
204
204
  params = null,
205
205
  query = params || null,
206
206
  headers = null,
@@ -210,39 +210,40 @@ async function request(api, {
210
210
  deprecate(`request.params is deprecated. Use action.method and action.path instead.`)
211
211
  }
212
212
 
213
- const isApiRequest = api.isApiRequest(url)
214
- if (isApiRequest && !isAbsoluteUrl(url)) {
215
- url = api.getApiUrl(url)
216
- }
213
+ const isApiUrl = api.isApiUrl(url)
217
214
 
218
- const search = query && new URLSearchParams(query).toString()
219
- if (search) {
220
- url = `${url}?${search}`
221
- }
222
-
223
- const response = await fetch(url, {
215
+ const response = await fetch(api.getApiUrl({ url, query }), {
224
216
  method: method.toUpperCase(),
225
217
  ...(data && { body: JSON.stringify(data) }),
226
218
  headers: {
227
- ...(isApiRequest && api.headers),
219
+ ...(isApiUrl && api.headers),
228
220
  ...headers
229
221
  },
230
- credentials: isApiRequest && api.cors?.credentials
222
+ credentials: isApiUrl && api.cors?.credentials
231
223
  ? 'include'
232
224
  : 'same-origin'
233
225
  })
234
- response.data = await response.json()
226
+
227
+ if (response.headers.get('Content-Type')?.includes('application/json')) {
228
+ response.data = await response.json()
229
+ }
230
+
235
231
  if (!response.ok) {
236
232
  throw new RequestError(response)
237
233
  }
238
234
  return response
239
235
  }
240
236
 
241
- function getApiUrl(api, path) {
242
- // Use same approach as axios `combineURLs()` to join baseURL with path:
243
- return `${api.url.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`
237
+ function getApiUrl(api, { url, query }) {
238
+ if (!isAbsoluteUrl(url)) {
239
+ // Use same approach as axios `combineURLs()` to join baseURL with path:
240
+ url = `${api.url.replace(/\/+$/, '')}/${url.replace(/^\/+/, '')}`
241
+ }
242
+ // Support optional query parameters, to be are added to the URL.
243
+ const search = query && new URLSearchParams(query).toString()
244
+ return search ? `${url}?${search}` : url
244
245
  }
245
246
 
246
- function isApiRequest(api, url) {
247
+ function isApiUrl(api, url) {
247
248
  return !isAbsoluteUrl(url) || url.startsWith(api.url)
248
249
  }
@@ -292,19 +292,14 @@ export default {
292
292
  },
293
293
 
294
294
  getResourceUrl(resource) {
295
- const path = this.getResourcePath(resource)
296
- if (!path) return null
297
- const url = this.api.getApiUrl(path)
298
- // Support optional query parameters, to be are added to the URL.
299
- const { query } = resource
300
- const search = query && new URLSearchParams(query).toString()
301
- return search ? `${url}?${search}` : url
295
+ const url = this.getResourcePath(resource)
296
+ return url ? this.api.getApiUrl({ url, query: resource.query }) : null
302
297
  },
303
298
 
304
299
  async sendRequest({ method, url, resource, query, data, internal }) {
305
300
  url ||= this.getResourcePath(resource)
306
301
  method ||= resource?.method
307
- const checkUser = !internal && this.api.isApiRequest(url)
302
+ const checkUser = !internal && this.api.isApiUrl(url)
308
303
  if (checkUser) {
309
304
  await this.rootComponent.ensureUser()
310
305
  }
@@ -334,7 +329,9 @@ export default {
334
329
  const cacheKey = loadCache && `${
335
330
  options.method || 'get'} ${
336
331
  options.url} ${
337
- JSON.stringify(options.params || '')} ${
332
+ // TODO: `request.params` was deprecated in favor of `query` on
333
+ // 2022-11-01, remove once not in use anywhere anymore.
334
+ JSON.stringify(options.query || options.params || '')} ${
338
335
  JSON.stringify(options.data || '')
339
336
  }`
340
337
  if (loadCache && (cacheKey in loadCache)) {
@@ -383,13 +380,10 @@ export default {
383
380
  if (isString(options)) {
384
381
  options = { url: options }
385
382
  }
386
- const { url, filename } = options
387
383
  // See: https://stackoverflow.com/a/49917066/1163708
388
384
  const a = document.createElement('a')
389
- a.href = url
390
- if (filename) {
391
- a.download = filename
392
- }
385
+ a.href = this.api.getApiUrl(options)
386
+ a.download = options.filename ?? null
393
387
  const { body } = document
394
388
  body.appendChild(a)
395
389
  a.click()
@@ -135,11 +135,13 @@ export default TypeComponent.register('color', {
135
135
  default: 'hex'
136
136
  }),
137
137
 
138
+ // TODO: Rename to `showAlpha`?
138
139
  alpha: getSchemaAccessor('alpha', {
139
140
  type: Boolean,
140
141
  default: false
141
142
  }),
142
143
 
144
+ // TODO: Rename to `showInputs`?
143
145
  inputs: getSchemaAccessor('inputs', {
144
146
  type: Boolean,
145
147
  default: true
@@ -293,8 +293,8 @@ export default TypeComponent.register('multiselect', {
293
293
  placeholder() {
294
294
  const { placeholder, searchable, taggable } = this.schema
295
295
  return placeholder || (
296
- searchable && taggable ? 'Search or add a tag'
297
- : searchable ? 'Select or search entry'
296
+ searchable && taggable ? `Search or add a ${this.label}`
297
+ : searchable ? `Select or search ${this.label}`
298
298
  : undefined
299
299
  )
300
300
  }
@@ -50,6 +50,7 @@ export default TypeComponent.register('slider', {
50
50
  nativeField: true,
51
51
 
52
52
  computed: {
53
+ // TODO: Rename to `showInput`?
53
54
  input: getSchemaAccessor('input', {
54
55
  type: Boolean,
55
56
  default: true