apostrophe 3.53.0 → 3.55.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 +58 -1
- package/defaults.js +1 -0
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +5 -2
- package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +28 -19
- package/modules/@apostrophecms/any-doc-type/index.js +2 -2
- package/modules/@apostrophecms/any-page-type/index.js +2 -2
- package/modules/@apostrophecms/doc/index.js +55 -29
- package/modules/@apostrophecms/doc-type/index.js +11 -6
- package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocContextMenu.vue +4 -440
- package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +445 -0
- package/modules/@apostrophecms/i18n/i18n/de.json +113 -105
- package/modules/@apostrophecms/i18n/i18n/es.json +10 -0
- package/modules/@apostrophecms/i18n/i18n/fr.json +8 -0
- package/modules/@apostrophecms/i18n/i18n/pt-BR.json +10 -0
- package/modules/@apostrophecms/i18n/i18n/sk.json +8 -0
- package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +1 -0
- package/modules/@apostrophecms/log/index.js +429 -0
- package/modules/@apostrophecms/login/index.js +47 -4
- package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +14 -1
- package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +1 -1
- package/modules/@apostrophecms/module/index.js +32 -6
- package/modules/@apostrophecms/module/lib/log.js +68 -0
- package/modules/@apostrophecms/page/index.js +71 -19
- package/modules/@apostrophecms/page/lib/legacy-migrations.js +0 -57
- package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +8 -285
- package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +291 -0
- package/modules/@apostrophecms/page-type/index.js +39 -26
- package/modules/@apostrophecms/piece-type/index.js +19 -11
- package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +1 -0
- package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +2 -357
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +2 -86
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +2 -254
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputAttachment.vue +2 -77
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputBoolean.vue +2 -44
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputCheckboxes.vue +2 -64
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputColor.vue +2 -94
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputDateAndTime.vue +3 -47
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +2 -82
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputPassword.vue +2 -37
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +2 -26
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputRange.vue +2 -57
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +2 -259
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputSelect.vue +2 -38
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +2 -275
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +2 -167
- package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +2 -115
- package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +3 -279
- package/modules/@apostrophecms/schema/ui/apos/components/AposSearchList.vue +2 -83
- package/modules/@apostrophecms/schema/ui/apos/lib/detectChange.js +10 -1
- package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +361 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArea.js +89 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArray.js +257 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputAttachment.js +81 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputBoolean.js +48 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputCheckboxes.js +68 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputColor.js +98 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputDateAndTime.js +49 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputObject.js +86 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputPassword.js +41 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRadio.js +29 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRange.js +60 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +262 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSelect.js +41 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSlug.js +278 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +170 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +118 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +281 -0
- package/modules/@apostrophecms/schema/ui/apos/logic/AposSearchList.js +85 -0
- package/modules/@apostrophecms/template/index.js +1 -1
- package/modules/@apostrophecms/ui/ui/apos/components/AposTreeHeader.vue +2 -2
- package/modules/@apostrophecms/util/index.js +83 -13
- package/modules/@apostrophecms/util/lib/logger.js +19 -17
- package/package.json +1 -1
- package/test/docs.js +35 -2
- package/test/log.js +1765 -0
- package/test/pages.js +57 -0
- package/test-lib/util.js +1 -1
|
@@ -27,90 +27,10 @@
|
|
|
27
27
|
</template>
|
|
28
28
|
|
|
29
29
|
<script>
|
|
30
|
-
import
|
|
31
|
-
import AposInputFollowingMixin from 'Modules/@apostrophecms/schema/mixins/AposInputFollowingMixin.js';
|
|
32
|
-
import AposInputConditionalFieldsMixin from 'Modules/@apostrophecms/schema/mixins/AposInputConditionalFieldsMixin.js';
|
|
33
|
-
|
|
30
|
+
import AposInputObjectLogic from '../logic/AposInputObject';
|
|
34
31
|
export default {
|
|
35
32
|
name: 'AposInputObject',
|
|
36
|
-
mixins: [
|
|
37
|
-
AposInputMixin,
|
|
38
|
-
AposInputFollowingMixin,
|
|
39
|
-
AposInputConditionalFieldsMixin
|
|
40
|
-
],
|
|
41
|
-
props: {
|
|
42
|
-
generation: {
|
|
43
|
-
type: Number,
|
|
44
|
-
required: false,
|
|
45
|
-
default() {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
docId: {
|
|
50
|
-
type: String,
|
|
51
|
-
required: false,
|
|
52
|
-
default() {
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
data () {
|
|
58
|
-
const next = this.getNext();
|
|
59
|
-
return {
|
|
60
|
-
schemaInput: {
|
|
61
|
-
data: next
|
|
62
|
-
},
|
|
63
|
-
next
|
|
64
|
-
};
|
|
65
|
-
},
|
|
66
|
-
computed: {
|
|
67
|
-
followingValuesWithParent() {
|
|
68
|
-
return this.computeFollowingValues(this.schemaInput.data);
|
|
69
|
-
},
|
|
70
|
-
// Reqiured for AposInputConditionalFieldsMixin
|
|
71
|
-
schema() {
|
|
72
|
-
return this.field.schema;
|
|
73
|
-
},
|
|
74
|
-
values() {
|
|
75
|
-
return this.schemaInput.data;
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
watch: {
|
|
79
|
-
schemaInput: {
|
|
80
|
-
deep: true,
|
|
81
|
-
handler() {
|
|
82
|
-
if (!this.schemaInput.hasErrors) {
|
|
83
|
-
this.next = this.schemaInput.data;
|
|
84
|
-
}
|
|
85
|
-
// Our validate method was called first before that of
|
|
86
|
-
// the subfields, so remedy that by calling again on any
|
|
87
|
-
// change to the subfield state during validation
|
|
88
|
-
if (this.triggerValidation) {
|
|
89
|
-
this.validateAndEmit();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
generation() {
|
|
94
|
-
this.next = this.getNext();
|
|
95
|
-
this.schemaInput = {
|
|
96
|
-
data: this.next
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
async created() {
|
|
101
|
-
await this.evaluateExternalConditions();
|
|
102
|
-
},
|
|
103
|
-
methods: {
|
|
104
|
-
validate (value) {
|
|
105
|
-
if (this.schemaInput.hasErrors) {
|
|
106
|
-
return 'invalid';
|
|
107
|
-
}
|
|
108
|
-
},
|
|
109
|
-
// Return next at mount or when generation changes
|
|
110
|
-
getNext() {
|
|
111
|
-
return this.value ? this.value.data : (this.field.def || {});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
33
|
+
mixins: [ AposInputObjectLogic ]
|
|
114
34
|
};
|
|
115
35
|
</script>
|
|
116
36
|
|
|
@@ -23,44 +23,9 @@
|
|
|
23
23
|
</template>
|
|
24
24
|
|
|
25
25
|
<script>
|
|
26
|
-
import
|
|
27
|
-
|
|
26
|
+
import AposInputPasswordLogic from '../logic/AposInputPassword';
|
|
28
27
|
export default {
|
|
29
28
|
name: 'AposInputPassword',
|
|
30
|
-
mixins: [
|
|
31
|
-
emits: [ 'return' ],
|
|
32
|
-
computed: {
|
|
33
|
-
tabindex () {
|
|
34
|
-
return this.field.disableFocus ? '-1' : '0';
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
methods: {
|
|
38
|
-
validate(value) {
|
|
39
|
-
if (this.field.required) {
|
|
40
|
-
if (!value.length) {
|
|
41
|
-
return { message: 'required' };
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (this.field.min) {
|
|
45
|
-
if (value.length && (value.length < this.field.min)) {
|
|
46
|
-
return {
|
|
47
|
-
message: this.$t('apostrophe:passwordErrorMin', {
|
|
48
|
-
min: this.field.min
|
|
49
|
-
})
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
if (this.field.max) {
|
|
54
|
-
if (value.length && (value.length > this.field.max)) {
|
|
55
|
-
return {
|
|
56
|
-
message: this.$t('apostrophe:passwordErrorMax', {
|
|
57
|
-
max: this.field.max
|
|
58
|
-
})
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
29
|
+
mixins: [ AposInputPasswordLogic ]
|
|
65
30
|
};
|
|
66
31
|
</script>
|
|
@@ -42,34 +42,10 @@
|
|
|
42
42
|
</template>
|
|
43
43
|
|
|
44
44
|
<script>
|
|
45
|
-
import
|
|
46
|
-
import AposInputChoicesMixin from 'Modules/@apostrophecms/schema/mixins/AposInputChoicesMixin';
|
|
47
|
-
import InformationIcon from 'vue-material-design-icons/Information.vue';
|
|
48
|
-
|
|
45
|
+
import AposInputRadioLogic from '../logic/AposInputRadio';
|
|
49
46
|
export default {
|
|
50
47
|
name: 'AposInputRadio',
|
|
51
|
-
|
|
52
|
-
mixins: [ AposInputMixin, AposInputChoicesMixin ],
|
|
53
|
-
methods: {
|
|
54
|
-
getChoiceId(uid, value) {
|
|
55
|
-
return (uid + JSON.stringify(value)).replace(/\s+/g, '');
|
|
56
|
-
},
|
|
57
|
-
validate(value) {
|
|
58
|
-
if (this.field.required && (value === '')) {
|
|
59
|
-
return 'required';
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (value && !this.choices.find(choice => choice.value === value)) {
|
|
63
|
-
return 'invalid';
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return false;
|
|
67
|
-
},
|
|
68
|
-
change(value) {
|
|
69
|
-
// Allows expression of non-string values
|
|
70
|
-
this.next = this.choices.find(choice => choice.value === JSON.parse(value)).value;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
48
|
+
mixins: [ AposInputRadioLogic ]
|
|
73
49
|
};
|
|
74
50
|
</script>
|
|
75
51
|
|
|
@@ -51,65 +51,10 @@
|
|
|
51
51
|
</template>
|
|
52
52
|
|
|
53
53
|
<script>
|
|
54
|
-
import
|
|
55
|
-
|
|
54
|
+
import AposInputRangeLogic from '../logic/AposInputRange';
|
|
56
55
|
export default {
|
|
57
56
|
name: 'AposInputRange',
|
|
58
|
-
mixins: [
|
|
59
|
-
data() {
|
|
60
|
-
return {
|
|
61
|
-
unit: this.field.unit || ''
|
|
62
|
-
};
|
|
63
|
-
},
|
|
64
|
-
computed: {
|
|
65
|
-
minLabel() {
|
|
66
|
-
return this.field.min + this.unit;
|
|
67
|
-
},
|
|
68
|
-
maxLabel() {
|
|
69
|
-
return this.field.max + this.unit;
|
|
70
|
-
},
|
|
71
|
-
valueLabel() {
|
|
72
|
-
return this.next + this.unit;
|
|
73
|
-
},
|
|
74
|
-
isSet() {
|
|
75
|
-
// Detect whether or not a range is currently unset
|
|
76
|
-
// Use this flag to hide/show UI elements
|
|
77
|
-
if (this.next >= this.field.min) {
|
|
78
|
-
return true;
|
|
79
|
-
} else {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
mounted() {
|
|
85
|
-
// The range spec defaults to a value of midway between the min and max
|
|
86
|
-
// Example: a range with an unset value and a min of 0 and max of 100 will become 50
|
|
87
|
-
// This does not allow ranges to go unset :(
|
|
88
|
-
if (!this.next) {
|
|
89
|
-
this.unset();
|
|
90
|
-
}
|
|
91
|
-
},
|
|
92
|
-
methods: {
|
|
93
|
-
// Default to a value outside the range when no def is defined,
|
|
94
|
-
// to be used as a flag.
|
|
95
|
-
// The value will be set to null later in validation
|
|
96
|
-
unset() {
|
|
97
|
-
this.next = typeof this.field.def === 'number'
|
|
98
|
-
? this.field.def
|
|
99
|
-
: this.field.min - 1;
|
|
100
|
-
},
|
|
101
|
-
validate(value) {
|
|
102
|
-
if (this.field.required) {
|
|
103
|
-
if (!value) {
|
|
104
|
-
return 'required';
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return false;
|
|
108
|
-
},
|
|
109
|
-
convert(value) {
|
|
110
|
-
return parseFloat(value);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
57
|
+
mixins: [ AposInputRangeLogic ]
|
|
113
58
|
};
|
|
114
59
|
</script>
|
|
115
60
|
|
|
@@ -76,267 +76,10 @@
|
|
|
76
76
|
</template>
|
|
77
77
|
|
|
78
78
|
<script>
|
|
79
|
-
import
|
|
80
|
-
import { klona } from 'klona';
|
|
81
|
-
|
|
79
|
+
import AposInputRelationshipLogic from '../logic/AposInputRelationship';
|
|
82
80
|
export default {
|
|
83
81
|
name: 'AposInputRelationship',
|
|
84
|
-
mixins: [
|
|
85
|
-
emits: [ 'input' ],
|
|
86
|
-
data () {
|
|
87
|
-
const next = (this.value && Array.isArray(this.value.data))
|
|
88
|
-
? klona(this.value.data) : (klona(this.field.def) || []);
|
|
89
|
-
|
|
90
|
-
// Remember relationship subfield values even if a document
|
|
91
|
-
// is temporarily deselected, easing the user's pain if they
|
|
92
|
-
// inadvertently deselect something for a moment
|
|
93
|
-
const subfields = Object.fromEntries(
|
|
94
|
-
(next || []).filter(doc => doc._fields)
|
|
95
|
-
.map(doc => [ doc._id, doc._fields ])
|
|
96
|
-
);
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
searchTerm: '',
|
|
100
|
-
searchList: [],
|
|
101
|
-
next,
|
|
102
|
-
subfields,
|
|
103
|
-
disabled: false,
|
|
104
|
-
searching: false,
|
|
105
|
-
choosing: false,
|
|
106
|
-
relationshipSchema: null
|
|
107
|
-
};
|
|
108
|
-
},
|
|
109
|
-
computed: {
|
|
110
|
-
limitReached() {
|
|
111
|
-
return this.field.max === this.next.length;
|
|
112
|
-
},
|
|
113
|
-
pluralLabel() {
|
|
114
|
-
return apos.modules[this.field.withType].pluralLabel;
|
|
115
|
-
},
|
|
116
|
-
// TODO get 'Search' server for better i18n
|
|
117
|
-
placeholder() {
|
|
118
|
-
return this.field.placeholder || {
|
|
119
|
-
key: 'apostrophe:searchDocType',
|
|
120
|
-
type: this.$t(this.pluralLabel)
|
|
121
|
-
};
|
|
122
|
-
},
|
|
123
|
-
// TODO get 'Browse' for better i18n
|
|
124
|
-
browseLabel() {
|
|
125
|
-
return {
|
|
126
|
-
key: 'apostrophe:browseDocType',
|
|
127
|
-
type: this.$t(this.pluralLabel)
|
|
128
|
-
};
|
|
129
|
-
},
|
|
130
|
-
suggestion() {
|
|
131
|
-
return {
|
|
132
|
-
disabled: true,
|
|
133
|
-
tooltip: false,
|
|
134
|
-
icon: false,
|
|
135
|
-
classes: [ 'suggestion' ],
|
|
136
|
-
title: this.$t(this.field.suggestionLabel),
|
|
137
|
-
help: this.$t({
|
|
138
|
-
key: this.field.suggestionHelp || 'apostrophe:relationshipSuggestionHelp',
|
|
139
|
-
type: this.$t(this.pluralLabel)
|
|
140
|
-
}),
|
|
141
|
-
customFields: [ 'help' ]
|
|
142
|
-
};
|
|
143
|
-
},
|
|
144
|
-
hint() {
|
|
145
|
-
return {
|
|
146
|
-
disabled: true,
|
|
147
|
-
tooltip: false,
|
|
148
|
-
icon: 'binoculars-icon',
|
|
149
|
-
iconSize: 35,
|
|
150
|
-
classes: [ 'hint' ],
|
|
151
|
-
title: this.$t('apostrophe:relationshipSuggestionNoResults'),
|
|
152
|
-
help: this.$t({
|
|
153
|
-
key: this.field.browse
|
|
154
|
-
? 'apostrophe:relationshipSuggestionSearchAndBrowse'
|
|
155
|
-
: 'apostrophe:relationshipSuggestionSearch',
|
|
156
|
-
type: this.$t(this.pluralLabel)
|
|
157
|
-
}),
|
|
158
|
-
customFields: [ 'help' ]
|
|
159
|
-
};
|
|
160
|
-
},
|
|
161
|
-
chooserComponent () {
|
|
162
|
-
return apos.modules[this.field.withType].components.managerModal;
|
|
163
|
-
},
|
|
164
|
-
disableUnpublished() {
|
|
165
|
-
return apos.modules[this.field.withType].localized;
|
|
166
|
-
},
|
|
167
|
-
buttonModifiers() {
|
|
168
|
-
const modifiers = [ 'small' ];
|
|
169
|
-
if (this.modifiers.includes('no-search')) {
|
|
170
|
-
modifiers.push('block');
|
|
171
|
-
}
|
|
172
|
-
return modifiers;
|
|
173
|
-
},
|
|
174
|
-
minSize() {
|
|
175
|
-
const [ widgetOptions = {} ] = apos.area.widgetOptions;
|
|
176
|
-
|
|
177
|
-
return widgetOptions.minSize || [];
|
|
178
|
-
},
|
|
179
|
-
duplicate () {
|
|
180
|
-
return this.value.duplicate ? 'apos-input--error' : null;
|
|
181
|
-
}
|
|
182
|
-
},
|
|
183
|
-
watch: {
|
|
184
|
-
next(after, before) {
|
|
185
|
-
for (const doc of before) {
|
|
186
|
-
this.subfields[doc._id] = doc._fields;
|
|
187
|
-
}
|
|
188
|
-
for (const doc of after) {
|
|
189
|
-
if (Object.keys(doc._fields || {}).length) {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
doc._fields = this.field.schema && (this.subfields[doc._id]
|
|
193
|
-
? this.subfields[doc._id]
|
|
194
|
-
: this.getDefault());
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
},
|
|
198
|
-
mounted () {
|
|
199
|
-
this.checkLimit();
|
|
200
|
-
},
|
|
201
|
-
methods: {
|
|
202
|
-
validate(value) {
|
|
203
|
-
this.checkLimit();
|
|
204
|
-
|
|
205
|
-
if (this.field.required && !value.length) {
|
|
206
|
-
return { message: 'required' };
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (this.field.min && this.field.min > value.length) {
|
|
210
|
-
return { message: `minimum of ${this.field.min} required` };
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return false;
|
|
214
|
-
},
|
|
215
|
-
checkLimit() {
|
|
216
|
-
if (this.limitReached) {
|
|
217
|
-
this.searchTerm = 'Limit reached!';
|
|
218
|
-
} else if (this.searchTerm === 'Limit reached!') {
|
|
219
|
-
this.searchTerm = '';
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
this.disabled = !!this.limitReached;
|
|
223
|
-
},
|
|
224
|
-
updateSelected(items) {
|
|
225
|
-
this.next = items;
|
|
226
|
-
},
|
|
227
|
-
async search(qs) {
|
|
228
|
-
if (this.field.suggestionLimit) {
|
|
229
|
-
qs.perPage = this.field.suggestionLimit;
|
|
230
|
-
}
|
|
231
|
-
if (this.field.suggestionSort) {
|
|
232
|
-
qs.sort = this.field.suggestionSort;
|
|
233
|
-
}
|
|
234
|
-
if (this.field.withType === '@apostrophecms/image') {
|
|
235
|
-
apos.bus.$emit('piece-relationship-query', qs);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
this.searching = true;
|
|
239
|
-
const list = await apos.http.get(
|
|
240
|
-
apos.modules[this.field.withType].action,
|
|
241
|
-
{
|
|
242
|
-
busy: false,
|
|
243
|
-
draft: true,
|
|
244
|
-
qs
|
|
245
|
-
}
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
const removeSelectedItem = item => !this.next.map(i => i._id).includes(item._id);
|
|
249
|
-
const formatItems = item => ({
|
|
250
|
-
...item,
|
|
251
|
-
disabled: this.disableUnpublished && !item.lastPublishedAt
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
const results = (list.results || [])
|
|
255
|
-
.filter(removeSelectedItem)
|
|
256
|
-
.map(formatItems);
|
|
257
|
-
|
|
258
|
-
const suggestion = !qs.autocomplete && this.suggestion;
|
|
259
|
-
const hint = (!qs.autocomplete || !results.length) && this.hint;
|
|
260
|
-
|
|
261
|
-
this.searchList = [ suggestion, ...results, hint ].filter(Boolean);
|
|
262
|
-
this.searching = false;
|
|
263
|
-
},
|
|
264
|
-
async input () {
|
|
265
|
-
if (this.searching) {
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
const trimmed = this.searchTerm.trim();
|
|
270
|
-
const qs = trimmed.length
|
|
271
|
-
? {
|
|
272
|
-
autocomplete: trimmed
|
|
273
|
-
}
|
|
274
|
-
: {};
|
|
275
|
-
|
|
276
|
-
await this.search(qs);
|
|
277
|
-
},
|
|
278
|
-
handleFocusOut() {
|
|
279
|
-
// hide search list when click outside the input
|
|
280
|
-
// timeout to execute "@select" method before
|
|
281
|
-
setTimeout(() => {
|
|
282
|
-
this.searchList = [];
|
|
283
|
-
}, 200);
|
|
284
|
-
},
|
|
285
|
-
watchValue () {
|
|
286
|
-
this.error = this.value.error;
|
|
287
|
-
// Ensure the internal state is an array.
|
|
288
|
-
this.next = Array.isArray(this.value.data) ? this.value.data : [];
|
|
289
|
-
},
|
|
290
|
-
async choose () {
|
|
291
|
-
const result = await apos.modal.execute(this.chooserComponent, {
|
|
292
|
-
title: this.field.label || this.field.name,
|
|
293
|
-
moduleName: this.field.withType,
|
|
294
|
-
chosen: this.next,
|
|
295
|
-
relationshipField: this.field
|
|
296
|
-
});
|
|
297
|
-
if (result) {
|
|
298
|
-
this.updateSelected(result);
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
async editRelationship (item) {
|
|
302
|
-
const editor = this.field.editor || 'AposRelationshipEditor';
|
|
303
|
-
|
|
304
|
-
const result = await apos.modal.execute(editor, {
|
|
305
|
-
schema: this.field.schema,
|
|
306
|
-
item,
|
|
307
|
-
title: item.title,
|
|
308
|
-
value: item._fields
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
if (result) {
|
|
312
|
-
const index = this.next.findIndex(_item => _item._id === item._id);
|
|
313
|
-
this.$set(this.next, index, {
|
|
314
|
-
...this.next[index],
|
|
315
|
-
_fields: result
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
},
|
|
319
|
-
getEditRelationshipLabel () {
|
|
320
|
-
if (this.field.editor === 'AposImageRelationshipEditor') {
|
|
321
|
-
return 'apostrophe:editImageAdjustments';
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
|
-
getDefault() {
|
|
325
|
-
const object = {};
|
|
326
|
-
this.field.schema.forEach(field => {
|
|
327
|
-
if (field.name.startsWith('_')) {
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
// Using `hasOwn` here, not simply checking if `field.def` is truthy
|
|
331
|
-
// so that `false`, `null`, `''` or `0` are taken into account:
|
|
332
|
-
const hasDefaultValue = Object.hasOwn(field, 'def');
|
|
333
|
-
object[field.name] = hasDefaultValue
|
|
334
|
-
? klona(field.def)
|
|
335
|
-
: null;
|
|
336
|
-
});
|
|
337
|
-
return object;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
82
|
+
mixins: [ AposInputRelationshipLogic ]
|
|
340
83
|
};
|
|
341
84
|
</script>
|
|
342
85
|
|
|
@@ -20,45 +20,9 @@
|
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
22
|
<script>
|
|
23
|
-
import
|
|
24
|
-
import AposInputChoicesMixin from 'Modules/@apostrophecms/schema/mixins/AposInputChoicesMixin';
|
|
25
|
-
|
|
23
|
+
import AposInputSelectLogic from '../logic/AposInputSelect';
|
|
26
24
|
export default {
|
|
27
25
|
name: 'AposInputSelect',
|
|
28
|
-
mixins: [
|
|
29
|
-
props: {
|
|
30
|
-
icon: {
|
|
31
|
-
type: String,
|
|
32
|
-
default: 'menu-down-icon'
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
data() {
|
|
36
|
-
return {
|
|
37
|
-
next: (this.value.data == null) ? null : this.value.data,
|
|
38
|
-
choices: []
|
|
39
|
-
};
|
|
40
|
-
},
|
|
41
|
-
computed: {
|
|
42
|
-
classes () {
|
|
43
|
-
return [ this.value.duplicate && 'apos-input--error' ];
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
methods: {
|
|
47
|
-
validate(value) {
|
|
48
|
-
if (this.field.required && (value === null)) {
|
|
49
|
-
return 'required';
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (value && !this.choices.find(choice => choice.value === value)) {
|
|
53
|
-
return 'invalid';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return false;
|
|
57
|
-
},
|
|
58
|
-
change(value) {
|
|
59
|
-
// Allows expression of non-string values
|
|
60
|
-
this.next = this.choices.find(choice => choice.value === value).value;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
26
|
+
mixins: [ AposInputSelectLogic ]
|
|
63
27
|
};
|
|
64
28
|
</script>
|