@ditojs/admin 1.21.0 → 1.23.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.21.0",
3
+ "version": "1.23.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",
@@ -22,12 +22,6 @@
22
22
  "dist/",
23
23
  "types/"
24
24
  ],
25
- "scripts": {
26
- "build": "vite build",
27
- "watch": "yarn build --mode 'development' --watch",
28
- "prepare": "yarn build",
29
- "types": "tsc --noEmit types/index.d.ts"
30
- },
31
25
  "engines": {
32
26
  "node": ">= 18.0.0",
33
27
  "yarn": ">= 1.0.0"
@@ -39,14 +33,14 @@
39
33
  "not ie_mob > 0"
40
34
  ],
41
35
  "dependencies": {
42
- "@ditojs/build": "^1.21.0",
43
- "@ditojs/ui": "^1.21.0",
44
- "@ditojs/utils": "^1.21.0",
36
+ "@ditojs/build": "^1.23.0",
37
+ "@ditojs/ui": "^1.23.0",
38
+ "@ditojs/utils": "^1.23.0",
45
39
  "codeflask": "^1.4.1",
46
40
  "filesize": "^10.0.6",
47
41
  "filesize-parser": "^1.5.0",
48
- "nanoid": "^4.0.0",
49
- "tinycolor2": "^1.4.2",
42
+ "nanoid": "^4.0.1",
43
+ "tinycolor2": "^1.6.0",
50
44
  "tiptap": "^1.32.2",
51
45
  "tiptap-commands": "^1.17.1",
52
46
  "tiptap-extensions": "^1.35.2",
@@ -54,7 +48,7 @@
54
48
  "vue": "^2.7.14",
55
49
  "vue-color": "^2.8.1",
56
50
  "vue-js-modal": "^2.0.1",
57
- "vue-multiselect": "^2.1.6",
51
+ "vue-multiselect": "^2.1.7",
58
52
  "vue-notification": "^1.3.20",
59
53
  "vue-router": "^3.6.5",
60
54
  "vue-spinner": "^1.0.4",
@@ -65,12 +59,18 @@
65
59
  "devDependencies": {
66
60
  "@ditojs/build": "^1.19.0",
67
61
  "pug": "^3.0.2",
68
- "sass": "1.56.2",
69
- "type-fest": "^3.4.0",
70
- "typescript": "^4.9.4",
71
- "vite": "^4.0.1",
72
- "vite-plugin-vue2": "^2.0.2"
62
+ "sass": "1.58.0",
63
+ "type-fest": "^3.5.5",
64
+ "typescript": "^4.9.5",
65
+ "vite": "^4.1.1",
66
+ "vite-plugin-vue2": "^2.0.3"
73
67
  },
74
68
  "types": "types",
75
- "gitHead": "a9dd1a854dbf2928a92c0be6481d704bd579cfdc"
76
- }
69
+ "gitHead": "3258fd030226062efa6837bfc5e5a761e80cead5",
70
+ "scripts": {
71
+ "build": "vite build",
72
+ "watch": "yarn build --mode 'development' --watch",
73
+ "types": "tsc --noEmit types/index.d.ts"
74
+ },
75
+ "readme": "# Dito.js Admin\n\nDito.js is a declarative and modern web framework with a focus on API driven\ndevelopment, based on Koa.js, Objection.js and Vue.js\n\nReleased in 2018 under the MIT license, with support by https://lineto.com/\n\nDito.js Admin is a schema based admin interface for Dito.js, featuring auto-\ngenerated views and forms and built with Vue.js\n\n## Build Setup\n\n``` bash\n# install dependencies\nyarn install\n\n# serve your admin folder sym-linked into `dev` with hot reload at localhost:8080\nyarn serer\n\n# build library for production, with and without minification\nyarn build\n\n# build for production and view the bundle analyzer report\nyarn build --report\n```\n\nFor detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).\n\n## Introduction\n\nAn admin of a model consists of two parts, the view and the form. The view represents the model class and has access to the collection routes. The view typically shows a list of model instances with different functionalities like sorting and scopes. The form represents model instances and has access to members of the model. On the form model instances can be edited. The view and the form have in common that they both consist of components.\n\n## Creating A View\n\nIn order to add a new model to the admin create a new folder in dito-admin/src/schemas. The name of the folder is irrelevant however the convention is to use the hyphenated model name. Also export the new folder in the index.js file in the schemas folder like this:\n\n```js\nexport * from './folder-name/index.js'\n```\n\nWithin the folder create a new index.js file. Within this file the View is exported. An empty view looks like this:\n\n```js\nexport const viewName = {}\n```\n\nNotice, that the name given to the view is important. Firstly, it is a default value for the label used in the view. In the example the label would be 'View Name'. Secondly it is the default route the view retrieves data from. In the example the route would be '/api/view-name'.\n\nFrom there we define the view with a number of properties:\n\n| Property | Description |\n| --- | --- |\n| `type` | The type of the view. For now the value is 'list'. |\n| `label` | The label of the view. If no label is given, the labelized export name is used. |\n| `form/forms` | The form or a dictionary of forms of the view. |\n| `path` | The route of the view. If no path is given, the hyphentaed export name is used. |\n| `itemLabel` | The label given to the items. Can be string giving a property name of the item or a function of the item returning a string (e.g. `(person) => person.firstName + person.lastName`). If no itemLabel is given, the default is the 'name' property of the item, followed by label of the form of the view (plus item id) and other defaults. |\n| `columns` | The columns displayed in the table. The columns can be given as a list where each entry is the name of a property of the item (e.g. `['property1', 'property2'])`). However it is usually beneficial to assign an object with further options to the columns property. The options are the following:<br><ul><li>**label** The name of the column as a string. The default value is the labelized key.</li><li>**component** Use a Vue component to render the cell. The component is specified like this: `import(...)`.</li><li>**sortable** Boolean value determining if the column should be sortable.</li><li>**render** A function of the value and the item returning the displayed name. If the column is sortable, the column is sorted by value and not by rendered name.</li><li>**class** A string giving a class to the column cells.</li><li>**style** A string giving a style to the column cells.</li></ul>|\n| `editable` | Boolean value determining if the items can be edited with the admin. |\n| `creatable` | Boolean value determining if the items can be created with the admin. |\n| `deletable` | Boolean value determining if the items can be deleted with the admin. |\n| `paginate` | The number of items displayed per page. |\n| `scopes` | Scope names as defined on the model. Can be given as an array (`['scope1', 'scope2']`) or as a dictionary with optional labels (`{scope1 : {label : 'Scope A'}, scope2 : {label : 'Scope B'}}`). |\n| `scope` | Optional default scope name. |\n\n\n## Creating A Form\n\nThe form is created in the same folder as the view. The convention for the form name is to take the model name. Again, the labelized form name is used as the default label. A form can have the following properties:\n\n| Property | Description |\n| --- | --- |\n| `label` | The label of the form. |\n| `tabs` | With tabs several forms can be displayed in different tabs within the form (`{tab1 : form1, tab2 : form2}`). |\n| `components` | Keys within the components dictionary are the are the property name of the item which they are displaying/editing. The value is another object with options. I both tabs and components are given, the components are always visible whereas the tabs can be toggled. |\n\n\n### Components\n\nThere are a large variety of components for different data types and purposes. The most important properties are these:\n\n| Property | Description |\n| --- | --- |\n| `label` | The label of the component, if none is given the labelized key of the compoenent is used. |\n| `type` | The type of the component, there are many different options like 'text', 'textarea', 'email', 'radio', 'select' etc. For more types see the examples below or consult the code. |\n| `options` | An array of options. Only required if the type is 'select', 'radio' or a similar type. The array can also contain label-value pairs (`[{label : 'Option 1', value : 1}, {label : 'Option 2', value : 6}]`). |\n| `width` | The width of the component. The value can be given in percent (e.g. '20%') or as 'auto'. There will be several components on one line until their percentage exeeds 100%. |\n| `required` | Boolean value if the field is required or not. Dito uses both backend and frontend validation both required validation as well as the validation of some types (like email) are only frontend. |\n\nAlso, a component can be a nested list. For example, if you are modelling people with children, then a list of children can be shown for every person with a component like this:\n\n``` js\nchildren: {\n type: 'list',\n form: import('./ChildrenForm')\n inlined: true,\n creatable: true,\n editable: true,\n deletable: true\n}\n```\n\n### Component Examples\n\nA text component, as simple as it gets.\n\n```js\nfirstName: {\n type: 'text',\n label: 'First Name',\n width: '40%'\n}\n\n```\n\nHere is an example of a select component. One might just as well use type radio here. The layout can be vertical or horizontal.\n\n```js\nprefix: {\n type: 'select',\n label: 'Prefix',\n width: '10%',\n layout: 'vertical',\n options: [\n { label: 'Dr.', value: 'dr' },\n { label: 'Mr.', value: 'mr' },\n { label: 'Ms.', value: 'ms' }\n ]\n}\n```\n\nThis component allows selection of multiple items. It also searchable, meaning there will be suggestions as one enters a string into the input. Taggable allows adding additional options.\n\n```js\ntags: {\n type: 'multiselect',\n label: 'Tags',\n width: '50%',\n multiple: true,\n searchable: true,\n taggable: true,\n options: ['Developer', 'Designer', 'Writer', 'Composer']\n}\n```\n\nThis component uses an API to fetch its data. It also has a placeholder which is displayed in the input field until data is entered. The API provides JSON with an array of dictionaries. `label` retrieves the label that is diplayed to the user. `value` the value of the options. Options with the same `groupBy` value can be merged into groups.\n\n```js\ncountry: {\n type: 'multiselect',\n label: 'Country',\n multiple: false,\n searchable: true,\n placeholder: 'Select or search country',\n options: {\n data({ request }) {\n return request({\n cache: 'global',\n url: 'https://cdn.rawgit.com/lukes/ISO-3166-Countries-with-Regional-Codes/d4031492/all/all.json'\n })\n },\n label: 'name',\n value: 'alpha-2',\n groupBy: 'sub-region'\n }\n}\n```\n\nThis example validates the input with the step and the range options. There are further such options like min and max. step also gives buttons to increase/decrease the number.\n\n```js\nfactor: {\n label: 'Factor',\n type: 'number',\n width: 'auto',\n step: 0.01,\n range: [0, 100],\n required: true\n}\n```\n"
76
+ }
package/src/DitoAdmin.js CHANGED
@@ -288,10 +288,11 @@ function onBeforeViteUpdate(event) {
288
288
  // Why the stored `deps` are missing this part of the URL, I cannot say…
289
289
  const updates = []
290
290
  for (const update of event.updates) {
291
- updates.push(update, {
292
- ...update,
293
- acceptedPath: update.acceptedPath.replace(/\?v=[0-9a-f]+&/, '?')
294
- })
291
+ updates.push(update) // Keep the original update.
292
+ const acceptedPath = update.acceptedPath.replace(/\?v=[0-9a-f]+&/i, '?')
293
+ if (acceptedPath !== update.acceptedPath) {
294
+ updates.push({ ...update, acceptedPath })
295
+ }
295
296
  }
296
297
  event.updates = updates
297
298
  }
@@ -93,7 +93,7 @@ export default DitoComponent.component('dito-dialog', {
93
93
 
94
94
  mounted() {
95
95
  this.windowEvents = addEvents(window, {
96
- keyup: () => {
96
+ keyup: event => {
97
97
  if (this.hasCancel && event.keyCode === 27) {
98
98
  this.cancel()
99
99
  }
package/types/index.d.ts CHANGED
@@ -35,8 +35,8 @@ export type RequestMethod = <T>({
35
35
  method: HTTPVerb
36
36
  data: any
37
37
  /** @deprecated use query instead */
38
- params: ConstructorParameters<typeof URLSearchParams>[0]
39
- query: ConstructorParameters<typeof URLSearchParams>[0]
38
+ params: Record<string, string | string[]> | [string, string][]
39
+ query: Record<string, string | string[]> | [string, string][]
40
40
  headers: Record<string, string>
41
41
  }) => Promise<RequestMethodResponse<T>>
42
42
 
@@ -1035,11 +1035,14 @@ export type DitoContext<$Item = any> = {
1035
1035
  cache?: 'local' | 'global'
1036
1036
  url: string
1037
1037
  /**
1038
- * @defaultValue `'get'`
1038
+ * @default 'get'
1039
1039
  */
1040
1040
  method?: HTTPVerb
1041
- params?: any
1041
+ /** @deprecated use query instead */
1042
+ params?: Record<string, string | string[]> | [string, string][]
1043
+ query?: Record<string, string | string[]> | [string, string][]
1042
1044
  data?: any
1045
+ resource?: Resource
1043
1046
  }): Promise<T>
1044
1047
  format: typeof utilsFormat
1045
1048
  navigate(location: string | { path: string }): Promise<boolean>
@@ -1056,31 +1059,16 @@ export type DitoContext<$Item = any> = {
1056
1059
  }
1057
1060
 
1058
1061
  export type View<$Item = any> = {
1062
+ type: 'view',
1059
1063
  resource?: Form['resource']
1060
1064
  clipboard?: Form['clipboard']
1061
- } & (
1062
- | InputSchema<$Item>
1063
- | RadioSchema<$Item>
1064
- | CheckboxSchema<$Item>
1065
- | CheckboxesSchema<$Item>
1066
- | ColorSchema<$Item>
1067
- | SelectSchema<$Item>
1068
- | MultiselectSchema<$Item>
1069
- | ListSchema<$Item>
1070
- | TextareaSchema<$Item>
1071
- | CodeSchema<$Item>
1072
- | NumberSchema<$Item>
1073
- | SliderSchema<$Item>
1074
- | UploadSchema<$Item>
1075
- | MarkupSchema<$Item>
1076
- | ButtonSchema<$Item>
1077
- | SwitchSchema<$Item>
1078
- | DateSchema<$Item>
1079
- | ComponentSchema<$Item>
1080
- | LabelSchema<$Item>
1081
- | SectionSchema<$Item>
1082
- | HiddenSchema<$Item>
1083
- )
1065
+ component?: Component<$Item>
1066
+ } | {
1067
+ type: 'view',
1068
+ resource?: Form['resource']
1069
+ clipboard?: Form['clipboard']
1070
+ components?: Components<$Item>
1071
+ }
1084
1072
 
1085
1073
  export type Component<$Item = any> =
1086
1074
  | InputSchema<$Item>
@@ -1105,7 +1093,7 @@ export type Component<$Item = any> =
1105
1093
  | SectionSchema<$Item>
1106
1094
  | HiddenSchema<$Item>
1107
1095
 
1108
- export type Components<$Item = any> = {
1096
+ export type Components<$Item = any> = Component<$Item>[] | {
1109
1097
  [$name: string]: Component<$Item>
1110
1098
  }
1111
1099
 
@@ -1115,6 +1103,8 @@ export type Buttons<$Item> = Record<
1115
1103
  >
1116
1104
 
1117
1105
  export type Form<$Item = any> = {
1106
+ type: 'form'
1107
+
1118
1108
  /**
1119
1109
  * The name of the item model produced by the form.
1120
1110
  */
@@ -1133,9 +1123,9 @@ export type Form<$Item = any> = {
1133
1123
  */
1134
1124
  tabs?: Record<
1135
1125
  string,
1136
- Omit<Form<$Item>, 'tabs'> & {
1126
+ Omit<Form<$Item>, 'tabs' | 'type'> & {
1137
1127
  defaultTab?: OrItemAccessor<$Item, {}, boolean>
1138
- }
1128
+ }
1139
1129
  >
1140
1130
  // TODO: document components
1141
1131
  components?: Components<$Item>