@ditojs/admin 2.6.6 → 2.6.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ditojs/admin",
3
- "version": "2.6.6",
3
+ "version": "2.6.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",
@@ -83,7 +83,7 @@
83
83
  "vite": "^4.3.4"
84
84
  },
85
85
  "types": "types",
86
- "gitHead": "cc88d57c87cb03764f8ea351a9447f5911e64a80",
86
+ "gitHead": "6c09a5f0fe96aeadf73ca07daa427e39a7f1462d",
87
87
  "scripts": {
88
88
  "build": "vite build",
89
89
  "watch": "yarn build --mode 'development' --watch",
@@ -24,6 +24,7 @@
24
24
  :single="single"
25
25
  :nested="nested"
26
26
  :disabled="componentDisabled"
27
+ :accumulatedBasis="combinedBasis"
27
28
  @errors="onErrors"
28
29
  )
29
30
  DitoErrors(:errors="errors")
@@ -49,7 +50,8 @@ export default DitoComponent.component('DitoContainer', {
49
50
  nested: { type: Boolean, default: true },
50
51
  disabled: { type: Boolean, required: true },
51
52
  generateLabels: { type: Boolean, default: false },
52
- verticalLabels: { type: Boolean, default: false }
53
+ verticalLabels: { type: Boolean, default: false },
54
+ accumulatedBasis: { type: Number, default: null }
53
55
  },
54
56
 
55
57
  data() {
@@ -140,14 +142,20 @@ export default DitoComponent.component('DitoContainer', {
140
142
  flexBasis() {
141
143
  const width = this.width
142
144
  // 'auto' = no fitting:
143
- const basis = [null, 'auto', 'fill'].includes(width)
145
+ return [null, 'auto', 'fill'].includes(width)
144
146
  ? 'auto'
145
147
  : /%$/.test(width)
146
- ? parseFloat(width) // percentage
148
+ ? parseFloat(width) / 100 // percentage -> fraction
147
149
  : /[a-z]/.test(width)
148
150
  ? width // native units
149
- : parseFraction(width) * 100 // fraction
150
- return isNumber(basis) ? `${basis}%` : basis
151
+ : parseFraction(width) // fraction
152
+ },
153
+
154
+ combinedBasis() {
155
+ const { accumulatedBasis, flexBasis } = this
156
+ return isNumber(accumulatedBasis) && isNumber(flexBasis)
157
+ ? accumulatedBasis * flexBasis
158
+ : null
151
159
  },
152
160
 
153
161
  containerClass() {
@@ -166,10 +174,15 @@ export default DitoComponent.component('DitoContainer', {
166
174
  },
167
175
 
168
176
  containerStyle() {
177
+ const { flexBasis, combinedBasis } = this
169
178
  return {
170
179
  '--grow': this.flexGrow ? 1 : 0,
171
180
  '--shrink': this.flexShrink ? 1 : 0,
172
- '--basis': this.flexBasis
181
+ '--basis': isNumber(flexBasis) ? `${flexBasis * 100}%` : flexBasis,
182
+ '--basis-mobile':
183
+ isNumber(combinedBasis) && combinedBasis <= 0.25
184
+ ? `${flexBasis * 200}%`
185
+ : null
173
186
  }
174
187
  },
175
188
 
@@ -215,30 +228,27 @@ export default DitoComponent.component('DitoContainer', {
215
228
  padding: $form-spacing $form-spacing-half;
216
229
 
217
230
  .dito-page .dito-pane > & {
218
- @container (width < #{$content-width}) {
219
- flex-grow: 1;
220
- }
221
-
222
231
  @container (width < #{calc($content-width * 0.8)}) {
223
- &:not(:has(> .dito-list, > .dito-object)) {
224
- flex-basis: calc(var(--basis) * 1.5);
225
- }
232
+ flex-grow: 1;
233
+ flex-basis: var(--basis-mobile, var(--basis));
234
+ // DEBUG: background: yellow;
226
235
  }
227
236
 
228
237
  @container (width < #{calc($content-width * 0.6)}) {
229
- &:not(:has(> .dito-list, > .dito-object)) {
230
- flex-basis: calc(var(--basis) * 2);
231
- }
238
+ flex-basis: calc(2 * var(--basis));
239
+ // DEBUG: background: orange;
232
240
  }
233
241
  }
234
242
 
235
243
  .dito-sidebar .dito-pane > & {
236
244
  @container (width < #{$sidebar-max-width}) {
237
245
  flex-grow: 1;
246
+ // DEBUG: background: yellow;
238
247
  }
239
248
 
240
249
  @container (width < #{calc($sidebar-max-width * 0.6)}) {
241
- flex-basis: calc(var(--basis) * 2);
250
+ flex-basis: calc(2 * var(--basis));
251
+ // DEBUG: background: orange;
242
252
  }
243
253
  }
244
254
 
@@ -112,12 +112,13 @@ export default DitoComponent.component('DitoHeader', {
112
112
  a {
113
113
  position: relative;
114
114
  display: block;
115
- padding-right: 0.4em;
116
115
 
117
116
  $angle: 33deg;
118
117
 
119
118
  &:hover {
120
- color: #999999;
119
+ span {
120
+ color: $color-light;
121
+ }
121
122
  }
122
123
 
123
124
  &::before,
@@ -125,9 +126,10 @@ export default DitoComponent.component('DitoHeader', {
125
126
  position: absolute;
126
127
  content: '';
127
128
  width: 1px;
128
- height: 1.2em;
129
- right: -1px;
130
- background: $color-dark;
129
+ height: 0.75em;
130
+ right: -0.25em;
131
+ background: $color-white;
132
+ opacity: 0.5;
131
133
  }
132
134
 
133
135
  &::before {
@@ -18,6 +18,7 @@ ul.dito-menu(
18
18
  v-if="item.items"
19
19
  :class="getItemClass(item, 'dito-sub-menu')"
20
20
  :items="item.items"
21
+ :path="getItemPath(item, false)"
21
22
  )
22
23
  </template>
23
24
 
@@ -30,6 +31,10 @@ export default DitoComponent.component('DitoMenu', {
30
31
  items: {
31
32
  type: [Object, Array],
32
33
  default: () => []
34
+ },
35
+ path: {
36
+ type: String,
37
+ default: ''
33
38
  }
34
39
  },
35
40
 
@@ -53,28 +58,27 @@ export default DitoComponent.component('DitoMenu', {
53
58
  }
54
59
  },
55
60
 
56
- getItemPath(item) {
57
- return item?.path
58
- ? `/${item.path}`
59
- : item.items
60
- ? this.getItemPath(Object.values(item.items)[0])
61
- : null
61
+ getItemPath(item, firstChild) {
62
+ const path = item.path ? `${this.path}/${item.path}` : null
63
+ return firstChild && path && item.items
64
+ ? `${path}${this.getItemPath(Object.values(item.items)[0], false)}`
65
+ : path
62
66
  },
63
67
 
64
68
  getItemHref(item) {
65
- const path = this.getItemPath(item)
69
+ const path = this.getItemPath(item, true)
66
70
  return path ? this.$router.resolve(path).href : null
67
71
  },
68
72
 
69
73
  isActiveItem(item) {
70
74
  return (
71
- this.$route.path.startsWith(this.getItemPath(item)) ||
75
+ this.$route.path.startsWith(this.getItemPath(item, false)) ||
72
76
  item.items && Object.values(item.items).some(this.isActiveItem)
73
77
  )
74
78
  },
75
79
 
76
80
  onClickItem(item) {
77
- const path = this.getItemPath(item)
81
+ const path = this.getItemPath(item, true)
78
82
  if (path) {
79
83
  this.$router.push({ path, force: true })
80
84
  }
@@ -33,6 +33,7 @@
33
33
  :disabled="disabled"
34
34
  :generateLabels="generateLabels"
35
35
  :verticalLabels="isInLabeledRow(index)"
36
+ :accumulatedBasis="accumulatedBasis"
36
37
  )
37
38
  .dito-break(
38
39
  v-if="schema.break === 'after'"
@@ -62,7 +63,8 @@ export default DitoComponent.component('DitoPane', {
62
63
  single: { type: Boolean, default: false },
63
64
  visible: { type: Boolean, default: true },
64
65
  disabled: { type: Boolean, default: false },
65
- generateLabels: { type: Boolean, default: false }
66
+ generateLabels: { type: Boolean, default: false },
67
+ accumulatedBasis: { type: Number, default: null }
66
68
  },
67
69
 
68
70
  data() {
@@ -223,22 +223,27 @@ export default DitoComponent.component('DitoPanel', {
223
223
 
224
224
  > .dito-schema-content {
225
225
  > .dito-pane {
226
- padding: $form-spacing-half $form-spacing;
226
+ padding: (2 * $form-spacing - $input-padding-ver)
227
+ (2 * $form-spacing - $input-padding-hor);
228
+ }
227
229
 
228
- > .dito-container {
229
- padding: $form-spacing-half;
230
- }
230
+ .dito-label {
231
+ margin: $form-spacing 0;
232
+ }
233
+
234
+ .dito-container {
235
+ padding: $form-spacing-half;
231
236
  }
232
237
 
233
238
  .dito-object {
234
- border: 0;
239
+ border: none;
235
240
  padding: 0;
236
241
  }
237
242
 
238
243
  > .dito-buttons {
239
244
  --button-margin: #{$form-spacing};
240
245
 
241
- padding: 0 $form-spacing $form-spacing;
246
+ padding: $form-spacing;
242
247
 
243
248
  .dito-container {
244
249
  padding: 0;
@@ -251,10 +256,6 @@ export default DitoComponent.component('DitoPanel', {
251
256
  font-weight: normal;
252
257
  }
253
258
  }
254
-
255
- .dito-pane {
256
- margin: 0 (-$form-spacing-half);
257
- }
258
259
  }
259
260
  }
260
261
  </style>
@@ -56,6 +56,7 @@ slot(name="before")
56
56
  :single="!inlined && !hasMainPane"
57
57
  :disabled="disabled"
58
58
  :generateLabels="generateLabels"
59
+ :accumulatedBasis="accumulatedBasis"
59
60
  )
60
61
  TransitionHeight(:enabled="inlined")
61
62
  DitoPane.dito-pane-main(
@@ -69,6 +70,7 @@ slot(name="before")
69
70
  :single="!inlined && !hasTabs"
70
71
  :disabled="disabled"
71
72
  :generateLabels="generateLabels"
73
+ :accumulatedBasis="accumulatedBasis"
72
74
  )
73
75
  slot(
74
76
  v-if="!inlined && isPopulated"
@@ -149,7 +151,8 @@ export default DitoComponent.component('DitoSchema', {
149
151
  scrollable: { type: Boolean, default: false },
150
152
  hasOwnData: { type: Boolean, default: false },
151
153
  headerInMenu: { type: Boolean, default: false },
152
- generateLabels: { type: Boolean, default: false }
154
+ generateLabels: { type: Boolean, default: false },
155
+ accumulatedBasis: { type: Number, default: 1 }
153
156
  },
154
157
 
155
158
  data() {
@@ -12,6 +12,7 @@ DitoSchema.dito-schema-inlined(
12
12
  :collapsed="collapsed"
13
13
  :collapsible="collapsible"
14
14
  :generateLabels="!isCompact"
15
+ :accumulatedBasis="accumulatedBasis"
15
16
  )
16
17
  //- Render dito-edit-buttons for inlined schemas separately from all
17
18
  //- others in `TypeList` as a scope, for better handling of layout.
@@ -51,7 +52,8 @@ export default DitoComponent.component('DitoSchemaInlined', {
51
52
  draggable: { type: Boolean, default: false },
52
53
  editable: { type: Boolean, default: false },
53
54
  deletable: { type: Boolean, default: false },
54
- editPath: { type: String, default: null }
55
+ editPath: { type: String, default: null },
56
+ accumulatedBasis: { type: Number, default: null }
55
57
  },
56
58
 
57
59
  computed: {
@@ -73,7 +73,7 @@ export default {
73
73
  },
74
74
 
75
75
  path() {
76
- return this.getRoutePath(this.routeRecord.path)
76
+ return this.getRoutePath(this.routeRecord?.path)
77
77
  },
78
78
 
79
79
  label() {
@@ -168,10 +168,13 @@ export default {
168
168
  // Maps the route's actual path to the matched routes by counting its
169
169
  // parts separated by '/', splitting the path into the mapped parts
170
170
  // containing actual parameters.
171
- return this.$route.path
172
- .split('/')
173
- .slice(0, templatePath.split('/').length)
174
- .join('/')
171
+ const { path } = this.$route
172
+ return templatePath
173
+ ? path
174
+ .split('/')
175
+ .slice(0, templatePath.split('/').length)
176
+ .join('/')
177
+ : path
175
178
  },
176
179
 
177
180
  getChildPath(path) {
@@ -21,7 +21,8 @@ export default {
21
21
  label: { type: String, default: null },
22
22
  single: { type: Boolean, default: false },
23
23
  nested: { type: Boolean, default: true },
24
- disabled: { type: Boolean, default: false }
24
+ disabled: { type: Boolean, default: false },
25
+ accumulatedBasis: { type: Number, default: null }
25
26
  },
26
27
 
27
28
  data() {
@@ -3,7 +3,7 @@
3
3
  display: flex;
4
4
 
5
5
  > * {
6
- flex: 1;
6
+ flex: 1 0 auto;
7
7
  display: flex;
8
8
  }
9
9
  }
@@ -28,8 +28,8 @@ export default DitoTypeComponent.register(
28
28
  {
29
29
  defaultValue: () => undefined, // Callback to override `defaultValue: null`
30
30
  excludeValue: true,
31
- generateLabel: false,
32
31
  defaultWidth: 'auto',
32
+ generateLabel: false,
33
33
 
34
34
  computed: {
35
35
  verb() {
@@ -27,6 +27,7 @@ export default DitoTypeComponent.register('checkboxes', {
27
27
 
28
28
  nativeField: true,
29
29
  defaultValue: [],
30
+ defaultWidth: 'auto',
30
31
 
31
32
  computed: {
32
33
  selectedOptions: {
@@ -18,6 +18,7 @@
18
18
  :disabled="disabled || isLoading"
19
19
  :collapsed="collapsed"
20
20
  :collapsible="collapsible"
21
+ :accumulatedBasis="accumulatedBasis"
21
22
  )
22
23
  component(
23
24
  v-else-if="schema.component"
@@ -25,7 +25,8 @@ import OptionsMixin from '../mixins/OptionsMixin.js'
25
25
  export default DitoTypeComponent.register('radio', {
26
26
  mixins: [OptionsMixin],
27
27
 
28
- nativeField: true
28
+ nativeField: true,
29
+ defaultWidth: 'auto'
29
30
  })
30
31
  </script>
31
32
 
@@ -283,32 +283,32 @@ export async function processSchemaComponent(
283
283
  ])
284
284
  }
285
285
 
286
- export async function processView(component, api, schema, name) {
286
+ export async function processView(component, api, schema, name, menuLevel = 0) {
287
287
  processSchemaDefaults(api, schema)
288
+ let children = []
288
289
  if (isView(schema)) {
289
290
  processRouteSchema(api, schema, name)
290
291
  await processNestedSchemas(api, schema)
291
- const children = []
292
- await processSchemaComponents(api, schema, children, 0)
293
- return {
294
- path: `/${schema.path}`,
295
- children,
296
- component,
297
- meta: {
298
- api,
299
- schema
300
- }
301
- }
292
+ await processSchemaComponents(api, schema, children)
302
293
  } else if (isMenu(schema)) {
303
- return Promise.all(
294
+ processRouteSchema(api, schema, name)
295
+ children = await Promise.all(
304
296
  Object.entries(schema.items).map(async ([name, item]) =>
305
- processView(component, api, item, name)
297
+ processView(component, api, item, name, menuLevel + 1)
306
298
  )
307
299
  )
308
- //
309
300
  } else {
310
301
  throw new Error(`Invalid view schema: '${getSchemaIdentifier(schema)}'`)
311
302
  }
303
+ return {
304
+ path: menuLevel === 0 ? `/${schema.path}` : schema.path,
305
+ children,
306
+ component,
307
+ meta: {
308
+ api,
309
+ schema
310
+ }
311
+ }
312
312
  }
313
313
 
314
314
  export function processSchemaDefaults(api, schema) {