@ditojs/admin 2.3.1 → 2.4.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.
@@ -43,21 +43,31 @@ $content-color-background: $color-lightest;
43
43
  $form-spacing: $input-padding-hor;
44
44
  $form-spacing-half: calc($form-spacing / 2);
45
45
 
46
- // Menu
47
- $menu-font-size: 14px;
48
- $menu-line-height: 1;
49
- $menu-z-index: 1000;
50
- $menu-padding-ver: $menu-font-size;
51
- $menu-padding-hor: $content-padding;
52
- $menu-padding: $menu-padding-ver $menu-padding-hor;
53
- $menu-height: $menu-font-size + 2 * $menu-padding-ver;
46
+ // Header
47
+ $header-font-size: 14px;
48
+ $header-line-height: 1;
49
+ $header-z-index: 1000;
50
+ $header-padding-ver: $header-font-size;
51
+ $header-padding-hor: $content-padding;
52
+ $header-padding: $header-padding-ver $header-padding-hor;
53
+ $header-height: $header-font-size + 2 * $header-padding-ver;
54
54
 
55
55
  // Tabs
56
56
  $tab-margin: 6px;
57
57
  $tab-padding-hor: 12px;
58
- $tab-padding-ver: calc(($menu-padding-ver * 2 - $tab-margin) / 2);
58
+ $tab-padding-ver: calc(($header-padding-ver * 2 - $tab-margin) / 2);
59
59
  $tab-radius: 4px;
60
- // $border-radius
60
+
61
+ // Menu
62
+ $menu-font-size: $header-font-size;
63
+ $menu-line-height: $header-line-height;
64
+ $menu-spacing: 4px;
65
+ $menu-padding-ver: $header-padding-ver - $menu-spacing;
66
+ $menu-padding-hor: $header-padding-hor - $menu-spacing;
67
+ $menu-padding: $menu-padding-ver $menu-padding-hor;
68
+
69
+ // Drag & Drop
70
+ $drag-overlay-z-index: 2000;
61
71
 
62
72
  // Patterns
63
73
  $pattern-transparency-size: ($font-size - $border-width) * $input-height-factor;
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  button.dito-button(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  :type="type"
6
5
  :title="title"
7
6
  :class="buttonClass"
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  input.dito-checkbox(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  v-model="value"
6
5
  type="checkbox"
7
6
  v-bind="attributes"
@@ -3,7 +3,6 @@
3
3
  //- involve actually rendering it when the component is not visible.
4
4
  input.dito-text.dito-input(
5
5
  :id="dataPath"
6
- ref="element"
7
6
  :name="name"
8
7
  type="text"
9
8
  :value="value"
@@ -1,6 +1,6 @@
1
1
  <template lang="pug">
2
2
  .dito-markup(:id="dataPath")
3
- .dito-markup-toolbar(:editor="editor")
3
+ .dito-markup-toolbar
4
4
  .dito-buttons.dito-buttons-toolbar(
5
5
  v-if="groupedButtons.length > 0"
6
6
  )
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  InputField.dito-number(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  v-model="inputValue"
6
5
  type="number"
7
6
  v-bind="attributes"
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  progress.dito-progress(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  :value="progressValue"
6
5
  :max="progressMax"
7
6
  v-bind="attributes"
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  SwitchButton.dito-switch(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  v-model="value"
6
5
  :labels="labels"
7
6
  v-bind="attributes"
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  InputField.dito-text(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  v-model="inputValue"
6
5
  :type="inputType"
7
6
  v-bind="attributes"
@@ -1,7 +1,6 @@
1
1
  <template lang="pug">
2
2
  textarea.dito-textarea.dito-input(
3
3
  :id="dataPath"
4
- ref="element"
5
4
  v-model="value"
6
5
  v-bind="attributes"
7
6
  :rows="lines"
@@ -73,13 +73,8 @@
73
73
  v-if="isUploadActive"
74
74
  type="button"
75
75
  @click.prevent="upload.active = false"
76
- ) Cancel All
77
- button.dito-button(
78
- v-else-if="isUploadReady"
79
- type="button"
80
- @click.prevent="upload.active = true"
81
- ) Upload All
82
- VueUpload.dito-button.dito-button-add-upload(
76
+ ) Cancel
77
+ VueUpload.dito-button(
83
78
  ref="upload"
84
79
  v-model="uploads"
85
80
  :inputId="dataPath"
@@ -90,10 +85,13 @@
90
85
  :accept="accept"
91
86
  :multiple="multiple"
92
87
  :size="maxSize"
93
- title="Upload Files"
88
+ :title="multiple ? 'Upload Files' : 'Upload File'"
89
+ :drop="$el?.closest('.dito-container')"
90
+ :dropDirectory="true"
94
91
  @input-filter="inputFilter"
95
92
  @input-file="inputFile"
96
93
  )
94
+ .dito-button-upload
97
95
  </template>
98
96
 
99
97
  <script>
@@ -169,7 +167,7 @@ export default DitoTypeComponent.register('upload', {
169
167
 
170
168
  isUploadReady() {
171
169
  return (
172
- this.uploads.length &&
170
+ this.uploads.length > 0 &&
173
171
  !(this.upload.active || this.upload.uploaded)
174
172
  )
175
173
  },
@@ -180,7 +178,7 @@ export default DitoTypeComponent.register('upload', {
180
178
 
181
179
  uploadProgress() {
182
180
  return (
183
- this.uploads.reduce((total, file) => total + file.progress, 0) /
181
+ this.uploads.reduce((total, file) => +file.progress + total, 0) /
184
182
  this.uploads.length
185
183
  )
186
184
  },
@@ -193,6 +191,17 @@ export default DitoTypeComponent.register('upload', {
193
191
  }
194
192
  },
195
193
 
194
+ watch: {
195
+ isUploadReady(ready) {
196
+ if (ready) {
197
+ // Auto-upload.
198
+ this.$nextTick(() => {
199
+ this.upload.active = true
200
+ })
201
+ }
202
+ }
203
+ },
204
+
196
205
  methods: {
197
206
  formatFileSize,
198
207
 
@@ -293,6 +302,7 @@ export default DitoTypeComponent.register('upload', {
293
302
  this.removeFile(newFile)
294
303
  }
295
304
  } else if (error) {
305
+ this.removeFile(newFile)
296
306
  const text = (
297
307
  {
298
308
  abort: 'Upload aborted',
@@ -310,7 +320,6 @@ export default DitoTypeComponent.register('upload', {
310
320
  title: 'File Upload Error',
311
321
  text
312
322
  })
313
- this.removeFile(newFile)
314
323
  }
315
324
  }
316
325
  },
@@ -347,7 +356,7 @@ function asFiles(value) {
347
356
  }
348
357
  }
349
358
 
350
- .dito-button-add-upload {
359
+ .dito-button-upload {
351
360
  padding: 0;
352
361
 
353
362
  > * {
@@ -113,6 +113,10 @@ export function isPanel(schema) {
113
113
  return isSchema(schema) && schema.type === 'panel'
114
114
  }
115
115
 
116
+ export function isMenu(schema) {
117
+ return isSchema(schema) && schema.type === 'menu'
118
+ }
119
+
116
120
  export function getSchemaIdentifier(schema) {
117
121
  return JSON.stringify(schema)
118
122
  }
@@ -176,6 +180,19 @@ export async function resolveSchemas(
176
180
  return schemas
177
181
  }
178
182
 
183
+ export async function resolveViews(unresolvedViews) {
184
+ return resolveSchemas(unresolvedViews, async (schema, unwrapModule) => {
185
+ schema = await resolveSchema(schema, unwrapModule)
186
+ if (!schema.name && isMenu(schema)) {
187
+ // Generate a name for sub-menus from their label if it's missing.
188
+ // NOTE: This is never actually referenced from anywhere, but they need
189
+ // a name by which they're stored in the parent object.
190
+ schema.name = camelize(schema.label)
191
+ }
192
+ return schema
193
+ })
194
+ }
195
+
179
196
  export async function resolveSchemaComponent(schema) {
180
197
  // Resolves async schema components and adds DitoMixin and TypeMixin to them.
181
198
  let { component } = schema
@@ -250,22 +267,31 @@ export async function processSchemaComponent(
250
267
  }
251
268
 
252
269
  export async function processView(component, api, schema, name) {
253
- if (!isView(schema)) {
254
- throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
255
- }
256
- processRouteSchema(api, schema, name)
257
270
  processSchemaDefaults(api, schema)
258
- await processNestedSchemas(api, schema)
259
- const children = []
260
- await processSchemaComponents(api, schema, children, 0)
261
- return {
262
- path: `/${schema.path}`,
263
- children,
264
- component,
265
- meta: {
266
- api,
267
- schema
271
+ if (isView(schema)) {
272
+ processRouteSchema(api, schema, name)
273
+ await processNestedSchemas(api, schema)
274
+ const children = []
275
+ await processSchemaComponents(api, schema, children, 0)
276
+ return {
277
+ path: `/${schema.path}`,
278
+ children,
279
+ component,
280
+ meta: {
281
+ api,
282
+ schema
283
+ }
268
284
  }
285
+ } else if (isMenu(schema)) {
286
+ schema.items = await resolveSchemas(schema.items)
287
+ return Promise.all(
288
+ Object.entries(schema.items).map(async ([name, item]) =>
289
+ processView(component, api, item, name)
290
+ )
291
+ )
292
+ //
293
+ } else {
294
+ throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
269
295
  }
270
296
  }
271
297
 
@@ -303,8 +329,8 @@ export function processNestedSchemaDefaults(api, schema) {
303
329
 
304
330
  export function processRouteSchema(api, schema, name) {
305
331
  // Used for view and source schemas, see SourceMixin.
306
- schema.name = name
307
- schema.path ||= api.normalizePath(name)
332
+ schema.name ??= name
333
+ schema.path ??= api.normalizePath(name)
308
334
  }
309
335
 
310
336
  export async function processForms(api, schema, level) {