@ditojs/admin 2.2.7-debug.5 → 2.2.8

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.
Files changed (37) hide show
  1. package/dist/dito-admin.es.js +652 -676
  2. package/dist/dito-admin.umd.js +4 -4
  3. package/dist/style.css +1 -1
  4. package/package.json +2 -2
  5. package/src/DitoTypeComponent.js +0 -1
  6. package/src/components/DitoButtons.vue +0 -1
  7. package/src/components/DitoContainer.vue +28 -13
  8. package/src/components/DitoDialog.vue +2 -1
  9. package/src/components/DitoForm.vue +4 -2
  10. package/src/components/DitoHeader.vue +2 -0
  11. package/src/components/DitoLabel.vue +0 -1
  12. package/src/components/DitoPane.vue +16 -3
  13. package/src/components/DitoPanel.vue +9 -4
  14. package/src/components/DitoRoot.vue +0 -9
  15. package/src/components/DitoSchema.vue +42 -48
  16. package/src/components/DitoSchemaInlined.vue +4 -7
  17. package/src/components/{DitoMenu.vue → DitoSidebar.vue} +2 -2
  18. package/src/components/DitoView.vue +3 -3
  19. package/src/components/index.js +1 -1
  20. package/src/mixins/DitoMixin.js +16 -8
  21. package/src/mixins/SourceMixin.js +1 -9
  22. package/src/mixins/TypeMixin.js +3 -6
  23. package/src/styles/_button.scss +1 -1
  24. package/src/types/DitoTypeCode.vue +0 -1
  25. package/src/types/DitoTypeComponent.vue +0 -1
  26. package/src/types/DitoTypeLabel.vue +1 -2
  27. package/src/types/DitoTypeList.vue +20 -8
  28. package/src/types/DitoTypeMarkup.vue +0 -2
  29. package/src/types/DitoTypeObject.vue +0 -2
  30. package/src/types/DitoTypePanel.vue +0 -1
  31. package/src/types/DitoTypeSection.vue +5 -2
  32. package/src/types/DitoTypeTextarea.vue +0 -1
  33. package/src/types/DitoTypeTreeList.vue +0 -2
  34. package/src/types/DitoTypeUpload.vue +0 -2
  35. package/src/utils/filter.js +0 -17
  36. package/src/utils/options.js +0 -1
  37. package/src/utils/schema.js +0 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/admin",
3
- "version": "2.2.7-debug.5",
3
+ "version": "2.2.8",
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",
@@ -82,7 +82,7 @@
82
82
  "vite": "^4.3.1"
83
83
  },
84
84
  "types": "types",
85
- "gitHead": "a7d0c07bd2b065bbd103e9bcd73ecaa91a1f58e8",
85
+ "gitHead": "6c520e0985b080c574f93fdee8b7f19d51a84140",
86
86
  "scripts": {
87
87
  "build": "vite build",
88
88
  "watch": "yarn build --mode 'development' --watch",
@@ -21,7 +21,6 @@ export default {
21
21
  generateLabel: true,
22
22
  excludeValue: false,
23
23
  ignoreMissingValue: null,
24
- alignBottom: true,
25
24
  omitPadding: false,
26
25
 
27
26
  component: DitoComponent.component,
@@ -14,7 +14,6 @@
14
14
  :meta="meta"
15
15
  :store="getChildStore(buttonSchema.name)"
16
16
  :disabled="disabled"
17
- :generateLabels="false"
18
17
  )
19
18
  template(
20
19
  v-for="vnode of $slots.default?.()"
@@ -31,7 +31,7 @@ import { isString, isNumber } from '@ditojs/utils'
31
31
  import DitoComponent from '../DitoComponent.js'
32
32
  import DitoContext from '../DitoContext.js'
33
33
  import { getSchemaAccessor } from '../utils/accessor.js'
34
- import { getTypeComponent, alignBottom, omitPadding } from '../utils/schema.js'
34
+ import { getTypeComponent, omitPadding } from '../utils/schema.js'
35
35
  import { parseFraction } from '../utils/math.js'
36
36
 
37
37
  // @vue/component
@@ -45,7 +45,7 @@ export default DitoComponent.component('DitoContainer', {
45
45
  single: { type: Boolean, default: false },
46
46
  nested: { type: Boolean, default: true },
47
47
  disabled: { type: Boolean, required: true },
48
- generateLabels: { type: Boolean, default: true }
48
+ generateLabels: { type: Boolean, default: false }
49
49
  },
50
50
 
51
51
  data() {
@@ -68,13 +68,25 @@ export default DitoComponent.component('DitoContainer', {
68
68
  return (
69
69
  label !== false && (
70
70
  !!label ||
71
- this.generateLabels && this.typeComponent?.generateLabel
71
+ this.generateLabels && (
72
+ this.typeComponent?.generateLabel ||
73
+ // If the component has no label but isn't full width, render an
74
+ // empty label for alignment with other components:
75
+ !this.isFullWidth
76
+ )
72
77
  )
73
78
  )
74
79
  },
75
80
 
76
81
  label() {
77
- return this.hasLabel ? this.getLabel(this.schema) : null
82
+ return this.hasLabel
83
+ ? this.getLabel(
84
+ this.schema,
85
+ // Pass an empty string in case we need an empty label, see
86
+ // `hasLabel()`:
87
+ this.typeComponent?.generateLabel ? this.schema.name : ''
88
+ ) || ''
89
+ : null
78
90
  },
79
91
 
80
92
  labelDataPath() {
@@ -82,6 +94,13 @@ export default DitoComponent.component('DitoContainer', {
82
94
  return this.nested ? this.dataPath : null
83
95
  },
84
96
 
97
+ isFullWidth() {
98
+ return (
99
+ !this.componentBasis.endsWith('%') ||
100
+ parseFloat(this.componentBasis) === 100
101
+ )
102
+ },
103
+
85
104
  componentWidth: getSchemaAccessor('width', {
86
105
  type: [String, Number],
87
106
  default() {
@@ -127,7 +146,6 @@ export default DitoComponent.component('DitoContainer', {
127
146
  return {
128
147
  [`${prefix}--single`]: this.single,
129
148
  [`${prefix}--has-label`]: this.hasLabel,
130
- [`${prefix}--align-bottom`]: alignBottom(this.schema),
131
149
  [`${prefix}--omit-padding`]: omitPadding(this.schema),
132
150
  ...(
133
151
  isString(containerClass)
@@ -166,11 +184,10 @@ export default DitoComponent.component('DitoContainer', {
166
184
  componentClass() {
167
185
  const basisIsAuto = this.componentBasis === 'auto'
168
186
  return {
169
- // TODO: BEM
187
+ // TODO: BEM?
170
188
  'dito-single': this.single,
171
189
  'dito-disabled': this.componentDisabled,
172
190
  'dito-width-fill': !basisIsAuto || this.componentWidth === 'fill',
173
- 'dito-width-auto': basisIsAuto,
174
191
  'dito-has-errors': !!this.errors
175
192
  }
176
193
  }
@@ -204,8 +221,10 @@ export default DitoComponent.component('DitoContainer', {
204
221
  padding: 0;
205
222
  }
206
223
 
207
- &--align-bottom {
208
- justify-content: end; // To align components with and without labels.
224
+ &--single {
225
+ height: 100%; // So that list buttons can be sticky at the bottom;
226
+ // Just like on DitoPane, clear settings from above.
227
+ padding: 0;
209
228
  }
210
229
 
211
230
  &--omit-padding {
@@ -215,10 +234,6 @@ export default DitoComponent.component('DitoContainer', {
215
234
  margin: $form-spacing $form-spacing-half 0;
216
235
  }
217
236
  }
218
-
219
- &--single {
220
- height: 100%; // So that list buttons can be sticky at the bottom;
221
- }
222
237
  }
223
238
 
224
239
  // NOTE: This is not nested inside `.dito-container` so that other
@@ -13,9 +13,10 @@
13
13
  form.dito-scroll-parent(
14
14
  @submit.prevent="submit"
15
15
  )
16
- DitoSchema.dito-scroll(
16
+ DitoSchema(
17
17
  :schema="schema"
18
18
  :data="dialogData"
19
+ scrollable
19
20
  )
20
21
  template(#buttons)
21
22
  DitoButtons.dito-buttons-large(
@@ -12,7 +12,7 @@
12
12
  v-show="!isActive"
13
13
  )
14
14
  //- Use a <div> for inlined forms, as we shouldn't nest actual <form> tags.
15
- component.dito-scroll(
15
+ component.dito-scroll-parent(
16
16
  v-show="isActive"
17
17
  :is="isNestedRoute ? 'div' : 'form'"
18
18
  @submit.prevent
@@ -24,7 +24,9 @@
24
24
  :meta="meta"
25
25
  :store="store"
26
26
  :disabled="isLoading"
27
- :menuHeader="true"
27
+ scrollable
28
+ headerInMenu
29
+ generateLabels
28
30
  )
29
31
  template(#buttons)
30
32
  DitoButtons.dito-buttons-round.dito-buttons-main.dito-buttons-large(
@@ -19,6 +19,8 @@ nav.dito-header
19
19
  DitoSpinner(
20
20
  v-if="isLoading"
21
21
  )
22
+ //- Teleport target for `.dito-schema-header`:
23
+ .dito-menu
22
24
  slot
23
25
  </template>
24
26
 
@@ -1,6 +1,5 @@
1
1
  <template lang="pug">
2
2
  component.dito-label(
3
- v-if="text || collapsible"
4
3
  :is="tag"
5
4
  v-bind="attributes"
6
5
  :class="{ 'dito-active': isActive }"
@@ -3,6 +3,9 @@
3
3
  .dito-pane(
4
4
  v-if="isPopulated && componentSchemas.length > 0"
5
5
  v-show="visible"
6
+ :class=`{
7
+ 'dito-pane--single': isSingleComponent
8
+ }`
6
9
  )
7
10
  template(
8
11
  v-for=`{
@@ -57,7 +60,7 @@ export default DitoComponent.component('DitoPane', {
57
60
  single: { type: Boolean, default: false },
58
61
  visible: { type: Boolean, default: true },
59
62
  disabled: { type: Boolean, default: false },
60
- generateLabels: { type: Boolean, default: true }
63
+ generateLabels: { type: Boolean, default: false }
61
64
  },
62
65
 
63
66
  computed: {
@@ -141,24 +144,34 @@ export default DitoComponent.component('DitoPane', {
141
144
  @import '../styles/_imports';
142
145
 
143
146
  .dito-pane {
147
+ $max-width: $content-width + 2 * $content-padding;
148
+
144
149
  display: flex;
145
150
  position: relative;
146
151
  flex-flow: row wrap;
147
152
  align-content: flex-start;
148
153
  align-items: baseline;
154
+ padding: $content-padding;
149
155
  // Remove the padding added by `.dito-container` inside `.dito-pane`:
150
156
  margin: (-$form-spacing) (-$form-spacing-half);
151
157
  // Add removed horizontal margin again to max-width:
152
- max-width: $content-width + 2 * $form-spacing-half;
158
+ max-width: $max-width + 2 * $form-spacing-half;
153
159
  // Use `flex: 0%` for all `.dito-pane` except `.dito-pane-main`,
154
160
  // so that the `.dito-buttons-main` can be moved all the way to the bottom.
155
161
  flex: 0%;
156
162
 
163
+ &--single {
164
+ // Clear settings from above.
165
+ margin: 0;
166
+ max-width: $max-width;
167
+ }
168
+
157
169
  &.dito-pane-main {
158
170
  flex: 100%;
171
+ margin-bottom: 0; // For vertical scroll size.
159
172
  }
160
173
 
161
- .dito-schema-header:not(.dito-schema-menu-header) + & {
174
+ .dito-schema-header + & {
162
175
  // Clear top-margin if the components are preceded by a schema header.
163
176
  margin-top: 0;
164
177
  }
@@ -13,6 +13,7 @@ component.dito-panel(
13
13
  :store="store"
14
14
  :disabled="disabled"
15
15
  :hasOwnData="hasOwnData"
16
+ generateLabels
16
17
  )
17
18
  template(#before)
18
19
  h2.dito-panel__header(:class="{ 'dito-panel__header--sticky': sticky }")
@@ -163,7 +164,9 @@ export default DitoComponent.component('DitoPanel', {
163
164
  @import '../styles/_imports';
164
165
 
165
166
  .dito-panel {
166
- padding-bottom: $content-padding;
167
+ & + & {
168
+ margin-top: $content-padding;
169
+ }
167
170
 
168
171
  &__header {
169
172
  display: block;
@@ -180,7 +183,7 @@ export default DitoComponent.component('DitoPanel', {
180
183
  $form-spacing;
181
184
 
182
185
  position: sticky;
183
- top: $content-padding;
186
+ top: 0;
184
187
  margin-bottom: $margin;
185
188
  z-index: 1;
186
189
 
@@ -218,7 +221,9 @@ export default DitoComponent.component('DitoPanel', {
218
221
  border-bottom-right-radius: $border-radius;
219
222
 
220
223
  > .dito-schema-content {
221
- padding: $form-spacing-half $form-spacing;
224
+ > .dito-pane {
225
+ padding: $form-spacing-half $form-spacing;
226
+ }
222
227
 
223
228
  .dito-container {
224
229
  padding: $form-spacing-half;
@@ -232,7 +237,7 @@ export default DitoComponent.component('DitoPanel', {
232
237
  > .dito-buttons {
233
238
  --button-margin: #{$form-spacing};
234
239
 
235
- padding: $form-spacing-half 0;
240
+ padding: 0 $form-spacing $form-spacing;
236
241
 
237
242
  .dito-container {
238
243
  padding: 0;
@@ -369,15 +369,6 @@ function addRoutes(router, routes) {
369
369
  .dito-root {
370
370
  .dito-page {
371
371
  background: $content-color-background;
372
- // The root-level views and forms may have a `.dito-schema-header` that
373
- // should appear layered over `.dito-menu`, while having `overlay: hidden`
374
- // set by `.dito-scroll-parent` to delegate scrolling to `.dito-scroll`.
375
- // In order to not have the header clipped, adjust the top here:
376
- > .dito-form,
377
- > .dito-view {
378
- margin-top: -$menu-height;
379
- padding-top: $menu-height;
380
- }
381
372
  }
382
373
  }
383
374
  </style>
@@ -3,35 +3,39 @@ slot(name="before")
3
3
  .dito-schema(
4
4
  v-bind="$attrs"
5
5
  )
6
- .dito-schema-content
7
- .dito-schema-header(
8
- v-if="hasLabel || hasTabs || clipboard"
9
- :class="{ 'dito-schema-menu-header': menuHeader }"
6
+ .dito-schema-content(:class="{ 'dito-scroll': scrollable }")
7
+ Teleport(
8
+ to=".dito-menu"
9
+ :disabled="!headerInMenu"
10
10
  )
11
- DitoLabel(
12
- v-if="hasLabel"
13
- :label="label"
14
- :dataPath="dataPath"
15
- :collapsible="collapsible"
16
- :collapsed="!opened"
17
- @expand="onExpand"
11
+ .dito-schema-header(
12
+ v-if="hasLabel || hasTabs || clipboard"
13
+ :class="{ 'dito-schema-header--menu': headerInMenu }"
18
14
  )
19
- //- Pass edit-buttons through to dito-label's own edit-buttons slot:
20
- template(
21
- v-if="inlined"
22
- #edit-buttons
15
+ DitoLabel(
16
+ v-if="hasLabel"
17
+ :label="label"
18
+ :dataPath="dataPath"
19
+ :collapsible="collapsible"
20
+ :collapsed="!opened"
21
+ @expand="onExpand"
22
+ )
23
+ //- Pass edit-buttons through to dito-label's own edit-buttons slot:
24
+ template(
25
+ v-if="inlined"
26
+ #edit-buttons
27
+ )
28
+ slot(name="edit-buttons")
29
+ DitoTabs(
30
+ v-if="tabs"
31
+ :tabs="tabs"
32
+ :selectedTab="selectedTab"
33
+ )
34
+ DitoClipboard(
35
+ :clipboard="clipboard"
36
+ :dataPath="dataPath"
37
+ :data="data"
23
38
  )
24
- slot(name="edit-buttons")
25
- DitoTabs(
26
- v-if="tabs"
27
- :tabs="tabs"
28
- :selectedTab="selectedTab"
29
- )
30
- DitoClipboard(
31
- :clipboard="clipboard"
32
- :dataPath="dataPath"
33
- :data="data"
34
- )
35
39
  template(
36
40
  v-if="hasTabs"
37
41
  )
@@ -78,6 +82,7 @@ slot(name="before")
78
82
  v-else-if="isPopulated"
79
83
  )
80
84
  DitoPanels(
85
+ :class="{ 'dito-scroll': scrollable }"
81
86
  :panels="panelEntries"
82
87
  :data="data"
83
88
  :meta="meta"
@@ -135,9 +140,10 @@ export default DitoComponent.component('DitoSchema', {
135
140
  disabled: { type: Boolean, default: false },
136
141
  collapsed: { type: Boolean, default: false },
137
142
  collapsible: { type: Boolean, default: false },
138
- generateLabels: { type: Boolean, default: true },
143
+ scrollable: { type: Boolean, default: false },
139
144
  hasOwnData: { type: Boolean, default: false },
140
- menuHeader: { type: Boolean, default: false }
145
+ headerInMenu: { type: Boolean, default: false },
146
+ generateLabels: { type: Boolean, default: false }
141
147
  },
142
148
 
143
149
  data() {
@@ -330,16 +336,6 @@ export default DitoComponent.component('DitoSchema', {
330
336
  }
331
337
  },
332
338
 
333
- watch: {
334
- schema() {
335
- console.log('DitoSchema: schema changed', this.dataPath)
336
- },
337
-
338
- data() {
339
- console.log('DitoSchema: data changed', this.dataPath)
340
- }
341
- },
342
-
343
339
  created() {
344
340
  this._register(true)
345
341
  this.setupSchemaFields()
@@ -711,8 +707,7 @@ export default DitoComponent.component('DitoSchema', {
711
707
  grid-row-end: none;
712
708
  }
713
709
 
714
- max-width: $content-width;
715
- padding: $content-padding;
710
+ max-width: $content-width + 2 * $content-padding;
716
711
  }
717
712
 
718
713
  > .dito-buttons,
@@ -740,6 +735,11 @@ export default DitoComponent.component('DitoSchema', {
740
735
  margin: $content-padding $form-spacing-half $form-spacing-half;
741
736
  }
742
737
  }
738
+
739
+ .dito-pane-main + .dito-buttons-main {
740
+ // Needed forms with sticky main buttons.
741
+ margin-bottom: 0;
742
+ }
743
743
  }
744
744
 
745
745
  .dito-schema-header {
@@ -762,8 +762,8 @@ export default DitoComponent.component('DitoSchema', {
762
762
  }
763
763
  }
764
764
 
765
- &.dito-schema-menu-header {
766
- // Bring the tabs up to the menu.
765
+ &--menu {
766
+ // Align the tabs on top of to the header menu.
767
767
  position: absolute;
768
768
  height: $menu-height;
769
769
  padding: 0 $menu-padding-hor;
@@ -783,11 +783,5 @@ export default DitoComponent.component('DitoSchema', {
783
783
  font-size: $menu-font-size;
784
784
  }
785
785
  }
786
-
787
- button.dito-label {
788
- width: 100%;
789
- // Catch all clicks, even when it would be partially covered by schema.
790
- z-index: 1;
791
- }
792
786
  }
793
787
  </style>
@@ -1,5 +1,6 @@
1
1
  <template lang="pug">
2
2
  DitoSchema.dito-schema-inlined(
3
+ :class="{ 'dito-schema-compact': isCompact }"
3
4
  :schema="schema"
4
5
  :dataPath="dataPath"
5
6
  :data="data"
@@ -11,7 +12,6 @@ DitoSchema.dito-schema-inlined(
11
12
  :collapsed="collapsed"
12
13
  :collapsible="collapsible"
13
14
  :generateLabels="!isCompact"
14
- :class="{ 'dito-schema-compact': isCompact }"
15
15
  )
16
16
  //- Render dito-edit-buttons for inlined schemas separately from all
17
17
  //- others in `TypeList` as a scope, for better handling of layout.
@@ -71,8 +71,6 @@ export default DitoComponent.component('DitoSchemaInlined', {
71
71
 
72
72
  .dito-schema-inlined {
73
73
  > .dito-schema-content {
74
- padding: 0;
75
-
76
74
  > .dito-schema-header {
77
75
  // Change spacing so .dito-label covers the full .dito-schema-header.
78
76
  margin: -$form-spacing;
@@ -90,11 +88,10 @@ export default DitoComponent.component('DitoSchemaInlined', {
90
88
  // .dito-schema-content, due to grid-template-rows: min-content
91
89
  min-height: 2em;
92
90
  }
91
+ }
93
92
 
94
- & + .dito-pane {
95
- // Needed for transition-height in DitoSchema:
96
- min-height: $form-spacing;
97
- }
93
+ > .dito-pane {
94
+ padding: 0;
98
95
  }
99
96
  }
100
97
  }
@@ -1,5 +1,5 @@
1
1
  <template lang="pug">
2
- nav.dito-menu.dito-scroll-parent
2
+ nav.dito-sidebar.dito-scroll-parent
3
3
  h1 {{ appState.title }}
4
4
  ul.dito-scroll
5
5
  li(
@@ -34,7 +34,7 @@ export default DitoComponent.component('DitoMenu', {
34
34
  <style lang="scss">
35
35
  @import '../styles/_imports';
36
36
 
37
- .dito-menu {
37
+ .dito-sidebar {
38
38
  flex: initial;
39
39
  font-size: $menu-font-size;
40
40
  white-space: nowrap;
@@ -14,14 +14,14 @@ template(
14
14
  v-else-if="shouldRender(viewSchema)"
15
15
  :data-resource="sourceSchema.path"
16
16
  )
17
- DitoSchema.dito-scroll(
17
+ DitoSchema(
18
18
  :schema="viewSchema"
19
19
  :data="data"
20
20
  :meta="meta"
21
21
  :store="getChildStore(name)"
22
22
  :disabled="isLoading"
23
- :generateLabels="false"
24
- :menuHeader="true"
23
+ scrollable
24
+ headerInMenu
25
25
  )
26
26
  </template>
27
27
 
@@ -4,7 +4,7 @@
4
4
  // convention is in order of encountered hierarchy in the DOM.
5
5
 
6
6
  export { default as DitoRoot } from './DitoRoot.vue'
7
- export { default as DitoMenu } from './DitoMenu.vue'
7
+ export { default as DitoSidebar } from './DitoSidebar.vue'
8
8
  export { default as DitoHeader } from './DitoHeader.vue'
9
9
  export { default as DitoAccount } from './DitoAccount.vue'
10
10
  export { default as DitoDialog } from './DitoDialog.vue'
@@ -15,7 +15,7 @@ import DitoContext from '../DitoContext.js'
15
15
  import EmitterMixin from './EmitterMixin.js'
16
16
  import { isMatchingType, convertType } from '../utils/type.js'
17
17
  import { getResource, getMemberResource } from '../utils/resource.js'
18
- import { reactive } from 'vue'
18
+ import { computed, reactive } from 'vue'
19
19
 
20
20
  // @vue/component
21
21
  export default {
@@ -243,7 +243,7 @@ export default {
243
243
  getLabel(schema, name) {
244
244
  return schema
245
245
  ? this.getSchemaValue('label', { type: String, schema }) ||
246
- labelize(name || schema.name)
246
+ labelize(name ?? schema.name)
247
247
  : labelize(name) || ''
248
248
  },
249
249
 
@@ -433,17 +433,25 @@ export default {
433
433
  },
434
434
 
435
435
  setupComputed() {
436
- for (const [key, value] of Object.entries(this.schema.computed || {})) {
437
- const accessor = isFunction(value)
438
- ? { get: value }
439
- : isObject(value) && isFunction(value.get)
440
- ? value
436
+ const getComputedAccessor = ({ get, set }) => {
437
+ const getter = computed(() => get.call(this))
438
+ return {
439
+ get: () => getter.value,
440
+ set: set ? value => set.call(this, value) : undefined
441
+ }
442
+ }
443
+
444
+ for (const [key, item] of Object.entries(this.schema.computed || {})) {
445
+ const accessor = isFunction(item)
446
+ ? getComputedAccessor({ get: item })
447
+ : isObject(item) && isFunction(item.get)
448
+ ? getComputedAccessor(item)
441
449
  : null
442
450
  if (accessor) {
443
451
  Object.defineProperty(this, key, accessor)
444
452
  } else {
445
453
  console.error(
446
- `Invalid computed property definition: ${key}: ${value}`
454
+ `Invalid computed property definition: ${key}: ${item}`
447
455
  )
448
456
  }
449
457
  }
@@ -3,6 +3,7 @@ import ResourceMixin from './ResourceMixin.js'
3
3
  import SchemaParentMixin from '../mixins/SchemaParentMixin.js'
4
4
  import { getSchemaAccessor, getStoreAccessor } from '../utils/accessor.js'
5
5
  import { getMemberResource } from '../utils/resource.js'
6
+ import { replaceRoute } from '../utils/route.js'
6
7
  import {
7
8
  processRouteSchema,
8
9
  processForms,
@@ -25,7 +26,6 @@ import {
25
26
  parseDataPath,
26
27
  normalizeDataPath
27
28
  } from '@ditojs/utils'
28
- import { replaceRoute } from '../utils/route.js'
29
29
 
30
30
  // @vue/component
31
31
  export default {
@@ -44,7 +44,6 @@ export default {
44
44
  data() {
45
45
  return {
46
46
  wrappedPrimitives: null,
47
- ignoreRouteChange: false,
48
47
  unwrappingPrimitives: false
49
48
  }
50
49
  },
@@ -178,9 +177,6 @@ export default {
178
177
  ...query
179
178
  }
180
179
  if (!equals(query, this.$route.query)) {
181
- // Tell the `$route` watcher to ignore the changed triggered here:
182
- // this.ignoreRouteChange = true
183
- // this.$router.replace({ query, hash: this.$route.hash })
184
180
  // Change the route query parameters, but don't trigger a route
185
181
  // change, as that would cause the list to reload.
186
182
  replaceRoute({ query })
@@ -318,10 +314,6 @@ export default {
318
314
 
319
315
  watch: {
320
316
  $route(to, from) {
321
- if (this.ignoreRouteChange) {
322
- this.ignoreRouteChange = false
323
- return
324
- }
325
317
  if (from.path === to.path && from.hash === to.hash) {
326
318
  // Paths and hashes remain the same, so only queries have changed.
327
319
  // Update filter and reload data without clearing.
@@ -69,6 +69,7 @@ export default {
69
69
  : value
70
70
  // eslint-disable-next-line vue/no-mutating-props
71
71
  this.data[this.name] = this.parsedValue
72
+ this.changedValue = undefined
72
73
  }
73
74
  },
74
75
 
@@ -277,6 +278,7 @@ export default {
277
278
 
278
279
  clear() {
279
280
  this.value = null
281
+ this.changedValue = undefined
280
282
  this.onChange()
281
283
  },
282
284
 
@@ -293,7 +295,6 @@ export default {
293
295
  },
294
296
 
295
297
  onInput() {
296
- console.log('onInput()', this.name)
297
298
  this.markDirty()
298
299
  this.emitEvent('input')
299
300
  },
@@ -306,14 +307,10 @@ export default {
306
307
  // For some odd reason, the native change event now sometimes fires
307
308
  // twice on Vue3. Filter out second call.
308
309
  // TODO: Investigate why this happens, and if it's a bug in Vue3.
309
- if (value === this.changedValue) {
310
- console.log('onChange() double', this.name)
311
- return
312
- }
310
+ if (value === this.changedValue) return
313
311
  this.changedValue = value
314
312
  }
315
313
 
316
- console.log('onChange()', this.name, value)
317
314
  this.markDirty()
318
315
  this.emitEvent('change', {
319
316
  // Prevent endless parse recursion: