@ditojs/admin 2.7.3 → 2.7.5

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.7.3",
3
+ "version": "2.7.5",
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": "13bec1eda290997bdc10d110652180cdc9d3653b",
86
+ "gitHead": "d88c47b18f85103460099db95afb067c8c244253",
87
87
  "scripts": {
88
88
  "build": "vite build",
89
89
  "watch": "yarn build --mode 'development' --watch",
@@ -5,8 +5,8 @@
5
5
  )
6
6
  button.dito-button(
7
7
  type="button"
8
- :class="`dito-button-${verb}`"
9
- :title="labelize(verb)"
8
+ :disabled="disabled"
9
+ v-bind="getButtonAttributes(verb)"
10
10
  @mousedown.stop="onPulldownMouseDown()"
11
11
  ) {{ text }}
12
12
  ul.dito-pulldown(:class="{ 'dito-open': pulldown.open }")
@@ -14,17 +14,17 @@
14
14
  v-for="(form, type) in forms"
15
15
  )
16
16
  a(
17
- v-if="shouldRenderSchema(form)"
18
- v-show="shouldShow(form)"
17
+ v-if="isFormCreatable(form)"
18
+ v-show="shouldShowSchema(form)"
19
19
  :class="getFormClass(form, type)"
20
20
  @mousedown.stop="onPulldownMouseDown(type)"
21
21
  @mouseup="onPulldownMouseUp(type)"
22
22
  ) {{ getLabel(form) }}
23
23
  button.dito-button(
24
- v-else
24
+ v-else-if="isFormCreatable(forms.default)"
25
25
  :type="isInlined ? 'button' : 'submit'"
26
- :class="`dito-button-${verb}`"
27
- :title="labelize(verb)"
26
+ :disabled="disabled"
27
+ v-bind="getButtonAttributes(verb)"
28
28
  @click="createItem(forms.default)"
29
29
  ) {{ text }}
30
30
  </template>
@@ -42,7 +42,8 @@ export default DitoComponent.component('DitoCreateButton', {
42
42
  schema: { type: Object, required: true },
43
43
  path: { type: String, required: true },
44
44
  verb: { type: String, required: true },
45
- text: { type: String, default: null }
45
+ text: { type: String, default: null },
46
+ disabled: { type: Boolean, required: true }
46
47
  },
47
48
 
48
49
  computed: {
@@ -55,13 +56,23 @@ export default DitoComponent.component('DitoCreateButton', {
55
56
  },
56
57
 
57
58
  showPulldown() {
58
- return Object.keys(this.forms).length > 1 || !this.forms.default
59
+ const forms = Object.values(this.forms)
60
+ return (
61
+ (forms.length > 1 || !this.forms.default) &&
62
+ forms.some(this.isFormCreatable)
63
+ )
59
64
  }
60
65
  },
61
66
 
62
67
  methods: {
68
+ isFormCreatable(form) {
69
+ // Forms can be excluded from the list by providing `if: false` or
70
+ // `creatable: false`.
71
+ return form.creatable !== false && this.shouldRenderSchema(form)
72
+ },
73
+
63
74
  createItem(form, type = null) {
64
- if (this.shouldRenderSchema(form) && !this.shouldDisable(form)) {
75
+ if (this.isFormCreatable(form) && !this.shouldDisableSchema(form)) {
65
76
  if (this.isInlined) {
66
77
  this.sourceComponent.createItem(form, type)
67
78
  } else {
@@ -78,7 +89,7 @@ export default DitoComponent.component('DitoCreateButton', {
78
89
  getFormClass(form, type) {
79
90
  return {
80
91
  [`dito-type-${type}`]: true,
81
- 'dito-disabled': this.shouldDisable(form)
92
+ 'dito-disabled': this.shouldDisableSchema(form)
82
93
  }
83
94
  },
84
95
 
@@ -7,9 +7,7 @@
7
7
  :style="{ '--width': `${settings.width}px` }"
8
8
  @mouseup="onMouseUp"
9
9
  )
10
- UseFocusTrap.dito-dialog__focus-trap(
11
- :options="{ immediate: true, fallbackFocus: () => $refs.dialog }"
12
- )
10
+ UseFocusTrap.dito-dialog__focus-trap(:options="focusTrapOptions")
13
11
  form.dito-scroll-parent(
14
12
  @submit.prevent="submit"
15
13
  )
@@ -104,6 +102,14 @@ export default DitoComponent.component('DitoDialog', {
104
102
  )
105
103
  },
106
104
 
105
+ focusTrapOptions() {
106
+ return {
107
+ immediate: true,
108
+ fallbackFocus: () => this.$refs.dialog,
109
+ onDeactivate: this.cancel
110
+ }
111
+ },
112
+
107
113
  hasButtons() {
108
114
  return Object.keys(this.buttonSchemas).length > 0
109
115
  },
@@ -11,25 +11,27 @@ DitoButtons.dito-edit-buttons.dito-buttons-round(
11
11
  //- Firefox doesn't like <button> here, so use <a> instead:
12
12
  a.dito-button(
13
13
  v-if="hasDraggable"
14
+ :class="{ 'dito-disabled': disabled }"
14
15
  v-bind="getButtonAttributes(verbs.drag)"
15
16
  )
16
17
  RouterLink.dito-button(
17
18
  v-if="hasEditable"
18
- :class="{ 'dito-disabled': !editPath }"
19
+ :class="{ 'dito-disabled': disabled || !editPath }"
19
20
  :to="editPath ? { path: editPath } : {}"
20
21
  v-bind="getButtonAttributes(verbs.edit)"
21
22
  )
22
23
  DitoCreateButton(
23
24
  v-if="hasCreatable"
24
- :class="{ 'dito-disabled': !createPath }"
25
25
  :schema="schema"
26
26
  :path="createPath"
27
27
  :verb="verbs.create"
28
28
  :text="createButtonText"
29
+ :disabled="disabled || !createPath"
29
30
  )
30
31
  button.dito-button(
31
32
  v-if="hasDeletable"
32
33
  type="button"
34
+ :disabled="disabled || !isFormDeletable"
33
35
  v-bind="getButtonAttributes(verbs.delete)"
34
36
  @click="$emit('delete')"
35
37
  )
@@ -44,18 +46,19 @@ export default DitoComponent.component('DitoEditButtons', {
44
46
  emits: ['delete'],
45
47
 
46
48
  props: {
47
- draggable: { type: Boolean, default: false },
48
- editable: { type: Boolean, default: false },
49
- creatable: { type: Boolean, default: false },
50
- deletable: { type: Boolean, default: false },
51
- editPath: { type: String, default: null },
52
- createPath: { type: String, default: null },
53
49
  buttons: { type: Object, default: null },
54
50
  schema: { type: Object, required: true },
55
51
  dataPath: { type: String, required: true },
56
52
  data: { type: [Object, Array], default: null },
57
53
  meta: { type: Object, required: true },
58
- store: { type: Object, required: true }
54
+ store: { type: Object, required: true },
55
+ disabled: { type: Boolean, required: true },
56
+ draggable: { type: Boolean, default: false },
57
+ editable: { type: Boolean, default: false },
58
+ creatable: { type: Boolean, default: false },
59
+ deletable: { type: Boolean, default: false },
60
+ editPath: { type: String, default: null },
61
+ createPath: { type: String, default: null }
59
62
  },
60
63
 
61
64
  computed: {
@@ -79,6 +82,10 @@ export default DitoComponent.component('DitoEditButtons', {
79
82
  return this.hasOption('deletable')
80
83
  },
81
84
 
85
+ isFormDeletable() {
86
+ return this.schema.deletable !== false
87
+ },
88
+
82
89
  createButtonText() {
83
90
  return (
84
91
  // Allow schema to override create button through creatable object:
@@ -17,6 +17,14 @@
17
17
  :is="isNestedRoute ? 'div' : 'form'"
18
18
  @submit.prevent
19
19
  )
20
+ //- Prevent implicit submission of the form, for example when typing enter
21
+ //- in an input field.
22
+ //- https://stackoverflow.com/a/51507806
23
+ button(
24
+ v-show="false"
25
+ type="submit"
26
+ disabled
27
+ )
20
28
  DitoSchema(
21
29
  :schema="schema"
22
30
  :dataPath="dataPath"
@@ -37,14 +45,6 @@
37
45
  :store="store"
38
46
  :disabled="isLoading"
39
47
  )
40
- //- Prevent implicit submission of the form, for example when typing enter
41
- //- in an input field.
42
- //- https://stackoverflow.com/a/51507806
43
- button(
44
- v-show="false"
45
- type="submit"
46
- disabled
47
- )
48
48
  </template>
49
49
 
50
50
  <script>
@@ -475,12 +475,14 @@ export default DitoComponent.component('DitoSchema', {
475
475
  },
476
476
 
477
477
  repositionErrors() {
478
- // Force repositioning of error tooltips, as otherwise they
479
- // sometimes don't show up in the right place initially when
480
- // changing tabs
481
- const scrollParent = this.$refs.content.closest('.dito-scroll')
482
- scrollParent.scrollTop++
483
- scrollParent.scrollTop--
478
+ // Fire a fake scroll event to force the repositioning of error tooltips,
479
+ // as otherwise they sometimes don't show up in the right place initially
480
+ // when changing tabs.
481
+ const scrollContainer = this.$refs.content.closest('.dito-scroll')
482
+ const dispatch = () => scrollContainer.dispatchEvent(new Event('scroll'))
483
+ dispatch()
484
+ // This is required to handle `&--label-vertical` based layout changes.
485
+ setTimeout(dispatch, 0)
484
486
  },
485
487
 
486
488
  focus() {
@@ -19,15 +19,16 @@ DitoSchema.dito-schema-inlined(
19
19
  template(#edit-buttons)
20
20
  DitoEditButtons(
21
21
  v-if="deletable || draggable || editable"
22
- :deletable="deletable"
23
- :draggable="draggable"
24
- :editable="editable"
25
- :editPath="editPath"
26
22
  :schema="schema"
27
23
  :dataPath="dataPath"
28
24
  :data="data"
29
25
  :meta="meta"
30
26
  :store="store"
27
+ :disabled="disabled"
28
+ :deletable="deletable"
29
+ :draggable="draggable"
30
+ :editable="editable"
31
+ :editPath="editPath"
31
32
  @delete="$emit('delete')"
32
33
  )
33
34
  </template>
@@ -288,7 +288,7 @@ export default {
288
288
  return shouldRenderSchema(schema, this.context)
289
289
  },
290
290
 
291
- shouldShow(schema = null) {
291
+ shouldShowSchema(schema = null) {
292
292
  return this.getSchemaValue('visible', {
293
293
  type: Boolean,
294
294
  default: true,
@@ -296,7 +296,7 @@ export default {
296
296
  })
297
297
  },
298
298
 
299
- shouldDisable(schema = null) {
299
+ shouldDisableSchema(schema = null) {
300
300
  return this.getSchemaValue('disabled', {
301
301
  type: Boolean,
302
302
  default: false,
@@ -3,7 +3,7 @@ import ValidationMixin from './ValidationMixin.js'
3
3
  import { getSchemaAccessor } from '../utils/accessor.js'
4
4
  import { computeValue } from '../utils/schema.js'
5
5
  import { getItem, getParentItem } from '../utils/data.js'
6
- import { camelize } from '@ditojs/utils'
6
+ import { asArray, camelize } from '@ditojs/utils'
7
7
 
8
8
  // @vue/component
9
9
  export default {
@@ -251,9 +251,7 @@ export default {
251
251
  // @overridable
252
252
  async scrollIntoView() {
253
253
  await this.focusSchema()
254
- let { element = this } = this.$refs
255
- element = element.scrollIntoView ? element : element.$el
256
- element.scrollIntoView?.({
254
+ this.getFocusElement()?.scrollIntoView?.({
257
255
  behavior: 'smooth',
258
256
  block: 'center'
259
257
  })
@@ -261,16 +259,17 @@ export default {
261
259
 
262
260
  // @overridable
263
261
  focusElement() {
264
- let { element = this } = this.$refs
265
- element = element.focus ? element : element.$el
266
- element.focus?.()
262
+ this.getFocusElement()?.focus?.()
267
263
  },
268
264
 
269
265
  // @overridable
270
266
  blurElement() {
271
- let { element = this } = this.$refs
272
- element = element.blur ? element : element.$el
273
- element.blur?.()
267
+ this.getFocusElement()?.blur?.()
268
+ },
269
+
270
+ getFocusElement() {
271
+ const element = asArray(this.$refs.element)[0] ?? this
272
+ return element.$el ?? element
274
273
  },
275
274
 
276
275
  async focusSchema() {
@@ -107,15 +107,16 @@
107
107
  v-if="hasCellEditButtons"
108
108
  )
109
109
  DitoEditButtons(
110
- :deletable="deletable"
111
- :draggable="draggable"
112
- :editable="editable"
113
- :editPath="getEditPath(item, index)"
114
110
  :schema="getItemFormSchema(schema, item, context)"
115
111
  :dataPath="getDataPath(index)"
116
112
  :data="item"
117
113
  :meta="nestedMeta"
118
114
  :store="getItemStore(schema, item, index)"
115
+ :disabled="disabled || isLoading"
116
+ :deletable="deletable"
117
+ :draggable="draggable"
118
+ :editable="editable"
119
+ :editPath="getEditPath(item, index)"
119
120
  @delete="deleteItem(item, index)"
120
121
  )
121
122
  //- Render create buttons inside table when not in a single component view:
@@ -125,26 +126,28 @@
125
126
  tr
126
127
  td.dito-cell-edit-buttons(:colspan="numColumns")
127
128
  DitoEditButtons(
128
- :creatable="creatable"
129
- :createPath="path"
130
129
  :buttons="buttonSchemas"
131
130
  :schema="schema"
132
131
  :dataPath="dataPath"
133
132
  :data="listData"
134
133
  :meta="meta"
135
134
  :store="store"
135
+ :disabled="disabled || isLoading"
136
+ :creatable="creatable"
137
+ :createPath="path"
136
138
  )
137
139
  //- Render create buttons outside table when in a single component view:
138
140
  DitoEditButtons.dito-buttons-main.dito-buttons-large(
139
141
  v-if="hasListButtons && single"
140
- :creatable="creatable"
141
- :createPath="path"
142
142
  :buttons="buttonSchemas"
143
143
  :schema="schema"
144
144
  :dataPath="dataPath"
145
145
  :data="listData"
146
146
  :meta="meta"
147
147
  :store="store"
148
+ :disabled="disabled || isLoading"
149
+ :creatable="creatable"
150
+ :createPath="path"
148
151
  )
149
152
  </template>
150
153
 
@@ -40,13 +40,14 @@
40
40
  )
41
41
  DitoEditButtons(
42
42
  v-if="editable"
43
- :editable="editable"
44
- :editPath="editPath"
45
43
  :schema="schema"
46
44
  :dataPath="dataPath"
47
45
  :data="data"
48
46
  :meta="meta"
49
47
  :store="store"
48
+ :disabled="disabled"
49
+ :editable="editable"
50
+ :editPath="editPath"
50
51
  )
51
52
  </template>
52
53
 
@@ -36,11 +36,6 @@
36
36
  v-html="getItemLabel(schema, objectData)"
37
37
  )
38
38
  DitoEditButtons(
39
- :creatable="creatable"
40
- :deletable="objectData && deletable"
41
- :editable="objectData && editable"
42
- :createPath="path"
43
- :editPath="path"
44
39
  :buttons="buttonSchemas"
45
40
  :schema="schema"
46
41
  :dataPath="dataPath"
@@ -48,6 +43,12 @@
48
43
  :path="path"
49
44
  :meta="meta"
50
45
  :store="store"
46
+ :disabled="disabled || isLoading"
47
+ :creatable="creatable"
48
+ :deletable="objectData && deletable"
49
+ :editable="objectData && editable"
50
+ :createPath="path"
51
+ :editPath="path"
51
52
  @delete="deleteItem(objectData)"
52
53
  )
53
54
  </template>
@@ -39,13 +39,14 @@
39
39
  )
40
40
  DitoEditButtons(
41
41
  v-if="editable"
42
- :editable="editable"
43
- :editPath="editPath"
44
42
  :schema="schema"
45
43
  :dataPath="dataPath"
46
44
  :data="data"
47
45
  :meta="meta"
48
46
  :store="store"
47
+ :disabled="disabled"
48
+ :editable="editable"
49
+ :editPath="editPath"
49
50
  )
50
51
  </template>
51
52