@ditojs/admin 2.3.0 → 2.3.1

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.3.0",
3
+ "version": "2.3.1",
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",
@@ -33,7 +33,7 @@
33
33
  "not ie_mob > 0"
34
34
  ],
35
35
  "dependencies": {
36
- "@ditojs/ui": "^2.3.0",
36
+ "@ditojs/ui": "^2.3.1",
37
37
  "@ditojs/utils": "^2.3.0",
38
38
  "@kyvg/vue3-notification": "^2.9.0",
39
39
  "@lk77/vue3-color": "^3.0.6",
@@ -83,7 +83,7 @@
83
83
  "vite": "^4.3.1"
84
84
  },
85
85
  "types": "types",
86
- "gitHead": "81398b333e755f30b2c3c1998c8879a3e87f7873",
86
+ "gitHead": "1b5f5121a2e8e6d3741f0bb2b81d38c2343810d6",
87
87
  "scripts": {
88
88
  "build": "vite build",
89
89
  "watch": "yarn build --mode 'development' --watch",
@@ -10,23 +10,25 @@ DitoButtons.dito-edit-buttons.dito-buttons-round(
10
10
  )
11
11
  //- Firefox doesn't like <button> here, so use <a> instead:
12
12
  a.dito-button(
13
- v-if="isDraggable"
13
+ v-if="hasDraggable"
14
14
  v-bind="getButtonAttributes(verbs.drag)"
15
15
  )
16
16
  RouterLink.dito-button(
17
- v-if="isEditable"
18
- :to="{ path: editPath }"
17
+ v-if="hasEditable"
18
+ :class="{ 'dito-disabled': !editPath }"
19
+ :to="editPath ? { path: editPath } : {}"
19
20
  v-bind="getButtonAttributes(verbs.edit)"
20
21
  )
21
22
  DitoCreateButton(
22
- v-if="isCreatable"
23
+ v-if="hasCreatable"
24
+ :class="{ 'dito-disabled': !createPath }"
23
25
  :schema="schema"
24
26
  :path="createPath"
25
27
  :verb="verbs.create"
26
28
  :text="createButtonText"
27
29
  )
28
30
  button.dito-button(
29
- v-if="isDeletable"
31
+ v-if="hasDeletable"
30
32
  type="button"
31
33
  v-bind="getButtonAttributes(verbs.delete)"
32
34
  @click="$emit('delete')"
@@ -61,19 +63,19 @@ export default DitoComponent.component('DitoEditButtons', {
61
63
  return this.getLabel(this.schema.form)
62
64
  },
63
65
 
64
- isDraggable() {
66
+ hasDraggable() {
65
67
  return this.hasOption('draggable')
66
68
  },
67
69
 
68
- isEditable() {
69
- return this.hasOption('editable') && !!this.editPath
70
+ hasEditable() {
71
+ return this.hasOption('editable')
70
72
  },
71
73
 
72
- isCreatable() {
73
- return this.hasOption('creatable') && !!this.createPath
74
+ hasCreatable() {
75
+ return this.hasOption('creatable')
74
76
  },
75
77
 
76
- isDeletable() {
78
+ hasDeletable() {
77
79
  return this.hasOption('deletable')
78
80
  },
79
81
 
@@ -289,8 +289,9 @@ export default DitoComponent.component('DitoForm', {
289
289
  if (
290
290
  param &&
291
291
  this.providesData &&
292
- from.params[param] !== 'create' &&
293
- to.params[param] !== from.params[param]
292
+ from.matched[0].path === to.matched[0].path && // Staying on same form?
293
+ from.params[param] !== 'create' && // But haven't been creating?
294
+ to.params[param] !== from.params[param] // Going to a different entity?
294
295
  ) {
295
296
  this.loadData(true)
296
297
  }
@@ -224,10 +224,10 @@ export default DitoComponent.component('DitoPanel', {
224
224
  > .dito-schema-content {
225
225
  > .dito-pane {
226
226
  padding: $form-spacing-half $form-spacing;
227
- }
228
227
 
229
- .dito-container {
230
- padding: $form-spacing-half;
228
+ > .dito-container {
229
+ padding: $form-spacing-half;
230
+ }
231
231
  }
232
232
 
233
233
  .dito-object {
@@ -1,5 +1,6 @@
1
1
  import DitoContext from '../DitoContext.js'
2
2
  import DataMixin from './DataMixin.js'
3
+ import { hasViewSchema, getViewEditPath } from '../utils/schema.js'
3
4
  import { getSchemaAccessor } from '../utils/accessor.js'
4
5
  import { setTemporaryId, isReference } from '../utils/data.js'
5
6
  import {
@@ -145,6 +146,23 @@ export default {
145
146
  }
146
147
  }),
147
148
 
149
+ editable: getSchemaAccessor('editable', {
150
+ type: Boolean,
151
+ default: false,
152
+ get(editable) {
153
+ return (
154
+ editable &&
155
+ hasViewSchema(this.schema, this.context)
156
+ )
157
+ }
158
+ }),
159
+
160
+ editPath() {
161
+ return this.editable && this.selectedValue
162
+ ? getViewEditPath(this.schema, this.selectedValue, this.context)
163
+ : null
164
+ },
165
+
148
166
  groupByLabel() {
149
167
  return this.groupBy ? 'label' : null
150
168
  },
@@ -191,18 +191,18 @@
191
191
  cursor: pointer;
192
192
 
193
193
  &.dito-button-clear {
194
+ $self: &;
195
+
194
196
  width: $input-height;
195
197
  z-index: 1;
196
198
  background: $color-white;
197
199
  display: none;
198
200
 
199
- $button-clear: &;
200
-
201
201
  @at-root .dito-component:hover {
202
202
  // Support two levels of nesting inside .dito-component, used by TypeColor
203
- & > #{$button-clear},
204
- & > * > #{$button-clear},
205
- & > * > * > #{$button-clear} {
203
+ & > #{$self},
204
+ & > * > #{$self},
205
+ & > * > * > #{$self} {
206
206
  display: block;
207
207
  }
208
208
  }
@@ -98,10 +98,6 @@ export default DitoTypeComponent.register(
98
98
  .dito-button {
99
99
  $self: &;
100
100
 
101
- display: flex;
102
- align-items: center;
103
- justify-content: center;
104
-
105
101
  &__text {
106
102
  position: relative;
107
103
  min-width: min-content;
@@ -251,9 +251,11 @@ export default DitoTypeComponent.register('list', {
251
251
 
252
252
  getEditPath(item, index) {
253
253
  if (this.editable) {
254
- const path = getViewEditPath(this.schema, this.context) || this.path
255
254
  const id = this.getItemId(this.schema, item, index)
256
- return `${path}/${id}`
255
+ return (
256
+ getViewEditPath(this.schema, id, this.context) ||
257
+ `${this.path}/${id}`
258
+ )
257
259
  }
258
260
  return null
259
261
  },
@@ -5,37 +5,48 @@
5
5
  'dito-multiselect-multiple': multiple
6
6
  }`
7
7
  )
8
- VueMultiselect(
9
- ref="element"
10
- v-model="selectedOptions"
11
- :class="{ 'multiselect--show-highlight': showHighlight }"
12
- :showLabels="false"
13
- :placeholder="placeholder"
14
- tagPlaceholder="Press enter to add new tag"
15
- :options="populate && activeOptions || []"
16
- :customLabel="getLabelForOption"
17
- :trackBy="optionValue"
18
- :groupLabel="groupByLabel"
19
- :groupValues="groupByOptions"
20
- :multiple="multiple"
21
- :taggable="taggable"
22
- :searchable="searchable"
23
- :internalSearch="!searchFilter"
24
- :preserveSearch="!!searchFilter"
25
- :clearOnSelect="!searchFilter"
26
- :closeOnSelect="!stayOpen"
27
- :loading="isLoading"
28
- v-bind="attributes"
29
- @open="onOpen"
30
- @close="onClose"
31
- @tag="onAddTag"
32
- @search-change="onSearchChange"
33
- )
34
- button.dito-button-clear.dito-button-overlay(
35
- v-if="showClearButton"
36
- type="button"
37
- :disabled="disabled"
38
- @click="clear"
8
+ .dito-multiselect__inner
9
+ VueMultiselect(
10
+ ref="element"
11
+ v-model="selectedOptions"
12
+ :class="{ 'multiselect--show-highlight': showHighlight }"
13
+ :showLabels="false"
14
+ :placeholder="placeholder"
15
+ tagPlaceholder="Press enter to add new tag"
16
+ :options="populate && activeOptions || []"
17
+ :customLabel="getLabelForOption"
18
+ :trackBy="optionValue"
19
+ :groupLabel="groupByLabel"
20
+ :groupValues="groupByOptions"
21
+ :multiple="multiple"
22
+ :taggable="taggable"
23
+ :searchable="searchable"
24
+ :internalSearch="!searchFilter"
25
+ :preserveSearch="!!searchFilter"
26
+ :clearOnSelect="!searchFilter"
27
+ :closeOnSelect="!stayOpen"
28
+ :loading="isLoading"
29
+ v-bind="attributes"
30
+ @open="onOpen"
31
+ @close="onClose"
32
+ @tag="onAddTag"
33
+ @search-change="onSearchChange"
34
+ )
35
+ button.dito-button-clear.dito-button-overlay(
36
+ v-if="showClearButton"
37
+ type="button"
38
+ :disabled="disabled"
39
+ @click="clear"
40
+ )
41
+ DitoEditButtons(
42
+ v-if="editable"
43
+ :editable="editable"
44
+ :editPath="editPath"
45
+ :schema="schema"
46
+ :dataPath="dataPath"
47
+ :data="data"
48
+ :meta="meta"
49
+ :store="store"
39
50
  )
40
51
  </template>
41
52
 
@@ -218,12 +229,20 @@ $tag-padding: 3px;
218
229
  $tag-line-height: 1em;
219
230
 
220
231
  .dito-multiselect {
232
+ display: inline-flex;
221
233
  position: relative;
222
234
 
235
+ &__inner {
236
+ flex: 1;
237
+ position: relative;
238
+ }
239
+
240
+ // TODO: BEM
223
241
  &.dito-multiselect-single {
224
242
  --input-width: 100%;
225
243
  }
226
244
 
245
+ // TODO: BEM
227
246
  &.dito-multiselect-multiple {
228
247
  --input-width: auto;
229
248
  }
@@ -234,6 +253,10 @@ $tag-line-height: 1em;
234
253
  }
235
254
  }
236
255
 
256
+ .dito-edit-buttons {
257
+ margin-left: $form-spacing-half;
258
+ }
259
+
237
260
  .dito-button-clear {
238
261
  width: $spinner-width;
239
262
  }
@@ -1,40 +1,51 @@
1
1
  <template lang="pug">
2
2
  //- Nesting is needed to make an arrow appear over the select item:
3
3
  .dito-select
4
- select(
5
- :id="dataPath"
6
- ref="element"
7
- v-model="selectedValue"
8
- v-bind="attributes"
9
- @mousedown="populate = true"
10
- @focus="populate = true"
11
- )
12
- template(
13
- v-if="populate"
4
+ .dito-select__inner
5
+ select(
6
+ :id="dataPath"
7
+ ref="element"
8
+ v-model="selectedValue"
9
+ v-bind="attributes"
10
+ @mousedown="populate = true"
11
+ @focus="populate = true"
14
12
  )
15
13
  template(
16
- v-for="option in options"
14
+ v-if="populate"
17
15
  )
18
- optgroup(
19
- v-if="groupBy"
20
- :label="option[groupByLabel]"
16
+ template(
17
+ v-for="option in options"
21
18
  )
19
+ optgroup(
20
+ v-if="groupBy"
21
+ :label="option[groupByLabel]"
22
+ )
23
+ option(
24
+ v-for="opt in option[groupByOptions]"
25
+ :value="getValueForOption(opt)"
26
+ ) {{ getLabelForOption(opt) }}
22
27
  option(
23
- v-for="opt in option[groupByOptions]"
24
- :value="getValueForOption(opt)"
25
- ) {{ getLabelForOption(opt) }}
26
- option(
27
- v-else
28
- :value="getValueForOption(option)"
29
- ) {{ getLabelForOption(option) }}
30
- template(
31
- v-else-if="selectedOption"
28
+ v-else
29
+ :value="getValueForOption(option)"
30
+ ) {{ getLabelForOption(option) }}
31
+ template(
32
+ v-else-if="selectedOption"
33
+ )
34
+ option(:value="selectedValue") {{ getLabelForOption(selectedOption) }}
35
+ button.dito-button-clear.dito-button-overlay(
36
+ v-if="showClearButton"
37
+ :disabled="disabled"
38
+ @click="clear"
32
39
  )
33
- option(:value="selectedValue") {{ getLabelForOption(selectedOption) }}
34
- button.dito-button-clear.dito-button-overlay(
35
- v-if="showClearButton"
36
- :disabled="disabled"
37
- @click="clear"
40
+ DitoEditButtons(
41
+ v-if="editable"
42
+ :editable="editable"
43
+ :editPath="editPath"
44
+ :schema="schema"
45
+ :dataPath="dataPath"
46
+ :data="data"
47
+ :meta="meta"
48
+ :store="store"
38
49
  )
39
50
  </template>
40
51
 
@@ -65,12 +76,30 @@ export default DitoTypeComponent.register('select', {
65
76
  $select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
66
77
 
67
78
  .dito-select {
68
- display: inline-block;
79
+ display: inline-flex;
69
80
  position: relative;
70
81
 
71
82
  select {
72
83
  padding-right: $select-arrow-width;
73
84
  }
85
+
86
+ &__inner {
87
+ flex: 1;
88
+ position: relative;
89
+
90
+ &::after {
91
+ position: absolute;
92
+ @include arrow($select-arrow-size);
93
+
94
+ bottom: $select-arrow-bottom;
95
+ right: calc(#{$select-arrow-right} + #{$border-width});
96
+ }
97
+ }
98
+
99
+ .dito-edit-buttons {
100
+ margin-left: $form-spacing-half;
101
+ }
102
+
74
103
  // Handle .dito-width-fill separately due to required nesting of select:
75
104
  &.dito-width-fill {
76
105
  select {
@@ -78,14 +107,6 @@ $select-arrow-right: calc(($select-arrow-width - $select-arrow-size) / 2);
78
107
  }
79
108
  }
80
109
 
81
- &::after {
82
- position: absolute;
83
- @include arrow($select-arrow-size);
84
-
85
- bottom: $select-arrow-bottom;
86
- right: calc(#{$select-arrow-right} + #{$border-width});
87
- }
88
-
89
110
  &.dito-disabled::after {
90
111
  border-color: $border-color;
91
112
  }
@@ -416,13 +416,19 @@ export function getViewSchema(schema, context) {
416
416
  : null
417
417
  }
418
418
 
419
- export function getViewEditPath(schema, context) {
419
+ export function hasViewSchema(schema, context) {
420
+ return !!getViewSchema(schema, context)
421
+ }
422
+
423
+ export function getViewEditPath(schema, id, context) {
420
424
  const view = getViewSchema(schema, context)
421
- return view
422
- ? isSingleComponentView(view)
425
+ if (view) {
426
+ const path = isSingleComponentView(view)
423
427
  ? `/${view.path}`
424
428
  : `/${view.path}/${view.path}`
425
- : null
429
+ return `${path}/${id}`
430
+ }
431
+ return null
426
432
  }
427
433
 
428
434
  export function getFormSchemas(schema, context, modifyForm) {
@@ -595,7 +601,7 @@ export function computeValue(schema, data, name, dataPath, {
595
601
  const { compute } = schema
596
602
  if (compute) {
597
603
  const value = compute(
598
- DitoContext.get(component, {
604
+ new DitoContext(component, {
599
605
  schema,
600
606
  // Override value to prevent endless recursion through calling the
601
607
  // getter for `this.value` in `DitoContext`:
@@ -691,7 +697,7 @@ export function processData(schema, sourceSchema, data, dataPath, {
691
697
 
692
698
  // NOTE: We don't cache this context, since `value` is changing.
693
699
  const getContext = () =>
694
- DitoContext.get(component, {
700
+ new DitoContext(component, {
695
701
  schema,
696
702
  value,
697
703
  name,
@@ -782,7 +788,7 @@ export function processSchemaData(
782
788
  index !== null
783
789
  ? getDataPath(componentDataPath, index)
784
790
  : componentDataPath
785
- const context = DitoContext.get(options.component, {
791
+ const context = new DitoContext(options.component, {
786
792
  schema: componentSchema,
787
793
  data,
788
794
  value: item,