apostrophe 3.28.1 → 3.29.0
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/CHANGELOG.md +17 -6
- package/modules/@apostrophecms/area/index.js +25 -4
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaContextualMenu.vue +382 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +28 -4
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +264 -0
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +40 -233
- package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +22 -7
- package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +6 -6
- package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +28 -5
- package/modules/@apostrophecms/piece-page-type/index.js +8 -1
- package/modules/@apostrophecms/schema/lib/addFieldTypes.js +24 -11
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +12 -1
- package/modules/@apostrophecms/widget-type/index.js +4 -0
- package/package.json +1 -1
- package/test/areas.js +38 -1
- package/test/schemas.js +62 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<AposModal
|
|
3
|
+
class="apos-area-menu--expanded"
|
|
4
|
+
:modal="modal"
|
|
5
|
+
modal-title="apostrophe:addContent"
|
|
6
|
+
@inactive="modal.active = false"
|
|
7
|
+
@show-modal="modal.showModal = true"
|
|
8
|
+
@esc="close"
|
|
9
|
+
@no-modal="$emit('safe-close')"
|
|
10
|
+
>
|
|
11
|
+
<template #main>
|
|
12
|
+
<AposModalBody>
|
|
13
|
+
<template #bodyMain>
|
|
14
|
+
<div
|
|
15
|
+
v-for="(group, groupIndex) in groups"
|
|
16
|
+
:key="groupIndex"
|
|
17
|
+
class="apos-widget-group"
|
|
18
|
+
>
|
|
19
|
+
<h2 class="apos-widget-group__label" v-if="group.label">{{ group.label }}</h2>
|
|
20
|
+
<div
|
|
21
|
+
:class="[
|
|
22
|
+
`apos-widget-group--${group.columns}-column${
|
|
23
|
+
group.columns > 1 ? 's' : ''
|
|
24
|
+
}`
|
|
25
|
+
]"
|
|
26
|
+
>
|
|
27
|
+
<div
|
|
28
|
+
v-for="(item, itemIndex) in group.widgets"
|
|
29
|
+
:key="itemIndex"
|
|
30
|
+
class="apos-widget"
|
|
31
|
+
@click="add(item)"
|
|
32
|
+
>
|
|
33
|
+
<div class="apos-widget__preview">
|
|
34
|
+
<plus-icon
|
|
35
|
+
:size="20"
|
|
36
|
+
class="apos-icon--add"
|
|
37
|
+
/>
|
|
38
|
+
<img
|
|
39
|
+
v-if="item.previewImage"
|
|
40
|
+
:src="previewUrl(item)"
|
|
41
|
+
:alt="`${item.name} preview`"
|
|
42
|
+
class="apos-widget__preview-image"
|
|
43
|
+
>
|
|
44
|
+
<component
|
|
45
|
+
v-else-if="hasIcon(item)"
|
|
46
|
+
:size="25"
|
|
47
|
+
class="apos-widget__preview--icon"
|
|
48
|
+
:is="item.previewIcon || item.icon"
|
|
49
|
+
/>
|
|
50
|
+
</div>
|
|
51
|
+
<p class="apos-widget__label">
|
|
52
|
+
{{ $t(item.label) }}
|
|
53
|
+
</p>
|
|
54
|
+
<p v-if="item.description" class="apos-widget__help">
|
|
55
|
+
{{ $t(item.description) }}
|
|
56
|
+
</p>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</template>
|
|
61
|
+
</AposModalBody>
|
|
62
|
+
</template>
|
|
63
|
+
</AposModal>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
export default {
|
|
68
|
+
name: 'AposAreaExpandedMenu',
|
|
69
|
+
props: {
|
|
70
|
+
options: {
|
|
71
|
+
type: Object,
|
|
72
|
+
required: true
|
|
73
|
+
},
|
|
74
|
+
index: {
|
|
75
|
+
type: Number,
|
|
76
|
+
default: 0
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
emits: [ 'expanded-menu-close', 'safe-close', 'modal-result' ],
|
|
80
|
+
data() {
|
|
81
|
+
return {
|
|
82
|
+
modal: {
|
|
83
|
+
active: false,
|
|
84
|
+
type: 'slide',
|
|
85
|
+
origin: 'left',
|
|
86
|
+
showModal: false,
|
|
87
|
+
width: 'one-third'
|
|
88
|
+
},
|
|
89
|
+
groups: []
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
async mounted() {
|
|
93
|
+
this.modal.active = true;
|
|
94
|
+
|
|
95
|
+
if (this.options.groups) {
|
|
96
|
+
for (const item of Object.keys(this.options.groups)) {
|
|
97
|
+
if (!this.isValidColumn(item.columns)) {
|
|
98
|
+
console.warn(
|
|
99
|
+
`apos.expanded-menu: The specified number of columns for the group ${item.label} is not between the allowed range of 1-4.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const group = this.createGroup(this.options.groups[item]);
|
|
104
|
+
this.groups.push(group);
|
|
105
|
+
}
|
|
106
|
+
} else if (this.options.widgets) {
|
|
107
|
+
if (!this.isValidColumn(this.options.columns)) {
|
|
108
|
+
console.warn(
|
|
109
|
+
'apos.expanded-menu: The specified number of columns for the area is not between the allowed range of 1-4.'
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const group = this.createGroup(this.options);
|
|
114
|
+
this.groups.push(group);
|
|
115
|
+
} else {
|
|
116
|
+
console.warn(
|
|
117
|
+
'apos.expanded-menu: No groups or widgets defined. Please, either add a groups or widgets property to your area configuration.'
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
methods: {
|
|
122
|
+
isValidColumn(count) {
|
|
123
|
+
return count ? +count > 1 && +count < 4 : true;
|
|
124
|
+
},
|
|
125
|
+
createGroup(config) {
|
|
126
|
+
const group = {
|
|
127
|
+
columns: +config.columns || 3,
|
|
128
|
+
widgets: []
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if (config.label) {
|
|
132
|
+
group.label = config.label;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
for (const item of Object.keys(config.widgets)) {
|
|
136
|
+
group.widgets.push(apos.modules[`${item}-widget`]);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return group;
|
|
140
|
+
},
|
|
141
|
+
hasIcon(widget) {
|
|
142
|
+
return widget.previewIcon || widget.icon;
|
|
143
|
+
},
|
|
144
|
+
previewUrl(widget) {
|
|
145
|
+
return widget.previewImage ? apos.util.assetUrl(`/modules/${widget.name}-widget/preview.${widget.previewImage}`) : '';
|
|
146
|
+
},
|
|
147
|
+
close() {
|
|
148
|
+
this.modal.showModal = false;
|
|
149
|
+
},
|
|
150
|
+
async add(item) {
|
|
151
|
+
const data = {
|
|
152
|
+
...item,
|
|
153
|
+
index: this.index
|
|
154
|
+
};
|
|
155
|
+
this.$emit('modal-result', data);
|
|
156
|
+
this.modal.showModal = false;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
</script>
|
|
161
|
+
|
|
162
|
+
<style lang="scss" scoped>
|
|
163
|
+
.apos-area-menu--expanded {
|
|
164
|
+
@include type-base;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.apos-widget-group {
|
|
168
|
+
&:not(:last-of-type) {
|
|
169
|
+
margin-bottom: 30px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.apos-widget__preview {
|
|
173
|
+
position: relative;
|
|
174
|
+
display: flex;
|
|
175
|
+
justify-content: center;
|
|
176
|
+
align-items: center;
|
|
177
|
+
height: 135px;
|
|
178
|
+
border: 1px solid var(--a-base-7);
|
|
179
|
+
border-radius: var(--a-border-radius);
|
|
180
|
+
background-color: var(--a-base-10);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
&--2-columns {
|
|
184
|
+
display: grid;
|
|
185
|
+
grid-template-columns: repeat(2, 1fr);
|
|
186
|
+
gap: 15px;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
&--3-columns {
|
|
190
|
+
display: grid;
|
|
191
|
+
grid-template-columns: repeat(3, 1fr);
|
|
192
|
+
gap: 10px;
|
|
193
|
+
.apos-widget__preview {
|
|
194
|
+
height: 89px;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
&--4-columns {
|
|
199
|
+
display: grid;
|
|
200
|
+
grid-template-columns: repeat(4, 1fr);
|
|
201
|
+
gap: 5px;
|
|
202
|
+
.apos-widget__preview {
|
|
203
|
+
height: 66px;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.apos-widget {
|
|
209
|
+
.apos-widget__preview {
|
|
210
|
+
transition: opacity 250ms ease-in-out;
|
|
211
|
+
.apos-icon--add {
|
|
212
|
+
z-index: $z-index-default;
|
|
213
|
+
position: absolute;
|
|
214
|
+
// Center in the parent element
|
|
215
|
+
align-self: center;
|
|
216
|
+
justify-self: center;
|
|
217
|
+
// Center the child content
|
|
218
|
+
display: flex;
|
|
219
|
+
justify-content: center;
|
|
220
|
+
align-items: center;
|
|
221
|
+
width: 27px;
|
|
222
|
+
height: 27px;
|
|
223
|
+
border-radius: 50%;
|
|
224
|
+
background-color: var(--a-primary);
|
|
225
|
+
opacity: 0;
|
|
226
|
+
color: var(--a-white);
|
|
227
|
+
}
|
|
228
|
+
&::after {
|
|
229
|
+
transition: all 250ms ease-in-out;
|
|
230
|
+
position: absolute;
|
|
231
|
+
content: '';
|
|
232
|
+
width: 100%;
|
|
233
|
+
height: 100%;
|
|
234
|
+
background-color: var(--a-primary);
|
|
235
|
+
opacity: 0;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
&:hover {
|
|
239
|
+
cursor: pointer;
|
|
240
|
+
// stylelint-disable max-nesting-depth
|
|
241
|
+
.apos-widget__preview {
|
|
242
|
+
.apos-icon--add {
|
|
243
|
+
opacity: 1;
|
|
244
|
+
}
|
|
245
|
+
&::after {
|
|
246
|
+
opacity: 0.4;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// stylelint-enable max-nesting-depth
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.apos-widget__preview-image {
|
|
254
|
+
width: 100%;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.apos-widget-group__label,
|
|
258
|
+
.apos-widget__help {
|
|
259
|
+
@include type-base;
|
|
260
|
+
line-height: var(--a-line-tall);
|
|
261
|
+
color: var(--a-base-4);
|
|
262
|
+
text-align: left;
|
|
263
|
+
}
|
|
264
|
+
</style>
|
|
@@ -1,91 +1,33 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<dt>
|
|
22
|
-
<button
|
|
23
|
-
:for="item.label" class="apos-area-menu__group-label"
|
|
24
|
-
v-if="item.items" tabindex="0"
|
|
25
|
-
:id="`${menuId}-trigger-${itemIndex}`"
|
|
26
|
-
:aria-controls="`${menuId}-group-${itemIndex}`"
|
|
27
|
-
@focus="groupFocused"
|
|
28
|
-
@blur="groupBlurred"
|
|
29
|
-
@click="toggleGroup(itemIndex)"
|
|
30
|
-
@keydown.prevent.space="toggleGroup(itemIndex)"
|
|
31
|
-
@keydown.prevent.enter="toggleGroup(itemIndex)"
|
|
32
|
-
@keydown.prevent.arrow-down="switchGroup(itemIndex, 1)"
|
|
33
|
-
@keydown.prevent.arrow-up="switchGroup(itemIndex, -1)"
|
|
34
|
-
@keydown.prevent.home="switchGroup(itemIndex, 0)"
|
|
35
|
-
@keydown.prevent.end="switchGroup(itemIndex, null)"
|
|
36
|
-
ref="groupButton"
|
|
37
|
-
>
|
|
38
|
-
<span>{{ item.label }}</span>
|
|
39
|
-
<chevron-up-icon
|
|
40
|
-
class="apos-area-menu__group-chevron"
|
|
41
|
-
:class="{'apos-is-active': itemIndex === active}" :size="13"
|
|
42
|
-
/>
|
|
43
|
-
</button>
|
|
44
|
-
</dt>
|
|
45
|
-
<dd class="apos-area-menu__group-list" role="region">
|
|
46
|
-
<ul
|
|
47
|
-
class="apos-area-menu__items apos-area-menu__items--accordion"
|
|
48
|
-
:class="{'apos-is-active': active === itemIndex}"
|
|
49
|
-
:id="`${menuId}-group-${itemIndex}`"
|
|
50
|
-
:aria-labelledby="`${menuId}-trigger-${itemIndex}`"
|
|
51
|
-
:aria-expanded="active === itemIndex ? 'true' : 'false'"
|
|
52
|
-
>
|
|
53
|
-
<li
|
|
54
|
-
class="apos-area-menu__item"
|
|
55
|
-
v-for="(child, childIndex) in item.items"
|
|
56
|
-
:key="child.name"
|
|
57
|
-
:ref="`child-${index}-${childIndex}`"
|
|
58
|
-
>
|
|
59
|
-
<AposAreaMenuItem
|
|
60
|
-
@click="add(child)"
|
|
61
|
-
:item="child"
|
|
62
|
-
:tabbable="itemIndex === active"
|
|
63
|
-
@up="switchItem(`child-${itemIndex}-${childIndex - 1}`, -1)"
|
|
64
|
-
@down="switchItem(`child-${itemIndex}-${childIndex + 1}`, 1)"
|
|
65
|
-
/>
|
|
66
|
-
</li>
|
|
67
|
-
</ul>
|
|
68
|
-
</dd>
|
|
69
|
-
</dl>
|
|
70
|
-
<AposAreaMenuItem
|
|
71
|
-
v-else
|
|
72
|
-
@click="add(item)"
|
|
73
|
-
:item="item"
|
|
74
|
-
@up="switchItem(`item-${itemIndex - 1}`, -1)"
|
|
75
|
-
@down="switchItem(`item-${itemIndex + 1}`, 1)"
|
|
76
|
-
/>
|
|
77
|
-
</li>
|
|
78
|
-
</ul>
|
|
79
|
-
</AposContextMenu>
|
|
80
|
-
</div>
|
|
2
|
+
<AposButton
|
|
3
|
+
v-if="options.expanded"
|
|
4
|
+
:disabled="disabled"
|
|
5
|
+
v-bind="buttonOptions"
|
|
6
|
+
@click="openExpandedMenu(index)"
|
|
7
|
+
role="button"
|
|
8
|
+
/>
|
|
9
|
+
<AposAreaContextualMenu
|
|
10
|
+
v-else
|
|
11
|
+
@add="$emit('add', $event);"
|
|
12
|
+
:button-options="buttonOptions"
|
|
13
|
+
:context-menu-options="contextMenuOptions"
|
|
14
|
+
:empty="true"
|
|
15
|
+
:index="index"
|
|
16
|
+
:widget-options="options.widgets"
|
|
17
|
+
:options="options"
|
|
18
|
+
:max-reached="maxReached"
|
|
19
|
+
:disabled="disabled"
|
|
20
|
+
/>
|
|
81
21
|
</template>
|
|
82
22
|
|
|
83
23
|
<script>
|
|
84
|
-
|
|
85
|
-
import cuid from 'cuid';
|
|
86
|
-
|
|
87
24
|
export default {
|
|
25
|
+
name: 'AposAreaMenu',
|
|
88
26
|
props: {
|
|
27
|
+
disabled: {
|
|
28
|
+
type: Boolean,
|
|
29
|
+
default: false
|
|
30
|
+
},
|
|
89
31
|
empty: {
|
|
90
32
|
type: Boolean,
|
|
91
33
|
default: false
|
|
@@ -98,30 +40,24 @@ export default {
|
|
|
98
40
|
type: Number,
|
|
99
41
|
default: 0
|
|
100
42
|
},
|
|
101
|
-
|
|
43
|
+
options: {
|
|
102
44
|
type: Object,
|
|
103
45
|
required: true
|
|
104
46
|
},
|
|
105
47
|
maxReached: {
|
|
106
48
|
type: Boolean
|
|
107
49
|
},
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
50
|
+
// NOTE: Left for backwards compatibility.
|
|
51
|
+
// Should use options now instead.
|
|
52
|
+
widgetOptions: {
|
|
53
|
+
type: Object,
|
|
54
|
+
default: function() {
|
|
55
|
+
return {};
|
|
56
|
+
}
|
|
111
57
|
}
|
|
112
58
|
},
|
|
113
|
-
emits: [ '
|
|
114
|
-
data() {
|
|
115
|
-
return {
|
|
116
|
-
active: 0,
|
|
117
|
-
groupIsFocused: false,
|
|
118
|
-
inContext: true
|
|
119
|
-
};
|
|
120
|
-
},
|
|
59
|
+
emits: [ 'add' ],
|
|
121
60
|
computed: {
|
|
122
|
-
moduleOptions() {
|
|
123
|
-
return window.apos.area;
|
|
124
|
-
},
|
|
125
61
|
buttonOptions() {
|
|
126
62
|
return {
|
|
127
63
|
label: 'apostrophe:addContent',
|
|
@@ -131,147 +67,18 @@ export default {
|
|
|
131
67
|
modifiers: this.empty ? [] : [ 'round', 'tiny' ],
|
|
132
68
|
iconSize: this.empty ? 20 : 11
|
|
133
69
|
};
|
|
134
|
-
},
|
|
135
|
-
isDisabled() {
|
|
136
|
-
let flag = this.disabled;
|
|
137
|
-
if (this.maxReached) {
|
|
138
|
-
flag = true;
|
|
139
|
-
}
|
|
140
|
-
return flag;
|
|
141
|
-
},
|
|
142
|
-
extendedContextMenuOptions() {
|
|
143
|
-
const modifiers = [ 'unpadded' ];
|
|
144
|
-
if (!this.groupedMenus) {
|
|
145
|
-
modifiers.push('tb-padded');
|
|
146
|
-
}
|
|
147
|
-
return {
|
|
148
|
-
menuPlacement: 'bottom',
|
|
149
|
-
menuOffset: 15,
|
|
150
|
-
...this.contextMenuOptions,
|
|
151
|
-
modifiers
|
|
152
|
-
};
|
|
153
|
-
},
|
|
154
|
-
groupedMenus() {
|
|
155
|
-
let flag = false;
|
|
156
|
-
this.contextMenuOptions.menu.forEach((e) => {
|
|
157
|
-
if (e.items) {
|
|
158
|
-
flag = true;
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
return flag;
|
|
162
|
-
},
|
|
163
|
-
myMenu() {
|
|
164
|
-
const clipboard = apos.area.widgetClipboard.get();
|
|
165
|
-
const menu = [ ...this.contextMenuOptions.menu ];
|
|
166
|
-
if (clipboard) {
|
|
167
|
-
const widget = clipboard;
|
|
168
|
-
const matchingChoice = menu.find(option => option.name === widget.type);
|
|
169
|
-
if (matchingChoice) {
|
|
170
|
-
menu.unshift({
|
|
171
|
-
type: 'clipboard',
|
|
172
|
-
...matchingChoice,
|
|
173
|
-
label: {
|
|
174
|
-
key: 'apostrophe:pasteWidget',
|
|
175
|
-
widget: this.$t(matchingChoice.label)
|
|
176
|
-
},
|
|
177
|
-
clipboard: widget
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (this.groupedMenus) {
|
|
182
|
-
return this.composeGroups(menu);
|
|
183
|
-
} else {
|
|
184
|
-
return menu;
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
menuId() {
|
|
188
|
-
return `areaMenu-${cuid()}`;
|
|
189
70
|
}
|
|
190
71
|
},
|
|
191
|
-
mounted() {
|
|
192
|
-
// if this area is not in-context then it is assumed in a schema's modal and we need to bump
|
|
193
|
-
// the z-index of menus above them
|
|
194
|
-
this.inContext = !apos.util.closest(this.$el, '[data-apos-schema-area]');
|
|
195
|
-
},
|
|
196
72
|
methods: {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
},
|
|
203
|
-
async add(item) {
|
|
204
|
-
// Potential TODO: If we find ourselves manually flipping these bits in other AposContextMenu overrides
|
|
205
|
-
// we should consider refactoring contextmenus to be able to self close when any click takes place within their el
|
|
206
|
-
// as it is often the logical experience (not always, see tag menus and filters)
|
|
207
|
-
this.$refs.contextMenu.isOpen = false;
|
|
208
|
-
this.$emit('add', {
|
|
209
|
-
...item,
|
|
210
|
-
index: this.index
|
|
211
|
-
});
|
|
212
|
-
},
|
|
213
|
-
groupFocused() {
|
|
214
|
-
this.groupIsFocused = true;
|
|
215
|
-
},
|
|
216
|
-
groupBlurred() {
|
|
217
|
-
this.groupIsFocused = false;
|
|
218
|
-
},
|
|
219
|
-
composeGroups(menu) {
|
|
220
|
-
const ungrouped = {
|
|
221
|
-
label: 'apostrophe:ungroupedWidgets',
|
|
222
|
-
items: []
|
|
223
|
-
};
|
|
224
|
-
const myMenu = [];
|
|
225
|
-
|
|
226
|
-
menu.forEach((item) => {
|
|
227
|
-
if (!item.items) {
|
|
228
|
-
ungrouped.items.push(item);
|
|
229
|
-
} else {
|
|
230
|
-
myMenu.push(item);
|
|
231
|
-
}
|
|
73
|
+
async openExpandedMenu(index) {
|
|
74
|
+
const data = await apos.modal.execute('AposAreaExpandedMenu', {
|
|
75
|
+
field: this.field,
|
|
76
|
+
options: this.options,
|
|
77
|
+
index
|
|
232
78
|
});
|
|
233
79
|
|
|
234
|
-
if (
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
return myMenu;
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
toggleGroup(index) {
|
|
241
|
-
if (this.active !== index) {
|
|
242
|
-
this.active = index;
|
|
243
|
-
} else {
|
|
244
|
-
this.active = null;
|
|
245
|
-
}
|
|
246
|
-
},
|
|
247
|
-
|
|
248
|
-
switchGroup(index, dir) {
|
|
249
|
-
let target;
|
|
250
|
-
|
|
251
|
-
if (dir > 0) {
|
|
252
|
-
target = index < this.$refs.groupButton.length - 1 ? index + 1 : 0;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
if (dir < 0) {
|
|
256
|
-
target = index === 0 ? this.$refs.groupButton.length - 1 : index - 1;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (dir === 0) {
|
|
260
|
-
target = 0;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
if (!dir) {
|
|
264
|
-
target = this.$refs.groupButton.length - 1;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
this.$nextTick(() => {
|
|
268
|
-
this.$refs.groupButton[target].focus();
|
|
269
|
-
});
|
|
270
|
-
},
|
|
271
|
-
|
|
272
|
-
switchItem(name, dir) {
|
|
273
|
-
if (this.$refs[name]) {
|
|
274
|
-
this.$refs[name][0].querySelector('button').focus();
|
|
80
|
+
if (data) {
|
|
81
|
+
this.$emit('add', data);
|
|
275
82
|
}
|
|
276
83
|
}
|
|
277
84
|
}
|
|
@@ -60,7 +60,8 @@
|
|
|
60
60
|
@menu-close="toggleMenuFocus($event, 'top', false)"
|
|
61
61
|
:context-menu-options="contextMenuOptions"
|
|
62
62
|
:index="i"
|
|
63
|
-
:widget-options="
|
|
63
|
+
:widget-options="widgets"
|
|
64
|
+
:options="options"
|
|
64
65
|
:disabled="disabled"
|
|
65
66
|
/>
|
|
66
67
|
</div>
|
|
@@ -96,10 +97,10 @@
|
|
|
96
97
|
<component
|
|
97
98
|
v-if="isContextual && !foreign"
|
|
98
99
|
:is="widgetEditorComponent(widget.type)"
|
|
100
|
+
:options="widgetOptions"
|
|
101
|
+
:type="widget.type"
|
|
99
102
|
:value="widget"
|
|
100
103
|
@update="$emit('update', $event)"
|
|
101
|
-
:options="options.widgets[widget.type]"
|
|
102
|
-
:type="widget.type"
|
|
103
104
|
:doc-id="docId"
|
|
104
105
|
:focused="focused"
|
|
105
106
|
:key="generation"
|
|
@@ -107,7 +108,7 @@
|
|
|
107
108
|
<component
|
|
108
109
|
v-else
|
|
109
110
|
:is="widgetComponent(widget.type)"
|
|
110
|
-
:options="
|
|
111
|
+
:options="widgetOptions"
|
|
111
112
|
:type="widget.type"
|
|
112
113
|
:id="widget._id"
|
|
113
114
|
:area-field-id="fieldId"
|
|
@@ -128,7 +129,8 @@
|
|
|
128
129
|
@add="$emit('add', $event)"
|
|
129
130
|
:context-menu-options="bottomContextMenuOptions"
|
|
130
131
|
:index="i + 1"
|
|
131
|
-
:widget-options="
|
|
132
|
+
:widget-options="widgets"
|
|
133
|
+
:options="options"
|
|
132
134
|
:disabled="disabled"
|
|
133
135
|
@menu-open="toggleMenuFocus($event, 'bottom', true)"
|
|
134
136
|
@menu-close="toggleMenuFocus($event, 'bottom', false)"
|
|
@@ -139,7 +141,6 @@
|
|
|
139
141
|
</template>
|
|
140
142
|
|
|
141
143
|
<script>
|
|
142
|
-
|
|
143
144
|
import { klona } from 'klona';
|
|
144
145
|
import AposIndicator from '../../../../ui/ui/apos/components/AposIndicator.vue';
|
|
145
146
|
|
|
@@ -249,7 +250,8 @@ export default {
|
|
|
249
250
|
breadcrumbs: {
|
|
250
251
|
$lastEl: null,
|
|
251
252
|
list: []
|
|
252
|
-
}
|
|
253
|
+
},
|
|
254
|
+
widgets: this.options.widgets || {}
|
|
253
255
|
};
|
|
254
256
|
},
|
|
255
257
|
computed: {
|
|
@@ -262,6 +264,9 @@ export default {
|
|
|
262
264
|
widgetLabel() {
|
|
263
265
|
return window.apos.modules[`${this.widget.type}-widget`].label;
|
|
264
266
|
},
|
|
267
|
+
widgetOptions() {
|
|
268
|
+
return this.widgets[this.widget.type];
|
|
269
|
+
},
|
|
265
270
|
isContextual() {
|
|
266
271
|
return this.moduleOptions.widgetIsContextual[this.widget.type];
|
|
267
272
|
},
|
|
@@ -334,6 +339,16 @@ export default {
|
|
|
334
339
|
}
|
|
335
340
|
}
|
|
336
341
|
},
|
|
342
|
+
created() {
|
|
343
|
+
if (this.options.groups) {
|
|
344
|
+
for (const group of Object.keys(this.options.groups)) {
|
|
345
|
+
this.widgets = {
|
|
346
|
+
...this.options.groups[group].widgets,
|
|
347
|
+
...this.widgets
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
337
352
|
mounted() {
|
|
338
353
|
// AposAreaEditor is listening for keyboard input that triggers
|
|
339
354
|
// a 'focus my parent' plea
|
|
@@ -232,16 +232,17 @@ export default {
|
|
|
232
232
|
} catch (e) {
|
|
233
233
|
this.error = e.message || 'An error occurred. Please try again.';
|
|
234
234
|
this.phase = 'beforeSubmit';
|
|
235
|
-
this.requirements = getRequirements();
|
|
236
235
|
} finally {
|
|
237
236
|
this.busy = false;
|
|
238
237
|
}
|
|
239
238
|
},
|
|
240
239
|
getInitialSubmitRequirementsData() {
|
|
241
|
-
return Object.fromEntries(this.requirements
|
|
242
|
-
r.
|
|
243
|
-
r
|
|
244
|
-
|
|
240
|
+
return Object.fromEntries(this.requirements
|
|
241
|
+
.filter(r => r.phase !== 'afterPasswordVerified' || !r.done)
|
|
242
|
+
.map(r => ([
|
|
243
|
+
r.name,
|
|
244
|
+
r.value
|
|
245
|
+
])));
|
|
245
246
|
},
|
|
246
247
|
async invokeFinalLoginApi() {
|
|
247
248
|
try {
|
|
@@ -257,7 +258,6 @@ export default {
|
|
|
257
258
|
this.redirectAfterLogin();
|
|
258
259
|
} catch (e) {
|
|
259
260
|
this.error = e.message || 'An error occurred. Please try again.';
|
|
260
|
-
this.requirements = getRequirements();
|
|
261
261
|
this.phase = 'beforeSubmit';
|
|
262
262
|
} finally {
|
|
263
263
|
this.busy = false;
|