@ditojs/admin 1.10.1 → 1.11.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/dist/dito-admin.es.js +1175 -1173
- package/dist/dito-admin.umd.js +4 -4
- package/dist/style.css +1 -1
- package/package.json +7 -8
- package/src/DitoAdmin.js +62 -41
- package/src/mixins/DitoMixin.js +10 -29
- package/src/mixins/ItemMixin.js +1 -1
- package/src/mixins/ResourceMixin.js +6 -6
- package/src/mixins/SourceMixin.js +1 -1
- package/src/utils/uid.js +1 -1
- package/src/utils/units.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.11.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",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"prepare": "yarn build"
|
|
26
26
|
},
|
|
27
27
|
"engines": {
|
|
28
|
-
"node": ">=
|
|
28
|
+
"node": ">= 18.0.0",
|
|
29
29
|
"yarn": ">= 1.0.0"
|
|
30
30
|
},
|
|
31
31
|
"browserslist": [
|
|
@@ -35,11 +35,10 @@
|
|
|
35
35
|
"not ie_mob > 0"
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@ditojs/ui": "^1.
|
|
39
|
-
"@ditojs/utils": "^1.
|
|
40
|
-
"axios": "^0.27.2",
|
|
38
|
+
"@ditojs/ui": "^1.11.0",
|
|
39
|
+
"@ditojs/utils": "^1.11.0",
|
|
41
40
|
"codeflask": "^1.4.1",
|
|
42
|
-
"filesize": "^
|
|
41
|
+
"filesize": "^10.0.5",
|
|
43
42
|
"filesize-parser": "^1.5.0",
|
|
44
43
|
"nanoid": "^4.0.0",
|
|
45
44
|
"tinycolor2": "^1.4.2",
|
|
@@ -59,11 +58,11 @@
|
|
|
59
58
|
"vuedraggable": "^2.24.3"
|
|
60
59
|
},
|
|
61
60
|
"devDependencies": {
|
|
62
|
-
"@ditojs/build": "^1.
|
|
61
|
+
"@ditojs/build": "^1.11.0",
|
|
63
62
|
"pug": "^3.0.2",
|
|
64
63
|
"sass": "1.55.0",
|
|
65
64
|
"vite": "^3.2.2",
|
|
66
65
|
"vite-plugin-vue2": "^2.0.2"
|
|
67
66
|
},
|
|
68
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "cc2a838ccf15a75f435844f3087698c4efaf44e4"
|
|
69
68
|
}
|
package/src/DitoAdmin.js
CHANGED
|
@@ -2,7 +2,6 @@ import Vue from 'vue'
|
|
|
2
2
|
import VueModal from 'vue-js-modal'
|
|
3
3
|
import VueRouter from 'vue-router'
|
|
4
4
|
import VueNotifications from 'vue-notification'
|
|
5
|
-
import axios from 'axios'
|
|
6
5
|
import {
|
|
7
6
|
isString, isAbsoluteUrl, merge, hyphenate, camelize, defaultFormats
|
|
8
7
|
} from '@ditojs/utils'
|
|
@@ -11,6 +10,7 @@ import * as types from './types/index.js'
|
|
|
11
10
|
import DitoRoot from './components/DitoRoot.vue'
|
|
12
11
|
import TypeComponent from './TypeComponent.js'
|
|
13
12
|
import { getResource } from './utils/resource.js'
|
|
13
|
+
import { deprecate } from './utils/deprecate.js'
|
|
14
14
|
import verbs from './verbs.js'
|
|
15
15
|
|
|
16
16
|
Vue.config.productionTip = false
|
|
@@ -37,25 +37,14 @@ export default class DitoAdmin {
|
|
|
37
37
|
|
|
38
38
|
// Setup default api setttings:
|
|
39
39
|
api.locale ||= 'en-US'
|
|
40
|
-
|
|
41
40
|
api.formats = merge({}, defaultFormats, api.formats)
|
|
42
|
-
|
|
43
|
-
api.
|
|
44
|
-
|
|
41
|
+
api.request ||= options => request(api, options)
|
|
42
|
+
api.getApiUrl ||= path => getApiUrl(api, path)
|
|
43
|
+
api.isApiRequest ||= url => isApiRequest(api, url)
|
|
45
44
|
// Setting `api.normalizePaths = true (plural) sets both:
|
|
46
45
|
// `api.normalizePath = hyphenate` and `api.denormalizePath = camelize`
|
|
47
|
-
api.normalizePath
|
|
48
|
-
|
|
49
|
-
api.normalizePaths
|
|
50
|
-
? hyphenate
|
|
51
|
-
: val => val
|
|
52
|
-
)
|
|
53
|
-
api.denormalizePath = (
|
|
54
|
-
api.denormalizePath ||
|
|
55
|
-
api.normalizePaths
|
|
56
|
-
? camelize
|
|
57
|
-
: val => val
|
|
58
|
-
)
|
|
46
|
+
api.normalizePath ||= api.normalizePaths ? hyphenate : val => val
|
|
47
|
+
api.denormalizePath ||= api.normalizePaths ? camelize : val => val
|
|
59
48
|
|
|
60
49
|
// Allow the configuration of all auth resources, like so:
|
|
61
50
|
// api.users = {
|
|
@@ -140,10 +129,6 @@ export default class DitoAdmin {
|
|
|
140
129
|
...api.headers
|
|
141
130
|
}
|
|
142
131
|
|
|
143
|
-
api.isApiRequest = api.isApiRequest || function(url) {
|
|
144
|
-
return !isAbsoluteUrl(url) || url.startsWith(api.url)
|
|
145
|
-
}
|
|
146
|
-
|
|
147
132
|
if (isString(el)) {
|
|
148
133
|
el = document.querySelector(el)
|
|
149
134
|
}
|
|
@@ -202,26 +187,62 @@ export default class DitoAdmin {
|
|
|
202
187
|
register(type, options) {
|
|
203
188
|
return TypeComponent.register(type, options)
|
|
204
189
|
}
|
|
190
|
+
}
|
|
205
191
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
})
|
|
192
|
+
class RequestError extends Error {
|
|
193
|
+
constructor(response) {
|
|
194
|
+
super(`Request failed with status code: ${response.status} (${response.statusText})`)
|
|
195
|
+
this.response = response
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async function request(api, {
|
|
200
|
+
url,
|
|
201
|
+
method = 'get',
|
|
202
|
+
// TODO: `params` was deprecated in favor of `query` on 2022-11-01, remove
|
|
203
|
+
// once not in use anywhere anymore.
|
|
204
|
+
params = null,
|
|
205
|
+
query = params || null,
|
|
206
|
+
headers = null,
|
|
207
|
+
data = null
|
|
208
|
+
}) {
|
|
209
|
+
if (params) {
|
|
210
|
+
deprecate(`request.params is deprecated. Use action.method and action.path instead.`)
|
|
226
211
|
}
|
|
212
|
+
|
|
213
|
+
const isApiRequest = api.isApiRequest(url)
|
|
214
|
+
if (isApiRequest && !isAbsoluteUrl(url)) {
|
|
215
|
+
url = api.getApiUrl(url)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const search = query && new URLSearchParams(query).toString()
|
|
219
|
+
if (search) {
|
|
220
|
+
url = `${url}?${search}`
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const response = await fetch(url, {
|
|
224
|
+
method: method.toUpperCase(),
|
|
225
|
+
...(data && { body: JSON.stringify(data) }),
|
|
226
|
+
headers: {
|
|
227
|
+
...(isApiRequest && api.headers),
|
|
228
|
+
...headers
|
|
229
|
+
},
|
|
230
|
+
credentials: isApiRequest && api.cors?.credentials
|
|
231
|
+
? 'include'
|
|
232
|
+
: 'same-origin'
|
|
233
|
+
})
|
|
234
|
+
response.data = await response.json()
|
|
235
|
+
if (!response.ok) {
|
|
236
|
+
throw new RequestError(response)
|
|
237
|
+
}
|
|
238
|
+
return response
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function getApiUrl(api, path) {
|
|
242
|
+
// Use same approach as axios `combineURLs()` to join baseURL with path:
|
|
243
|
+
return `${api.url.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function isApiRequest(api, url) {
|
|
247
|
+
return !isAbsoluteUrl(url) || url.startsWith(api.url)
|
|
227
248
|
}
|
package/src/mixins/DitoMixin.js
CHANGED
|
@@ -8,7 +8,6 @@ import DitoContext from '../DitoContext.js'
|
|
|
8
8
|
import EmitterMixin from './EmitterMixin.js'
|
|
9
9
|
import { isMatchingType, convertType } from '../utils/type.js'
|
|
10
10
|
import { getResource, getMemberResource } from '../utils/resource.js'
|
|
11
|
-
import { deprecate } from '../utils/deprecate.js'
|
|
12
11
|
|
|
13
12
|
// @vue/component
|
|
14
13
|
export default {
|
|
@@ -294,35 +293,22 @@ export default {
|
|
|
294
293
|
|
|
295
294
|
getResourceUrl(resource) {
|
|
296
295
|
const path = this.getResourcePath(resource)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
path.replace(/^\/+/, '')
|
|
304
|
-
}`
|
|
305
|
-
// Support optional query parameters, which are added to the URL:
|
|
306
|
-
const { query } = resource
|
|
307
|
-
if (query) {
|
|
308
|
-
const params = Object.entries(query).map(
|
|
309
|
-
([key, value]) =>
|
|
310
|
-
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`
|
|
311
|
-
)
|
|
312
|
-
url = `${url}?${params.join('&')}`
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
return url
|
|
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
|
|
316
302
|
},
|
|
317
303
|
|
|
318
|
-
async sendRequest({ method, url, resource,
|
|
319
|
-
url
|
|
320
|
-
method
|
|
304
|
+
async sendRequest({ method, url, resource, query, data, internal }) {
|
|
305
|
+
url ||= this.getResourcePath(resource)
|
|
306
|
+
method ||= resource?.method
|
|
321
307
|
const checkUser = !internal && this.api.isApiRequest(url)
|
|
322
308
|
if (checkUser) {
|
|
323
309
|
await this.rootComponent.ensureUser()
|
|
324
310
|
}
|
|
325
|
-
const response = await this.api.request({ method, url, data,
|
|
311
|
+
const response = await this.api.request({ method, url, data, query })
|
|
326
312
|
// Detect change of the own user, and fetch it again if it was changed.
|
|
327
313
|
if (
|
|
328
314
|
checkUser &&
|
|
@@ -371,11 +357,6 @@ export default {
|
|
|
371
357
|
return res
|
|
372
358
|
},
|
|
373
359
|
|
|
374
|
-
load(options) {
|
|
375
|
-
deprecate('load() is deprecated. Use request() instead.')
|
|
376
|
-
return this.request(options)
|
|
377
|
-
},
|
|
378
|
-
|
|
379
360
|
format(value, {
|
|
380
361
|
locale = this.api.locale,
|
|
381
362
|
defaults = this.api.formats,
|
package/src/mixins/ItemMixin.js
CHANGED
|
@@ -102,7 +102,7 @@ export default {
|
|
|
102
102
|
text = item[key]
|
|
103
103
|
}
|
|
104
104
|
const hadLabel = !!text
|
|
105
|
-
text
|
|
105
|
+
text ||= ''
|
|
106
106
|
// If no label was found so far, try to produce one from theindex.
|
|
107
107
|
if (!text) {
|
|
108
108
|
// Always use extended style when auto-generating labels from index/id:
|
|
@@ -193,8 +193,8 @@ export default {
|
|
|
193
193
|
},
|
|
194
194
|
|
|
195
195
|
requestData() {
|
|
196
|
-
const
|
|
197
|
-
this.handleRequest({ method: 'get',
|
|
196
|
+
const query = this.queryParams
|
|
197
|
+
this.handleRequest({ method: 'get', query }, (err, response) => {
|
|
198
198
|
if (err) {
|
|
199
199
|
if (response) {
|
|
200
200
|
const { data } = response
|
|
@@ -226,15 +226,15 @@ export default {
|
|
|
226
226
|
async handleRequest({
|
|
227
227
|
method,
|
|
228
228
|
resource = this.resource,
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
query,
|
|
230
|
+
data
|
|
231
231
|
}, callback) {
|
|
232
232
|
const loadingOptions = {
|
|
233
233
|
updateRoot: true, // Display spinner in header when loading in resources
|
|
234
234
|
updateView: this.isInView // Notify view of loading for view components
|
|
235
235
|
}
|
|
236
236
|
this.setLoading(true, loadingOptions)
|
|
237
|
-
const request = { method, resource, data,
|
|
237
|
+
const request = { method, resource, data, query }
|
|
238
238
|
try {
|
|
239
239
|
const response = await this.sendRequest(request)
|
|
240
240
|
// Pass both request and response to the callback, so they can be
|
|
@@ -307,7 +307,7 @@ export default {
|
|
|
307
307
|
} = {}) {
|
|
308
308
|
return new Promise(resolve => {
|
|
309
309
|
this.handleRequest(
|
|
310
|
-
{ method,
|
|
310
|
+
{ method, resource, data },
|
|
311
311
|
async (err, response) => {
|
|
312
312
|
const data = response?.data
|
|
313
313
|
if (err) {
|
package/src/utils/uid.js
CHANGED
package/src/utils/units.js
CHANGED