@ditojs/admin 1.13.0 → 1.14.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 +27 -11
- package/dist/dito-admin.umd.js +4 -4
- package/package.json +12 -12
- package/src/DitoAdmin.js +33 -6
- package/src/components/DitoForm.vue +1 -2
- package/src/utils/schema.js +1 -1
- package/types/index.d.ts +88 -76
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ditojs/admin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.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",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"not ie_mob > 0"
|
|
38
38
|
],
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@ditojs/ui": "^1.
|
|
41
|
-
"@ditojs/utils": "^1.
|
|
40
|
+
"@ditojs/ui": "^1.14.0",
|
|
41
|
+
"@ditojs/utils": "^1.14.0",
|
|
42
42
|
"codeflask": "^1.4.1",
|
|
43
43
|
"filesize": "^10.0.5",
|
|
44
44
|
"filesize-parser": "^1.5.0",
|
|
@@ -48,26 +48,26 @@
|
|
|
48
48
|
"tiptap-commands": "^1.17.1",
|
|
49
49
|
"tiptap-extensions": "^1.35.2",
|
|
50
50
|
"to-pascal-case": "^1.0.0",
|
|
51
|
-
"vue": "^2.7.
|
|
51
|
+
"vue": "^2.7.14",
|
|
52
52
|
"vue-color": "^2.8.1",
|
|
53
53
|
"vue-js-modal": "^2.0.1",
|
|
54
54
|
"vue-multiselect": "^2.1.6",
|
|
55
55
|
"vue-notification": "^1.3.20",
|
|
56
56
|
"vue-router": "^3.6.5",
|
|
57
57
|
"vue-spinner": "^1.0.4",
|
|
58
|
-
"vue-template-compiler": "^2.7.
|
|
59
|
-
"vue-upload-component": "^2.8.
|
|
58
|
+
"vue-template-compiler": "^2.7.14",
|
|
59
|
+
"vue-upload-component": "^2.8.23",
|
|
60
60
|
"vuedraggable": "^2.24.3"
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@ditojs/build": "^1.
|
|
63
|
+
"@ditojs/build": "^1.14.0",
|
|
64
64
|
"pug": "^3.0.2",
|
|
65
|
-
"sass": "1.
|
|
66
|
-
"type-fest": "^3.
|
|
67
|
-
"typescript": "^4.
|
|
68
|
-
"vite": "^3.2.
|
|
65
|
+
"sass": "1.56.1",
|
|
66
|
+
"type-fest": "^3.2.0",
|
|
67
|
+
"typescript": "^4.9.3",
|
|
68
|
+
"vite": "^3.2.4",
|
|
69
69
|
"vite-plugin-vue2": "^2.0.2"
|
|
70
70
|
},
|
|
71
71
|
"types": "types",
|
|
72
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "ba197ae5254deb657b2c3b5dab7a851f488e022a"
|
|
73
73
|
}
|
package/src/DitoAdmin.js
CHANGED
|
@@ -3,7 +3,9 @@ import VueModal from 'vue-js-modal'
|
|
|
3
3
|
import VueRouter from 'vue-router'
|
|
4
4
|
import VueNotifications from 'vue-notification'
|
|
5
5
|
import {
|
|
6
|
-
isString,
|
|
6
|
+
isString, isArray, asArray, isAbsoluteUrl,
|
|
7
|
+
merge, hyphenate, camelize,
|
|
8
|
+
defaultFormats
|
|
7
9
|
} from '@ditojs/utils'
|
|
8
10
|
import * as components from './components/index.js'
|
|
9
11
|
import * as types from './types/index.js'
|
|
@@ -234,16 +236,41 @@ async function request(api, {
|
|
|
234
236
|
return response
|
|
235
237
|
}
|
|
236
238
|
|
|
239
|
+
function isApiUrl(api, url) {
|
|
240
|
+
return !isAbsoluteUrl(url) || url.startsWith(api.url)
|
|
241
|
+
}
|
|
242
|
+
|
|
237
243
|
function getApiUrl(api, { url, query }) {
|
|
238
244
|
if (!isAbsoluteUrl(url)) {
|
|
239
|
-
|
|
240
|
-
url = `${api.url.replace(/\/+$/, '')}/${url.replace(/^\/+/, '')}`
|
|
245
|
+
url = combineUrls(api.url, url)
|
|
241
246
|
}
|
|
242
247
|
// Support optional query parameters, to be are added to the URL.
|
|
243
|
-
const search =
|
|
248
|
+
const search = formatQuery(query)
|
|
244
249
|
return search ? `${url}?${search}` : url
|
|
245
250
|
}
|
|
246
251
|
|
|
247
|
-
function
|
|
248
|
-
|
|
252
|
+
function combineUrls(baseUrl, relativeUrl) {
|
|
253
|
+
// Use same approach as axios `combineURLs()` to join baseUrl & relativeUrl:
|
|
254
|
+
return `${baseUrl.replace(/\/+$/, '')}/${relativeUrl.replace(/^\/+/, '')}`
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function formatQuery(query) {
|
|
258
|
+
const entries = query
|
|
259
|
+
? isArray(query)
|
|
260
|
+
? query
|
|
261
|
+
: Object.entries(query)
|
|
262
|
+
: []
|
|
263
|
+
return new URLSearchParams(
|
|
264
|
+
// Expand array values into multiple entries under the same key, so
|
|
265
|
+
// `formatQuery({ foo: [1, 2], bar: 3 })` => 'foo=1&foo=2&bar=3'.
|
|
266
|
+
entries.reduce(
|
|
267
|
+
(entries, [key, value]) => {
|
|
268
|
+
for (const val of asArray(value)) {
|
|
269
|
+
entries.push([key, val])
|
|
270
|
+
}
|
|
271
|
+
return entries
|
|
272
|
+
},
|
|
273
|
+
[]
|
|
274
|
+
)
|
|
275
|
+
).toString()
|
|
249
276
|
}
|
|
@@ -288,8 +288,7 @@ export default DitoComponent.component('dito-form', {
|
|
|
288
288
|
// @override ResourceMixin.setupData()
|
|
289
289
|
setupData() {
|
|
290
290
|
if (this.isCreating) {
|
|
291
|
-
this.createdData
|
|
292
|
-
this.createData(this.schema, this.type)
|
|
291
|
+
this.createdData ||= this.createData(this.schema, this.type)
|
|
293
292
|
} else {
|
|
294
293
|
this.ensureData()
|
|
295
294
|
}
|
package/src/utils/schema.js
CHANGED
|
@@ -163,7 +163,7 @@ export function processComponent(api, schema, name, routes, level) {
|
|
|
163
163
|
export function processRouteSchema(api, schema, name) {
|
|
164
164
|
// Used for view and source schemas, see SourceMixin
|
|
165
165
|
schema.name = name
|
|
166
|
-
schema.path
|
|
166
|
+
schema.path ||= api.normalizePath(name)
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
export async function processSchemaComponents(api, schema, routes, level) {
|
package/types/index.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
NumberFormat,
|
|
8
8
|
TimeFormat
|
|
9
9
|
} from '@ditojs/utils'
|
|
10
|
-
import { AxiosResponse as Response } from 'axios'
|
|
11
10
|
import { RequireAtLeastOne, SetOptional } from 'type-fest'
|
|
12
11
|
import Vue, { VueConstructor } from 'vue'
|
|
13
12
|
|
|
@@ -21,7 +20,7 @@ export interface DitoGlobal {
|
|
|
21
20
|
base?: string
|
|
22
21
|
settings?: Record<string, any>
|
|
23
22
|
}
|
|
24
|
-
export type
|
|
23
|
+
export type RequestMethod = <T>({
|
|
25
24
|
url,
|
|
26
25
|
method,
|
|
27
26
|
data,
|
|
@@ -39,7 +38,9 @@ export type PerformRequest = <T>({
|
|
|
39
38
|
params: ConstructorParameters<typeof URLSearchParams>[0]
|
|
40
39
|
query: ConstructorParameters<typeof URLSearchParams>[0]
|
|
41
40
|
headers: Record<string, string>
|
|
42
|
-
}) => Promise<
|
|
41
|
+
}) => Promise<RequestMethodResponse<T>>
|
|
42
|
+
|
|
43
|
+
export type RequestMethodResponse<T> = Response & { data: T }
|
|
43
44
|
|
|
44
45
|
export interface ApiResource {
|
|
45
46
|
type: string
|
|
@@ -61,7 +62,7 @@ export interface ApiConfig {
|
|
|
61
62
|
date?: DateFormat
|
|
62
63
|
time?: TimeFormat
|
|
63
64
|
}
|
|
64
|
-
request?:
|
|
65
|
+
request?: RequestMethod
|
|
65
66
|
/**
|
|
66
67
|
* Whether to display admin notifications.
|
|
67
68
|
*
|
|
@@ -74,7 +75,7 @@ export interface ApiConfig {
|
|
|
74
75
|
* The amount of milliseconds multiplied with the amount of characters
|
|
75
76
|
* displayed in the notification, plus 40 (40 + title + message).
|
|
76
77
|
* @defaultValue `20`
|
|
77
|
-
|
|
78
|
+
*/
|
|
78
79
|
durationFactor: number
|
|
79
80
|
}
|
|
80
81
|
cors?: {
|
|
@@ -214,7 +215,11 @@ export interface SchemaTypeMixin<$Item> {
|
|
|
214
215
|
* depend on its contents or as 'fill' to fill left over space. A line will
|
|
215
216
|
* contain multiple components until their widths exceed 100%.
|
|
216
217
|
*/
|
|
217
|
-
width?: OrItemAccessor
|
|
218
|
+
width?: OrItemAccessor<
|
|
219
|
+
$Item,
|
|
220
|
+
{},
|
|
221
|
+
'auto' | 'fill' | `${number}%` | `${number}/${number}` | number
|
|
222
|
+
>
|
|
218
223
|
|
|
219
224
|
/**
|
|
220
225
|
* Whether the component is visible.
|
|
@@ -879,76 +884,83 @@ export type ColumnSchema<$Item = any> = {
|
|
|
879
884
|
|
|
880
885
|
export type ResolvableForm<$Item = any> = Resolvable<Form<$Item>>
|
|
881
886
|
|
|
882
|
-
export type ListSchema<$Item = { [key: string]: any }> =
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
| {
|
|
920
|
-
label?: string
|
|
921
|
-
hint?: string
|
|
922
|
-
defaultScope?: boolean
|
|
923
|
-
}
|
|
924
|
-
| string
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
* Default scope name as defined on the model.
|
|
928
|
-
*/
|
|
929
|
-
scope?: string
|
|
930
|
-
|
|
931
|
-
// TODO: document filters
|
|
932
|
-
filters?: {
|
|
933
|
-
[k: string]:
|
|
934
|
-
| {
|
|
935
|
-
label?: string
|
|
936
|
-
filter: 'text'
|
|
937
|
-
/**
|
|
938
|
-
* @defaultValue `['contains']`
|
|
939
|
-
*/
|
|
940
|
-
operators?: ('contains' | 'equals' | 'starts-with' | 'ends-with')[]
|
|
941
|
-
}
|
|
942
|
-
| {
|
|
943
|
-
label?: string
|
|
944
|
-
filter: 'date-range'
|
|
945
|
-
}
|
|
887
|
+
export type ListSchema<$Item = { [key: string]: any }> =
|
|
888
|
+
SchemaSourceMixin<$Item> &
|
|
889
|
+
BaseSchema<$Item> & {
|
|
890
|
+
/**
|
|
891
|
+
* The type of the view
|
|
892
|
+
*/
|
|
893
|
+
type: 'list'
|
|
894
|
+
/**
|
|
895
|
+
* The form.
|
|
896
|
+
*/
|
|
897
|
+
form?: ResolvableForm
|
|
898
|
+
/**
|
|
899
|
+
* The forms.
|
|
900
|
+
*/
|
|
901
|
+
forms?: {
|
|
902
|
+
[key: string]: ResolvableForm
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* The label given to the items. If no itemLabel is given, the default is
|
|
906
|
+
* the 'name' property of the item, followed by label of the form of the
|
|
907
|
+
* view (plus item id) and other defaults.
|
|
908
|
+
*/
|
|
909
|
+
itemLabel?: OrItemAccessor<any, {}, string>
|
|
910
|
+
/**
|
|
911
|
+
* The columns displayed in the table. While columns can be supplied as an
|
|
912
|
+
* array where each entry is the name of a property of the item, it is
|
|
913
|
+
* usually beneficial to assign an object with further options to the
|
|
914
|
+
* columns property.
|
|
915
|
+
*/
|
|
916
|
+
columns?: Record<string, ColumnSchema<$Item>> | (keyof $Item)[]
|
|
917
|
+
/**
|
|
918
|
+
* Scope names as defined on the model. When set, the admin renders a set
|
|
919
|
+
* of scope buttons, allowing the user to switch between them while
|
|
920
|
+
* editing.
|
|
921
|
+
*/
|
|
922
|
+
scopes?:
|
|
923
|
+
| string[]
|
|
946
924
|
| {
|
|
947
|
-
|
|
948
|
-
|
|
925
|
+
[scopeName: string]:
|
|
926
|
+
| {
|
|
927
|
+
label?: string
|
|
928
|
+
hint?: string
|
|
929
|
+
defaultScope?: boolean
|
|
930
|
+
}
|
|
931
|
+
| string
|
|
949
932
|
}
|
|
933
|
+
/**
|
|
934
|
+
* Default scope name as defined on the model.
|
|
935
|
+
*/
|
|
936
|
+
scope?: string
|
|
937
|
+
|
|
938
|
+
// TODO: document filters
|
|
939
|
+
filters?: {
|
|
940
|
+
[k: string]:
|
|
941
|
+
| {
|
|
942
|
+
label?: string
|
|
943
|
+
filter: 'text'
|
|
944
|
+
/**
|
|
945
|
+
* @defaultValue `['contains']`
|
|
946
|
+
*/
|
|
947
|
+
operators?: (
|
|
948
|
+
| 'contains'
|
|
949
|
+
| 'equals'
|
|
950
|
+
| 'starts-with'
|
|
951
|
+
| 'ends-with'
|
|
952
|
+
)[]
|
|
953
|
+
}
|
|
954
|
+
| {
|
|
955
|
+
label?: string
|
|
956
|
+
filter: 'date-range'
|
|
957
|
+
}
|
|
958
|
+
| {
|
|
959
|
+
label?: string
|
|
960
|
+
components: Components<any>
|
|
961
|
+
}
|
|
962
|
+
}
|
|
950
963
|
}
|
|
951
|
-
}
|
|
952
964
|
|
|
953
965
|
export type OrItemAccessor<
|
|
954
966
|
$Item = any,
|
|
@@ -1013,7 +1025,7 @@ export type DitoContext<$Item = any> = {
|
|
|
1013
1025
|
|
|
1014
1026
|
// Helper Methods
|
|
1015
1027
|
|
|
1016
|
-
request<T
|
|
1028
|
+
request<T>(options: {
|
|
1017
1029
|
/**
|
|
1018
1030
|
* Allows caching of loaded data on two levels:
|
|
1019
1031
|
* - 'global': cache globally, for the entire admin session
|
|
@@ -1044,7 +1056,7 @@ export type DitoContext<$Item = any> = {
|
|
|
1044
1056
|
}
|
|
1045
1057
|
|
|
1046
1058
|
export type View<$Item = any> = {
|
|
1047
|
-
resource?: Form['resource']
|
|
1059
|
+
resource?: Form['resource']
|
|
1048
1060
|
clipboard?: Form['clipboard']
|
|
1049
1061
|
} & (
|
|
1050
1062
|
| InputSchema<$Item>
|
|
@@ -1167,7 +1179,7 @@ export class DitoAdmin<
|
|
|
1167
1179
|
|
|
1168
1180
|
// TODO: options and return type
|
|
1169
1181
|
register(type: OrArrayOf<string>, options: any): any
|
|
1170
|
-
request:
|
|
1182
|
+
request: RequestMethod
|
|
1171
1183
|
}
|
|
1172
1184
|
export type HTTPVerb = 'get' | 'post' | 'put' | 'delete' | 'patch'
|
|
1173
1185
|
|