apostrophe 3.63.3 → 4.1.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.
Files changed (184) hide show
  1. package/.eslintrc +13 -4
  2. package/CHANGELOG.md +37 -5
  3. package/defaults.js +2 -1
  4. package/modules/@apostrophecms/admin-bar/ui/apos/apps/AposAdminBar.js +7 -17
  5. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBar.vue +14 -16
  6. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarLocale.vue +1 -1
  7. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarMenu.vue +22 -15
  8. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarUser.vue +2 -2
  9. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextBar.vue +13 -8
  10. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +18 -10
  11. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +4 -4
  12. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextUndoRedo.vue +14 -8
  13. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposSavingIndicator.vue +2 -1
  14. package/modules/@apostrophecms/area/ui/apos/apps/AposAreas.js +36 -54
  15. package/modules/@apostrophecms/area/ui/apos/components/AposAreaContextualMenu.vue +20 -25
  16. package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +5 -12
  17. package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +11 -3
  18. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +6 -6
  19. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenuItem.vue +3 -2
  20. package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +31 -44
  21. package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +16 -16
  22. package/modules/@apostrophecms/asset/index.js +25 -12
  23. package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.config.js +3 -3
  24. package/modules/@apostrophecms/asset/lib/webpack/apos/webpack.vue.js +7 -1
  25. package/modules/@apostrophecms/attachment/index.js +2 -1
  26. package/modules/@apostrophecms/attachment/public/img/missing-icon.svg +14 -0
  27. package/modules/@apostrophecms/busy/ui/apos/apps/AposBusy.js +8 -7
  28. package/modules/@apostrophecms/busy/ui/apos/components/TheAposBusy.vue +1 -1
  29. package/modules/@apostrophecms/command-menu/ui/apos/apps/AposCommandMenu.js +11 -29
  30. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuKey.vue +1 -1
  31. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuShortcut.vue +6 -6
  32. package/modules/@apostrophecms/command-menu/ui/apos/components/TheAposCommandMenu.vue +10 -7
  33. package/modules/@apostrophecms/doc-type/index.js +34 -13
  34. package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocContextMenu.vue +3 -3
  35. package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +20 -15
  36. package/modules/@apostrophecms/doc-type/ui/apos/logic/AposDocContextMenu.js +1 -1
  37. package/modules/@apostrophecms/i18n/i18n/en.json +13 -0
  38. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +209 -33
  39. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalizeErrors.vue +3 -3
  40. package/modules/@apostrophecms/image/ui/apos/components/AposImageCropper.vue +5 -5
  41. package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +6 -6
  42. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +23 -16
  43. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerDisplay.vue +11 -11
  44. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerEditor.vue +28 -21
  45. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerSelections.vue +4 -3
  46. package/modules/@apostrophecms/image/ui/apos/components/AposMediaUploader.vue +5 -4
  47. package/modules/@apostrophecms/login/index.js +18 -1
  48. package/modules/@apostrophecms/login/ui/apos/apps/AposLogin.js +6 -7
  49. package/modules/@apostrophecms/login/ui/apos/components/AposForgotPasswordForm.vue +3 -3
  50. package/modules/@apostrophecms/login/ui/apos/components/AposLoginForm.vue +10 -10
  51. package/modules/@apostrophecms/login/ui/apos/components/AposResetPasswordForm.vue +3 -3
  52. package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +2 -2
  53. package/modules/@apostrophecms/login/ui/apos/logic/AposLoginForm.js +1 -16
  54. package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +60 -87
  55. package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +15 -11
  56. package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +17 -11
  57. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBreadcrumbs.vue +7 -4
  58. package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +9 -9
  59. package/modules/@apostrophecms/modal/ui/apos/components/AposModalLip.vue +2 -2
  60. package/modules/@apostrophecms/modal/ui/apos/components/AposModalShareDraft.vue +8 -8
  61. package/modules/@apostrophecms/modal/ui/apos/components/AposModalTabs.vue +4 -3
  62. package/modules/@apostrophecms/modal/ui/apos/components/AposModalToolbar.vue +7 -7
  63. package/modules/@apostrophecms/modal/ui/apos/components/TheAposModals.vue +22 -4
  64. package/modules/@apostrophecms/modal/ui/apos/composables/AposFocus.js +95 -0
  65. package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +2 -3
  66. package/modules/@apostrophecms/modal/ui/apos/mixins/AposEditorMixin.js +6 -0
  67. package/modules/@apostrophecms/notification/index.js +4 -4
  68. package/modules/@apostrophecms/notification/ui/apos/apps/AposNotification.js +6 -9
  69. package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +12 -8
  70. package/modules/@apostrophecms/notification/ui/apos/components/TheAposNotifications.vue +4 -2
  71. package/modules/@apostrophecms/oembed-field/ui/apos/components/AposInputOembed.vue +12 -10
  72. package/modules/@apostrophecms/page/index.js +1 -0
  73. package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +15 -11
  74. package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +1 -1
  75. package/modules/@apostrophecms/permission/ui/apos/components/AposInputRole.vue +3 -3
  76. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +25 -17
  77. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerDisplay.vue +24 -20
  78. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +9 -5
  79. package/modules/@apostrophecms/piece-type/ui/apos/components/AposRelationshipEditor.vue +15 -11
  80. package/modules/@apostrophecms/rich-text-widget/index.js +1 -0
  81. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposImageControlDialog.vue +7 -6
  82. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +31 -30
  83. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapAnchor.vue +12 -10
  84. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapButton.vue +1 -1
  85. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapImage.vue +1 -1
  86. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapLink.vue +9 -8
  87. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapStyles.vue +3 -3
  88. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapTable.vue +3 -3
  89. package/modules/@apostrophecms/schema/index.js +69 -8
  90. package/modules/@apostrophecms/schema/lib/addFieldTypes.js +1 -1
  91. package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +10 -8
  92. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +5 -3
  93. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArray.vue +81 -277
  94. package/modules/@apostrophecms/schema/ui/apos/components/AposInputAttachment.vue +4 -2
  95. package/modules/@apostrophecms/schema/ui/apos/components/AposInputBoolean.vue +24 -14
  96. package/modules/@apostrophecms/schema/ui/apos/components/AposInputCheckboxes.vue +7 -6
  97. package/modules/@apostrophecms/schema/ui/apos/components/AposInputColor.vue +10 -7
  98. package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +3 -3
  99. package/modules/@apostrophecms/schema/ui/apos/components/AposInputPassword.vue +6 -4
  100. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +5 -4
  101. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRange.vue +9 -6
  102. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +15 -12
  103. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSelect.vue +1 -1
  104. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +16 -12
  105. package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +19 -11
  106. package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +15 -12
  107. package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +75 -22
  108. package/modules/@apostrophecms/schema/ui/apos/components/AposSearchList.vue +1 -1
  109. package/modules/@apostrophecms/schema/ui/apos/components/AposSubform.vue +2 -2
  110. package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +0 -4
  111. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArea.js +3 -3
  112. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputArray.js +15 -4
  113. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputAttachment.js +3 -3
  114. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputCheckboxes.js +7 -7
  115. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputColor.js +5 -8
  116. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputDateAndTime.js +1 -1
  117. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputObject.js +1 -1
  118. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRadio.js +1 -1
  119. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +12 -9
  120. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputSelect.js +3 -3
  121. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +7 -9
  122. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +4 -4
  123. package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +42 -13
  124. package/modules/@apostrophecms/schema/ui/apos/logic/AposSubform.js +1 -1
  125. package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +9 -9
  126. package/modules/@apostrophecms/schema/ui/apos/scss/AposInputArray.scss +205 -0
  127. package/modules/@apostrophecms/settings/ui/apos/components/AposSettingsManager.vue +5 -5
  128. package/modules/@apostrophecms/settings/ui/apos/logic/AposSettingsManager.js +4 -4
  129. package/modules/@apostrophecms/submitted-draft/ui/apos/components/AposSubmittedDraftIcon.vue +5 -4
  130. package/modules/@apostrophecms/task/index.js +2 -0
  131. package/modules/@apostrophecms/translation/index.js +233 -0
  132. package/modules/@apostrophecms/translation/ui/apos/components/AposTranslationIndicator.vue +84 -0
  133. package/modules/@apostrophecms/ui/ui/apos/components/AposAvatar.vue +2 -1
  134. package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +4 -4
  135. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonGroup.vue +6 -6
  136. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonSplit.vue +120 -113
  137. package/modules/@apostrophecms/ui/ui/apos/components/AposCellButton.vue +2 -1
  138. package/modules/@apostrophecms/ui/ui/apos/components/AposCellLabels.vue +49 -5
  139. package/modules/@apostrophecms/ui/ui/apos/components/AposCheckbox.vue +19 -19
  140. package/modules/@apostrophecms/ui/ui/apos/components/AposCloudUploadIcon.vue +10 -5
  141. package/modules/@apostrophecms/ui/ui/apos/components/AposCombo.vue +15 -15
  142. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +214 -191
  143. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +77 -65
  144. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +1 -1
  145. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuTip.vue +28 -50
  146. package/modules/@apostrophecms/ui/ui/apos/components/AposEmptyState.vue +3 -3
  147. package/modules/@apostrophecms/ui/ui/apos/components/AposFile.vue +5 -5
  148. package/modules/@apostrophecms/ui/ui/apos/components/AposFilterMenu.vue +4 -4
  149. package/modules/@apostrophecms/ui/ui/apos/components/AposIndicator.vue +1 -1
  150. package/modules/@apostrophecms/ui/ui/apos/components/AposLabel.vue +1 -1
  151. package/modules/@apostrophecms/ui/ui/apos/components/AposMinMaxCount.vue +5 -5
  152. package/modules/@apostrophecms/ui/ui/apos/components/AposPager.vue +14 -8
  153. package/modules/@apostrophecms/ui/ui/apos/components/AposPagerDots.vue +2 -1
  154. package/modules/@apostrophecms/ui/ui/apos/components/AposSlat.vue +13 -12
  155. package/modules/@apostrophecms/ui/ui/apos/components/AposSlatList.vue +53 -59
  156. package/modules/@apostrophecms/ui/ui/apos/components/AposSpinner.vue +2 -2
  157. package/modules/@apostrophecms/ui/ui/apos/components/AposSubformPreview.vue +2 -2
  158. package/modules/@apostrophecms/ui/ui/apos/components/AposTag.vue +3 -2
  159. package/modules/@apostrophecms/ui/ui/apos/components/AposTagApply.vue +40 -35
  160. package/modules/@apostrophecms/ui/ui/apos/components/AposTagListItem.vue +2 -1
  161. package/modules/@apostrophecms/ui/ui/apos/components/AposToggle.vue +2 -2
  162. package/modules/@apostrophecms/ui/ui/apos/components/AposTree.vue +9 -11
  163. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeHeader.vue +5 -3
  164. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeRows.vue +129 -129
  165. package/modules/@apostrophecms/ui/ui/apos/composables/AposTheme.js +11 -0
  166. package/modules/@apostrophecms/ui/ui/apos/lib/click-outside-element.js +4 -4
  167. package/modules/@apostrophecms/ui/ui/apos/lib/i18next.js +56 -50
  168. package/modules/@apostrophecms/ui/ui/apos/lib/tooltip.js +191 -0
  169. package/modules/@apostrophecms/ui/ui/apos/lib/vue.js +19 -10
  170. package/modules/@apostrophecms/ui/ui/apos/mixins/AposAdvisoryLockMixin.js +1 -1
  171. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tables.scss +1 -1
  172. package/modules/@apostrophecms/ui/ui/apos/scss/global/_theme.scss +1 -0
  173. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tooltips.scss +6 -22
  174. package/modules/@apostrophecms/ui/ui/apos/scss/shared/_table-rows.scss +1 -1
  175. package/modules/@apostrophecms/widget-type/index.js +8 -2
  176. package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +26 -22
  177. package/modules/@apostrophecms/widget-type/ui/apos/mixins/AposWidgetMixin.js +4 -4
  178. package/package.json +31 -44
  179. package/test/attachments.js +5 -0
  180. package/test/schemas.js +138 -0
  181. package/test/translation.js +538 -0
  182. package/test-lib/util.js +21 -0
  183. package/modules/@apostrophecms/ui/ui/apos/lib/localized-v-tooltip.js +0 -63
  184. package/modules/@apostrophecms/ui/ui/apos/lib/tooltip-options.js +0 -13
@@ -106,7 +106,7 @@ export default {
106
106
  },
107
107
  // Return next at mount or when generation changes
108
108
  getNext() {
109
- return this.value?.data ? this.value.data : (this.field.def || {});
109
+ return this.modelValue?.data ? this.modelValue.data : (this.field.def || {});
110
110
  }
111
111
  }
112
112
  };
@@ -1,6 +1,6 @@
1
1
  import AposInputMixin from 'Modules/@apostrophecms/schema/mixins/AposInputMixin';
2
2
  import AposInputChoicesMixin from 'Modules/@apostrophecms/schema/mixins/AposInputChoicesMixin';
3
- import InformationIcon from 'vue-material-design-icons/Information.vue';
3
+ import InformationIcon from '@apostrophecms/vue-material-design-icons/Information.vue';
4
4
 
5
5
  export default {
6
6
  name: 'AposInputRadio',
@@ -6,8 +6,8 @@ export default {
6
6
  mixins: [ AposInputMixin ],
7
7
  emits: [ 'input' ],
8
8
  data () {
9
- const next = (this.value && Array.isArray(this.value.data))
10
- ? klona(this.value.data) : (klona(this.field.def) || []);
9
+ const next = (this.modelValue && Array.isArray(this.modelValue.data))
10
+ ? klona(this.modelValue.data) : (klona(this.field.def) || []);
11
11
 
12
12
  // Remember relationship subfield values even if a document
13
13
  // is temporarily deselected, easing the user's pain if they
@@ -99,7 +99,7 @@ export default {
99
99
  return widgetOptions.minSize || [];
100
100
  },
101
101
  duplicate () {
102
- return this.value.duplicate ? 'apos-input--error' : null;
102
+ return this.modelValue?.duplicate ? 'apos-input--error' : null;
103
103
  }
104
104
  },
105
105
  watch: {
@@ -209,9 +209,9 @@ export default {
209
209
  }, 200);
210
210
  },
211
211
  watchValue () {
212
- this.error = this.value.error;
212
+ this.error = this.modelValue.error;
213
213
  // Ensure the internal state is an array.
214
- this.next = Array.isArray(this.value.data) ? this.value.data : [];
214
+ this.next = Array.isArray(this.modelValue.data) ? this.modelValue.data : [];
215
215
  },
216
216
  async choose () {
217
217
  const result = await apos.modal.execute(this.chooserComponent, {
@@ -231,14 +231,17 @@ export default {
231
231
  schema: this.field.schema,
232
232
  item,
233
233
  title: item.title,
234
- value: item._fields
234
+ 'model-value': item._fields
235
235
  });
236
236
 
237
237
  if (result) {
238
238
  const index = this.next.findIndex(_item => _item._id === item._id);
239
- this.$set(this.next, index, {
240
- ...this.next[index],
241
- _fields: result
239
+
240
+ this.next = this.next.map((item, i) => {
241
+ return i === index ? {
242
+ ...item,
243
+ _fields: result
244
+ } : item;
242
245
  });
243
246
  }
244
247
  },
@@ -12,13 +12,13 @@ export default {
12
12
  },
13
13
  data() {
14
14
  return {
15
- next: (this.value.data == null) ? null : this.value.data,
15
+ next: (this.modelValue.data == null) ? null : this.modelValue.data,
16
16
  choices: []
17
17
  };
18
18
  },
19
19
  computed: {
20
- classes () {
21
- return [ this.value.duplicate && 'apos-input--error' ];
20
+ classes() {
21
+ return [ this.modelValue?.duplicate && 'apos-input--error' ];
22
22
  }
23
23
  },
24
24
  methods: {
@@ -27,8 +27,8 @@ export default {
27
27
  return 'text';
28
28
  }
29
29
  },
30
- classes () {
31
- return [ 'apos-input', `apos-input--${this.type}`, this.value.duplicate && 'apos-input--error' ];
30
+ classes() {
31
+ return [ 'apos-input', `apos-input--${this.type}`, this.modelValue?.duplicate && 'apos-input--error' ];
32
32
  },
33
33
  icon () {
34
34
  if (this.error) {
@@ -78,11 +78,9 @@ export default {
78
78
  this.$emit('return');
79
79
  }
80
80
  },
81
- validate(value) {
82
- if (value == null) {
83
- value = '';
84
- }
85
- if (typeof value === 'string' && !value.length) {
81
+ validate(value = '') {
82
+ const isString = typeof value === 'string';
83
+ if (isString && !value.length) {
86
84
  // Also correct for float and integer because Vue coerces
87
85
  // number fields to either a number or the empty string
88
86
  return this.field.required ? 'required' : false;
@@ -104,12 +102,12 @@ export default {
104
102
  }
105
103
 
106
104
  if (this.field.min && minMaxFields.includes(this.field.type)) {
107
- if ((value != null) && value.length && (this.minMaxComparable(value) < this.field.min)) {
105
+ if ((!isString || value.length) && (this.minMaxComparable(value) < this.field.min)) {
108
106
  return 'min';
109
107
  }
110
108
  }
111
109
  if (this.field.max && minMaxFields.includes(this.field.type)) {
112
- if ((value != null) && value.length && (this.minMaxComparable(value) > this.field.max)) {
110
+ if ((!isString || value.length) && (this.minMaxComparable(value) > this.field.max)) {
113
111
  return 'max';
114
112
  }
115
113
  }
@@ -135,11 +135,11 @@ export default {
135
135
  }
136
136
 
137
137
  return apos.schema.fieldMetadataComponents
138
- .map(component => {
138
+ .map(({ name, namespace }) => {
139
139
  return {
140
- name: component.name,
141
- namespace: component.namespace,
142
- data: meta[component.namespace] || {}
140
+ name,
141
+ namespace: namespace,
142
+ data: meta[namespace] || {}
143
143
  };
144
144
  });
145
145
  }
@@ -4,7 +4,7 @@ import { getConditionTypesObject } from '../lib/conditionalFields';
4
4
  export default {
5
5
  name: 'AposSchema',
6
6
  props: {
7
- value: {
7
+ modelValue: {
8
8
  type: Object,
9
9
  required: true
10
10
  },
@@ -87,7 +87,7 @@ export default {
87
87
  }
88
88
  },
89
89
  emits: [
90
- 'input',
90
+ 'update:model-value',
91
91
  'reset',
92
92
  'validate',
93
93
  'update-doc-data'
@@ -120,7 +120,7 @@ export default {
120
120
  required
121
121
  },
122
122
  value: {
123
- data: this.value[item.name]
123
+ data: this.modelValue[item.name]
124
124
  },
125
125
  serverError: this.serverErrors && this.serverErrors[item.name],
126
126
  modifiers: [
@@ -130,6 +130,32 @@ export default {
130
130
  }
131
131
  };
132
132
  }, {});
133
+ },
134
+ hasCompareMeta() {
135
+ return this.schema.some(field => this.meta[field.name]?.['@apostrophecms/schema:compare']);
136
+ },
137
+ classes() {
138
+ const classes = [];
139
+ if (this.hasCompareMeta) {
140
+ classes.push('apos-schema--compare');
141
+ }
142
+
143
+ return classes;
144
+ },
145
+ compareMetaState() {
146
+ if (!this.hasCompareMeta) {
147
+ return {};
148
+ }
149
+
150
+ const compareMetaState = {};
151
+ this.schema.forEach(field => {
152
+ compareMetaState[field.name] = {
153
+ error: false,
154
+ data: this.meta[field.name]?.['@apostrophecms/schema:compare']
155
+ };
156
+ });
157
+
158
+ return compareMetaState;
133
159
  }
134
160
  },
135
161
  watch: {
@@ -142,7 +168,7 @@ export default {
142
168
  schema() {
143
169
  this.populateDocData();
144
170
  },
145
- 'value.data._id'(_id) {
171
+ 'modelValue.data._id'(_id) {
146
172
  // The doc might be swapped out completely in cases such as the media
147
173
  // library editor. Repopulate the fields if that happens.
148
174
  if (
@@ -207,18 +233,18 @@ export default {
207
233
  const fieldState = {};
208
234
 
209
235
  // Though not in the schema, keep track of the _id field.
210
- if (this.value.data._id) {
211
- next.data._id = this.value.data._id;
212
- fieldState._id = { data: this.value.data._id };
236
+ if (this.modelValue.data._id) {
237
+ next.data._id = this.modelValue.data._id;
238
+ fieldState._id = { data: this.modelValue.data._id };
213
239
  }
214
240
  // Though not *always* in the schema, keep track of the archived status.
215
- if (this.value.data.archived !== undefined) {
216
- next.data.archived = this.value.data.archived;
217
- fieldState.archived = { data: this.value.data.archived };
241
+ if (this.modelValue.data.archived !== undefined) {
242
+ next.data.archived = this.modelValue.data.archived;
243
+ fieldState.archived = { data: this.modelValue.data.archived };
218
244
  }
219
245
 
220
246
  this.schema.forEach(field => {
221
- const value = this.value.data[field.name];
247
+ const value = this.modelValue.data[field.name];
222
248
  fieldState[field.name] = {
223
249
  error: false,
224
250
  data: (value === undefined) ? field.def : value
@@ -262,7 +288,7 @@ export default {
262
288
  changeFound = true;
263
289
  this.next.data[field.name] = this.fieldState[field.name].data;
264
290
  } else {
265
- this.next.data[field.name] = this.value.data[field.name];
291
+ this.next.data[field.name] = this.modelValue.data[field.name];
266
292
  }
267
293
  });
268
294
  if (
@@ -275,7 +301,7 @@ export default {
275
301
 
276
302
  if (changeFound) {
277
303
  // ... removes need for deep watch at parent level
278
- this.$emit('input', { ...this.next });
304
+ this.$emit('update:model-value', { ...this.next });
279
305
  }
280
306
  },
281
307
  displayComponent({ name, hidden = false }) {
@@ -302,6 +328,9 @@ export default {
302
328
  },
303
329
  onUpdateDocData(data) {
304
330
  this.$emit('update-doc-data', data);
331
+ },
332
+ highlight(fieldName) {
333
+ return this.meta[fieldName]?.['@apostrophecms/schema:highlight'];
305
334
  }
306
335
  }
307
336
  };
@@ -93,7 +93,7 @@ export default {
93
93
  this.evaluateConditions();
94
94
  this.docFields.data = klona(this.values);
95
95
  },
96
- beforeDestroy() {
96
+ beforeUnmount() {
97
97
  clearTimeout(this.scrollTimeout);
98
98
  },
99
99
  methods: {
@@ -2,11 +2,11 @@ import { klona } from 'klona';
2
2
 
3
3
  export default {
4
4
  // Implements v-model pattern
5
- emits: [ 'input' ],
5
+ emits: [ 'update:modelValue' ],
6
6
  props: {
7
7
  // The value passed in from the parent component through the v-model
8
8
  // directive.
9
- value: {
9
+ modelValue: {
10
10
  type: Object,
11
11
  required: true
12
12
  },
@@ -59,7 +59,7 @@ export default {
59
59
  },
60
60
  data () {
61
61
  return {
62
- next: (this.value && this.value.data !== undefined) ? this.value.data : '',
62
+ next: (this.modelValue && this.modelValue.data !== undefined) ? this.modelValue.data : '',
63
63
  error: false,
64
64
  // This is just meant to be sufficient to prevent unintended collisions
65
65
  // in the UI between id attributes
@@ -72,7 +72,7 @@ export default {
72
72
  this.$el.addEventListener('focusin', this.focusInListener);
73
73
  this.$el.addEventListener('focusout', this.focusOutListener);
74
74
  },
75
- destroyed () {
75
+ unmounted () {
76
76
  this.$el.removeEventListener('focusin', this.focusInListener);
77
77
  this.$el.removeEventListener('focusout', this.focusOutListener);
78
78
  },
@@ -102,7 +102,7 @@ export default {
102
102
  }
103
103
  },
104
104
  watch: {
105
- value: {
105
+ modelValue: {
106
106
  deep: true,
107
107
  handler (value) {
108
108
  this.watchValue();
@@ -134,15 +134,15 @@ export default {
134
134
  // If the field is conditional and isn't shown, disregard any errors.
135
135
  const error = this.conditionMet === false ? false : this.validate(this.next);
136
136
 
137
- this.$emit('input', {
137
+ this.$emit('update:modelValue', {
138
138
  data: error ? this.next : this.convert(this.next),
139
139
  error,
140
- ranValidation: this.conditionMet === false ? this.value.ranValidation : true
140
+ ranValidation: this.conditionMet === false ? this.modelValue.ranValidation : true
141
141
  });
142
142
  },
143
143
  watchValue () {
144
- this.error = this.value.error;
145
- this.next = this.value.data;
144
+ this.error = this.modelValue.error;
145
+ this.next = this.modelValue.data;
146
146
  },
147
147
  watchNext () {
148
148
  this.validateAndEmit();
@@ -0,0 +1,205 @@
1
+ .apos-schema {
2
+ padding-top: $spacing-base;
3
+ padding-bottom: $spacing-base;
4
+ }
5
+
6
+ :deep(.apos-field--array.apos-field--error-duplicate) {
7
+ .apos-input {
8
+ border-color: var(--a-base-8);
9
+ }
10
+ .apos-input:focus {
11
+ box-shadow: 0 0 3px var(--a-base-8);
12
+ }
13
+ .apos-input-icon {
14
+ color: var(--a-base-2);
15
+ }
16
+ .apos-input--error {
17
+ border-color: var(--a-danger);
18
+ }
19
+ }
20
+ :deep(.apos-input-relationship) {
21
+ .apos-slat__main {
22
+ min-width: 130px;
23
+ }
24
+ }
25
+ .apos-is-dragging {
26
+ opacity: 0.5;
27
+ background: var(--a-base-4);
28
+ }
29
+ .apos-input-array-inline-empty {
30
+ display: flex;
31
+ flex-direction: column;
32
+ justify-content: center;
33
+ align-items: center;
34
+ margin-bottom: $spacing-base;
35
+ padding: $spacing-triple 0;
36
+ border: 1px solid var(--a-base-9);
37
+ color: var(--a-base-8);
38
+ }
39
+ .apos-input-array-inline-empty-label {
40
+ @include type-label;
41
+ color: var(--a-base-3);
42
+ }
43
+
44
+ .apos-input-array-inline-table {
45
+ @include type-label;
46
+ position: relative;
47
+ left: -35px;
48
+ min-width: calc(100% + 35px);
49
+ width: max-content;
50
+ margin: 0 0 $spacing-base;
51
+ border-collapse: collapse;
52
+
53
+ th {
54
+ padding-left: $spacing-base;
55
+ padding-right: $spacing-base;
56
+ height: 40px;
57
+ border: 1px solid var(--a-base-9);
58
+ text-align: left;
59
+ background-color: var(--a-base-10);
60
+ }
61
+ .apos-table-cell--hidden {
62
+ padding-left: 5px;
63
+ border: none;
64
+ cursor: pointer;
65
+ background-color: transparent;
66
+ }
67
+
68
+ td, :deep(td) {
69
+ padding: $spacing-base;
70
+ border: 1px solid var(--a-base-9);
71
+ vertical-align: middle;
72
+ text-align: center;
73
+ transition: background-color 0.3s ease;
74
+ background-color: var(--a-background-primary);
75
+ }
76
+ td.apos-input-array-inline-item-controls {
77
+ width: 15px;
78
+ min-width: 15px;
79
+ border: none;
80
+ background-color: transparent;
81
+ }
82
+ tr.apos-is-dragging, :deep(tr.apos-is-dragging) {
83
+ td, &:hover td {
84
+ background: var(--a-base-4);
85
+ }
86
+ }
87
+ tr:hover, :deep(tr:hover) {
88
+ td {
89
+ background-color: var(--a-base-10);
90
+ }
91
+ td.apos-input-array-inline-item-controls {
92
+ background-color: transparent;
93
+ }
94
+ }
95
+
96
+ :deep(.apos-field__info) {
97
+ padding-top: 0;
98
+ }
99
+ :deep(.apos-field__label) {
100
+ display: none;
101
+ }
102
+ :deep(.apos-input-wrapper) {
103
+ padding: 0 4px;
104
+ }
105
+ :deep(.apos-input--select) {
106
+ min-width: 130px;
107
+ }
108
+ :deep(.apos-input--relationship) {
109
+ width: 100%;
110
+ min-width: 150px;
111
+ }
112
+ :deep(.apos-schema .apos-field.apos-field--small),
113
+ :deep(.apos-schema .apos-field.apos-field--micro),
114
+ :deep(.apos-schema .apos-field.apos-field--margin-micro) {
115
+ margin-bottom: 0;
116
+ }
117
+ :deep(.apos-search) {
118
+ z-index: calc(#{$z-index-widget-focused-controls} + 1);
119
+ position: absolute;
120
+ top: 35px;
121
+ width: 100%;
122
+ min-width: 350px;
123
+ }
124
+ :deep(.apos-slat-list .apos-slat),
125
+ :deep(.apos-input-relationship__items) {
126
+ margin-top: 0;
127
+ margin-bottom: 0;
128
+ }
129
+ :deep(.apos-input-relationship__input-wrapper :disabled) {
130
+ display: none;
131
+ }
132
+ :deep(.apos-field__error) {
133
+ position: absolute;
134
+ bottom: 13px;
135
+ left: $spacing-base;
136
+ }
137
+ :deep(.apos-field--relationship .apos-field__error) {
138
+ z-index: calc(#{$z-index-widget-focused-controls} + 1);
139
+ }
140
+ }
141
+
142
+ .apos-input-array-inline-standard {
143
+ .apos-input-array-inline-collapse {
144
+ position: absolute;
145
+ top: $spacing-quadruple;
146
+ left: $spacing-base;
147
+ }
148
+
149
+ :deep(.apos-schema) {
150
+ position: relative;
151
+ display: grid;
152
+ grid-template-columns: 35px auto 35px;
153
+ gap: 5px;
154
+ width: 100%;
155
+ padding-bottom: $spacing-base;
156
+ border-bottom: 1px solid var(--a-base-9);
157
+ transition: background-color 0.3s ease;
158
+ &:hover {
159
+ background-color: var(--a-base-10);
160
+ }
161
+ .apos-field.apos-field--small,
162
+ .apos-field.apos-field--micro,
163
+ .apos-field.apos-field--margin-micro {
164
+ margin-bottom: 0;
165
+ }
166
+ & > div {
167
+ grid-column: 2;
168
+ }
169
+ &.apos-input-array-inline-item--active {
170
+ background-color: var(--a-base-10);
171
+ border-bottom: 1px solid var(--a-base-6);
172
+ }
173
+ &.apos-input-array-inline-item--active > div {
174
+ display: block;
175
+ }
176
+ .apos-input-array-inline-label,
177
+ .apos-input-array-inline-item-controls,
178
+ .apos-input-array-inline-item-controls--remove {
179
+ display: block;
180
+ }
181
+
182
+ .apos-input-array-inline-label {
183
+ transition: background-color 0.3s ease;
184
+ @include type-label;
185
+ margin: 0;
186
+ padding-top: $spacing-base;
187
+ padding-bottom: $spacing-base;
188
+ text-align: left;
189
+ grid-column: 2;
190
+ }
191
+ .apos-input-array-inline-label:hover {
192
+ cursor: pointer;
193
+ }
194
+
195
+ .apos-input-array-inline-item-controls {
196
+ padding: $spacing-base;
197
+ grid-column: 1;
198
+ grid-row: 1;
199
+ }
200
+ .apos-input-array-inline-item-controls--remove {
201
+ grid-column: 3;
202
+ grid-row: 1;
203
+ }
204
+ }
205
+ }
@@ -45,8 +45,8 @@
45
45
  <div
46
46
  v-for="(group, name) in groups"
47
47
  v-show="name === activeGroup"
48
- class="apos-settings__subform-group"
49
48
  :key="name"
49
+ class="apos-settings__subform-group"
50
50
  data-apos-test="subformGroup"
51
51
  :data-apos-test-name="name"
52
52
  :data-apos-test-label="$t(group.label)"
@@ -94,7 +94,7 @@ export default {
94
94
  .apos-settings {
95
95
  @include type-base;
96
96
 
97
- ::v-deep .apos-modal__inner {
97
+ :deep(.apos-modal__inner) {
98
98
  // 1/2 or 2/3 width
99
99
  // $width: calc(100vw / 2);
100
100
  $width: min(700px, calc(calc(100vw / 3) * 2));
@@ -109,16 +109,16 @@ export default {
109
109
  height: calc(100vh - #{$vertical-spacing * 2});
110
110
  }
111
111
 
112
- ::v-deep .apos-modal__main--with-left-rail {
112
+ :deep(.apos-modal__main--with-left-rail) {
113
113
  grid-template-columns: 25% 75%;
114
114
  }
115
115
 
116
- ::v-deep .apos-modal__body-inner {
116
+ :deep(.apos-modal__body-inner) {
117
117
  // padding: $spacing-triple $spacing-triple $spacing-double;
118
118
  padding: $spacing-double $spacing-triple;
119
119
  }
120
120
 
121
- ::v-deep .apos-modal__header__main {
121
+ :deep(.apos-modal__header__main) {
122
122
  // padding: $spacing-triple $spacing-triple $spacing-double;
123
123
  padding: $spacing-double $spacing-triple;
124
124
  }
@@ -77,7 +77,7 @@ export default {
77
77
  }
78
78
  }
79
79
  },
80
- beforeDestroy() {
80
+ beforeUnmount() {
81
81
  clearTimeout(this.restoreRefTimeout);
82
82
  Object.values(this.subformUpdateTimeouts)
83
83
  .forEach(clearTimeout);
@@ -90,7 +90,7 @@ export default {
90
90
  this.expanded = event.value ? event.name : null;
91
91
  if (this.expanded) {
92
92
  clearTimeout(this.subformUpdateTimeouts[event.name]);
93
- this.$delete(this.subformUpdateTimeouts, event.name);
93
+ delete this.setSubformValues[event.name];
94
94
  }
95
95
  },
96
96
  async submit(event) {
@@ -125,9 +125,9 @@ export default {
125
125
  },
126
126
  setUpdatedTimeout(name, ms = 3000) {
127
127
  const updateTimeout = setTimeout(() => {
128
- this.$delete(this.subformUpdateTimeouts, name);
128
+ delete this.subformUpdateTimeouts[name];
129
129
  }, ms);
130
- this.$set(this.subformUpdateTimeouts, name, updateTimeout);
130
+ this.subformUpdateTimeouts[name] = updateTimeout;
131
131
  },
132
132
  async loadData() {
133
133
  const result = await apos.http.get(this.action, {
@@ -1,11 +1,12 @@
1
1
  <template>
2
2
  <AposButton
3
3
  icon="tray-full-icon"
4
- type="subtle" :modifiers="['small', 'no-motion']"
5
- @click="open"
4
+ type="subtle"
5
+ :modifiers="['small', 'no-motion']"
6
6
  :disabled="count <= 0"
7
7
  :tooltip="tooltip"
8
8
  :icon-only="true"
9
+ @click="open"
9
10
  >
10
11
  <template #label>
11
12
  <span v-if="canPublish && count > 0" class="apos-submitted-drafts__counter">
@@ -37,7 +38,7 @@ export default {
37
38
  mounted() {
38
39
  this.updateCount();
39
40
  },
40
- destroyed() {
41
+ unmounted() {
41
42
  if (this.timeout) {
42
43
  clearTimeout(this.timeout);
43
44
  }
@@ -69,7 +70,7 @@ export default {
69
70
  </script>
70
71
 
71
72
  <style lang="scss" scoped>
72
- ::v-deep .apos-submitted-drafts__counter {
73
+ :deep(.apos-submitted-drafts__counter) {
73
74
  display: inline-flex;
74
75
  margin-left: $spacing-half;
75
76
  padding: 3px;
@@ -265,7 +265,9 @@ module.exports = {
265
265
  lng: req.locale
266
266
  });
267
267
  },
268
+ body: {},
268
269
  data: {},
270
+ headers: {},
269
271
  protocol: 'http',
270
272
  get: function (propName) {
271
273
  return { Host: 'you-need-to-set-baseUrl-in-app-js.com' }[propName];