@ditojs/admin 2.8.1 → 2.8.2

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": "2.8.1",
3
+ "version": "2.8.2",
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",
@@ -83,7 +83,7 @@
83
83
  "vite": "^4.3.5"
84
84
  },
85
85
  "types": "types",
86
- "gitHead": "26db3d0a7ebbed92b052bd7cffa078e9cdae7497",
86
+ "gitHead": "d9a0905b7c93d509a3710b36c749cc6e651401d3",
87
87
  "scripts": {
88
88
  "build": "vite build",
89
89
  "watch": "yarn build --mode 'development' --watch",
@@ -73,6 +73,10 @@ export default DitoComponent.component('DitoClipboard', {
73
73
  }
74
74
  },
75
75
 
76
+ watch: {
77
+ 'appState.clipboardData': 'checkClipboard'
78
+ },
79
+
76
80
  mounted() {
77
81
  // Check clipboard content whenever something gets copied or the window gets
78
82
  // (re)activated, as those are the moments when the clipboard can change:
@@ -1,9 +1,10 @@
1
1
  <template lang="pug">
2
- UseSortable(
2
+ UseSortable.dito-draggable(
3
3
  v-if="draggable"
4
+ :class="{ 'dito-draggable--dragging': isDragging }"
4
5
  :tag="tag"
5
6
  :modelValue="modelValue"
6
- :options="options"
7
+ :options="{ ...options, onStart, onEnd }"
7
8
  @update:modelValue="$emit('update:modelValue', $event)"
8
9
  )
9
10
  slot
@@ -15,6 +16,7 @@ component(
15
16
  </template>
16
17
 
17
18
  <script>
19
+ import { addEvents } from '@ditojs/ui'
18
20
  import DitoComponent from '../DitoComponent'
19
21
  import { UseSortable } from '@vueuse/integrations/useSortable/component'
20
22
 
@@ -40,6 +42,73 @@ export default DitoComponent.component('DitoDraggable', {
40
42
  type: Boolean,
41
43
  default: true
42
44
  }
45
+ },
46
+
47
+ data() {
48
+ return {
49
+ mouseEvents: null,
50
+ isDragging: false
51
+ }
52
+ },
53
+
54
+ methods: {
55
+ onStart(event) {
56
+ this.isDragging = true
57
+ this.options.onStart?.(event)
58
+ this.mouseEvents?.remove()
59
+ },
60
+
61
+ onEnd(event) {
62
+ this.options.onEnd?.(event)
63
+ // Keep `isDragging` true until the next mouse interaction so that
64
+ // confused hover states are cleared before removing the hover catcher.
65
+ this.mouseEvents = addEvents(this.$el, {
66
+ mousedown: this.onMouse,
67
+ mousemove: this.onMouse,
68
+ mouseleave: this.onMouse
69
+ })
70
+ },
71
+
72
+ onMouse() {
73
+ this.isDragging = false
74
+ this.mouseEvents.remove()
75
+ this.mouseEvents = null
76
+ }
43
77
  }
44
78
  })
45
79
  </script>
80
+
81
+ <style lang="scss">
82
+ @import '../styles/_imports';
83
+
84
+ .dito-draggable {
85
+ // Overlay a hover catcher while we're dragging to prevent hover states from
86
+ // getting stuck / confused.
87
+ &:has(&__chosen),
88
+ &--dragging {
89
+ > * {
90
+ position: relative;
91
+
92
+ > :first-child::after {
93
+ content: '';
94
+ position: absolute;
95
+ inset: 0;
96
+ }
97
+ }
98
+ }
99
+
100
+ &__fallback {
101
+ filter: drop-shadow(0 2px 4px $color-shadow);
102
+
103
+ // Nested <td> need to also switch to `display: flex` style during dragging.
104
+ &,
105
+ td {
106
+ display: flex;
107
+
108
+ > * {
109
+ flex: 1;
110
+ }
111
+ }
112
+ }
113
+ }
114
+ </style>
@@ -78,19 +78,19 @@ export default DitoComponent.component('DitoEditButtons', {
78
78
  return this.disabled || !this.hasSchemaOption('deletable')
79
79
  },
80
80
 
81
- isCreatableDisabled() {
81
+ isEditableDisabled() {
82
82
  return (
83
83
  this.disabled ||
84
- !this.createPath ||
85
- !this.hasSchemaOption('creatable')
84
+ !this.editPath ||
85
+ !this.hasSchemaOption('editable')
86
86
  )
87
87
  },
88
88
 
89
- isEditableDisabled() {
89
+ isCreatableDisabled() {
90
90
  return (
91
91
  this.disabled ||
92
- !this.editPath ||
93
- !this.hasSchemaOption('editable')
92
+ !this.createPath ||
93
+ !this.hasSchemaOption('creatable')
94
94
  )
95
95
  },
96
96
 
@@ -214,7 +214,7 @@ export default DitoComponent.component('DitoSchema', {
214
214
  },
215
215
 
216
216
  clipboard() {
217
- return this.schema?.clipboard
217
+ return this.schema?.clipboard ?? null
218
218
  },
219
219
 
220
220
  hasHeader() {
@@ -676,6 +676,7 @@ export default DitoComponent.component('DitoSchema', {
676
676
  {
677
677
  // Needed for DitoContext handling inside `processData` and
678
678
  // `processSchemaData()`:
679
+ rootData: this.rootData,
679
680
  component: this,
680
681
  schemaOnly,
681
682
  target
@@ -772,7 +773,7 @@ export default DitoComponent.component('DitoSchema', {
772
773
  grid-template-rows: min-content;
773
774
  grid-template-columns: 100%;
774
775
 
775
- > *:only-child {
776
+ > :only-child {
776
777
  grid-row-end: none;
777
778
  }
778
779
  }
@@ -82,17 +82,10 @@ export default DitoComponent.component('DitoSchemaInlined', {
82
82
  grid-template-rows: min-content;
83
83
  grid-template-columns: 100%;
84
84
 
85
- > .dito-schema-content {
85
+ &:not(:hover, .dito-schema--open) {
86
86
  > .dito-schema-header {
87
- justify-content: space-between;
88
- position: relative;
89
-
90
- .dito-label {
91
- width: 100%;
92
- margin: 0;
93
- // Prevent collapsing to min-height when alone in
94
- // .dito-schema-content, due to grid-template-rows: min-content
95
- min-height: $input-height;
87
+ > .dito-clipboard {
88
+ display: none;
96
89
  }
97
90
  }
98
91
  }
@@ -2,7 +2,7 @@
2
2
  .dito-tree-item(
3
3
  :id="dataPath"
4
4
  :class=`{
5
- 'dito-dragging': dragging,
5
+ 'dito-dragging': isDragging,
6
6
  'dito-active': active
7
7
  }`
8
8
  :style="level > 0 && { '--level': level }"
@@ -76,7 +76,7 @@
76
76
  v-if="childrenSchema"
77
77
  v-show="opened"
78
78
  :modelValue="updateOrder(childrenSchema, childrenList)"
79
- :options="getSortableOptions(true)"
79
+ :options="getDraggableOptions(true)"
80
80
  :draggable="childrenDraggable"
81
81
  @update:modelValue="value => (childrenList = value)"
82
82
  )
@@ -2,19 +2,20 @@
2
2
  export default {
3
3
  data() {
4
4
  return {
5
- dragging: false
5
+ isDragging: false
6
6
  }
7
7
  },
8
8
 
9
9
  methods: {
10
- getSortableOptions(forceFallback = false) {
10
+ getDraggableOptions(forceFallback = false) {
11
+ const prefix = 'dito-draggable'
11
12
  return {
12
13
  animation: 150,
13
14
  handle: '.dito-button-drag',
14
- dragClass: 'dito-sortable-active',
15
- chosenClass: 'dito-sortable-chosen',
16
- ghostClass: 'dito-sortable-ghost',
17
- fallbackClass: 'dito-sortable-fallback',
15
+ dragClass: `${prefix}__drag`,
16
+ chosenClass: `${prefix}__chosen`,
17
+ ghostClass: `${prefix}__ghost`,
18
+ fallbackClass: `${prefix}__fallback`,
18
19
  forceFallback,
19
20
  onStart: this.onStartDrag,
20
21
  onEnd: this.onEndDrag
@@ -22,11 +23,11 @@ export default {
22
23
  },
23
24
 
24
25
  onStartDrag() {
25
- this.dragging = true
26
+ this.isDragging = true
26
27
  },
27
28
 
28
29
  onEndDrag({ oldIndex, newIndex }) {
29
- this.dragging = false
30
+ this.isDragging = false
30
31
  if (oldIndex !== newIndex) {
31
32
  this.onChange()
32
33
  }
@@ -13,7 +13,7 @@
13
13
  }
14
14
 
15
15
  .dito-layout-horizontal {
16
- > *:not(:first-child) {
16
+ > :not(:first-child) {
17
17
  padding-left: $form-spacing;
18
18
  }
19
19
  }
@@ -4,7 +4,6 @@
4
4
  @import '_pulldown';
5
5
  @import '_layout';
6
6
  @import '_scroll';
7
- @import '_sortable';
8
7
  @import '_table';
9
8
  @import '_info';
10
9
  @import '_tippy';
@@ -39,7 +39,7 @@
39
39
  DitoDraggable(
40
40
  tag="tbody"
41
41
  :modelValue="updateOrder(sourceSchema, listData, paginationRange)"
42
- :options="getSortableOptions()"
42
+ :options="getDraggableOptions()"
43
43
  :draggable="draggable"
44
44
  @update:modelValue="value => (listData = value)"
45
45
  )
@@ -1,15 +1,14 @@
1
1
  <template lang="pug">
2
- .dito-multiselect(
3
- :class=`{
4
- 'dito-multiselect-single': !multiple,
5
- 'dito-multiselect-multiple': multiple
6
- }`
7
- )
2
+ .dito-multiselect
8
3
  .dito-multiselect__inner
9
4
  VueMultiselect(
10
5
  ref="element"
11
6
  v-model="selectedOptions"
12
- :class="{ 'multiselect--show-highlight': showHighlight }"
7
+ :class=`{
8
+ 'multiselect--multiple': multiple,
9
+ 'multiselect--loading': isLoading,
10
+ 'multiselect--highlight': showHighlight
11
+ }`
13
12
  :showLabels="false"
14
13
  :placeholder="placeholder"
15
14
  tagPlaceholder="Press enter to add new tag"
@@ -241,16 +240,6 @@ $tag-line-height: 1em;
241
240
  position: relative;
242
241
  }
243
242
 
244
- // TODO: BEM
245
- &.dito-multiselect-single {
246
- --input-width: 100%;
247
- }
248
-
249
- // TODO: BEM
250
- &.dito-multiselect-multiple {
251
- --input-width: auto;
252
- }
253
-
254
243
  .dito-edit-buttons {
255
244
  margin-left: $form-spacing-half;
256
245
  }
@@ -258,10 +247,16 @@ $tag-line-height: 1em;
258
247
  .multiselect {
259
248
  $self: last-selector(&);
260
249
 
250
+ --input-width: 100%;
251
+
261
252
  font-size: inherit;
262
253
  min-height: inherit;
263
254
  color: $color-black;
264
255
 
256
+ &--multiple {
257
+ --input-width: auto;
258
+ }
259
+
265
260
  &__tags {
266
261
  display: flex;
267
262
  font-size: inherit;
@@ -373,11 +368,11 @@ $tag-line-height: 1em;
373
368
  }
374
369
 
375
370
  // Only show the highlight once the pulldown has received mouse or
376
- // keyboard interaction, in which case `&--show-highlight` will be set,
371
+ // keyboard interaction, in which case `&--highlight` will be set,
377
372
  // which is controlled by `pointerDirty` in vue-multiselect.
378
373
  // Until then, clear the highlight style, but only if it isn't also
379
374
  // disabled or selected, in which case we want to keep the style.
380
- @at-root #{$self}:not(#{$self}--show-highlight)
375
+ @at-root #{$self}:not(#{$self}--highlight)
381
376
  #{$option}:not(#{$option}--disabled):not(#{$option}--selected) {
382
377
  color: $color-text;
383
378
  background: transparent;
@@ -391,7 +386,7 @@ $tag-line-height: 1em;
391
386
  color: $color-white;
392
387
  }
393
388
 
394
- @at-root #{$self}#{$self}--show-highlight #{last-selector(&)} {
389
+ @at-root #{$self}#{$self}--highlight #{last-selector(&)} {
395
390
  color: $color-text-inverted;
396
391
  background: $color-active;
397
392
  }
@@ -402,7 +397,7 @@ $tag-line-height: 1em;
402
397
  color: $color-text;
403
398
  background: $color-highlight;
404
399
 
405
- @at-root #{$self}#{$self}--show-highlight &#{$option}--highlight {
400
+ @at-root #{$self}#{$self}--highlight &#{$option}--highlight {
406
401
  color: $color-text-inverted;
407
402
  }
408
403
  }
@@ -490,6 +485,16 @@ $tag-line-height: 1em;
490
485
  }
491
486
  }
492
487
  }
488
+
489
+ &--loading {
490
+ #{$self}__tags {
491
+ border-radius: $border-radius;
492
+ }
493
+
494
+ #{$self}__content-wrapper {
495
+ display: none;
496
+ }
497
+ }
493
498
  }
494
499
  }
495
500
  </style>
@@ -35,7 +35,7 @@
35
35
  DitoDraggable(
36
36
  v-model="files"
37
37
  tag="tbody"
38
- :options="getSortableOptions()"
38
+ :options="getDraggableOptions()"
39
39
  :draggable="draggable"
40
40
  )
41
41
  template(
@@ -485,11 +485,11 @@ export function getFormSchemas(schema, context, modifyForm) {
485
485
 
486
486
  let { form, forms } = schema
487
487
  if (!form && !forms) {
488
- const { components, tabs, compact, clipboard } = schema
488
+ const { name, compact, clipboard, tabs, components } = schema
489
489
  if (components || tabs) {
490
- // Convert inlined components to forms, also supporting `tabs`, `compact`
491
- // and `clipboard` settings.
492
- form = { components, tabs, compact, clipboard }
490
+ // Convert inlined forms to stand-alone forms, supporting `name`,
491
+ // `compact`, `clipboard`, `tabs` and `components` settings.
492
+ form = { type: 'form', name, compact, clipboard, tabs, components }
493
493
  } else {
494
494
  // No `forms`, `form` or `components`, return and empty `forms` object.
495
495
  return {}
@@ -702,10 +702,11 @@ function cloneItem(sourceSchema, item, options) {
702
702
 
703
703
  export function processData(schema, sourceSchema, data, dataPath, {
704
704
  component,
705
+ rootData,
705
706
  schemaOnly, // whether to only include data covered by the schema, or all data
706
707
  target
707
708
  } = {}) {
708
- const options = { component, schemaOnly, target, rootData: data }
709
+ const options = { component, rootData, schemaOnly, target }
709
710
  const processedData = cloneItem(sourceSchema, data, options)
710
711
  const graph = new SchemaGraph()
711
712
 
@@ -837,15 +838,15 @@ export function processSchemaData(
837
838
  const componentDataPath = getDataPath(dataPath, name)
838
839
 
839
840
  const processItem = (item, index = null) => {
840
- const dataPath =
841
+ const itemDataPath =
841
842
  index !== null
842
843
  ? getDataPath(componentDataPath, index)
843
844
  : componentDataPath
844
845
  const context = new DitoContext(options.component, {
845
846
  schema: componentSchema,
846
- data,
847
+ data: item,
847
848
  value: item,
848
- dataPath,
849
+ dataPath: itemDataPath,
849
850
  index,
850
851
  rootData: options.rootData
851
852
  })
@@ -862,7 +863,7 @@ export function processSchemaData(
862
863
  return processSchemaData(
863
864
  form,
864
865
  item,
865
- dataPath,
866
+ itemDataPath,
866
867
  processedItem,
867
868
  processBefore,
868
869
  processAfter,
@@ -882,6 +883,7 @@ export function processSchemaData(
882
883
  componentDataPath,
883
884
  processedData
884
885
  )
886
+
885
887
  let value = processedData ? processedData[name] : data[name]
886
888
  if (value != null && hasFormSchema(componentSchema)) {
887
889
  // Recursively process data on nested form items.
@@ -897,6 +899,7 @@ export function processSchemaData(
897
899
  processedData[name] = value
898
900
  }
899
901
  }
902
+
900
903
  processAfter?.(
901
904
  componentSchema,
902
905
  data,
@@ -1,13 +0,0 @@
1
- .dito-sortable-fallback {
2
- filter: drop-shadow(0 2px 4px $color-shadow);
3
-
4
- // Nested <td> need to also switch to `display: block` style during dragging
5
- &,
6
- td {
7
- display: flex;
8
-
9
- > * {
10
- flex: 1;
11
- }
12
- }
13
- }