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
@@ -11,14 +11,16 @@
11
11
  @create-placeholder="$emit('create-placeholder', $event)"
12
12
  />
13
13
  <div
14
- class="apos-media-manager-display__cell" v-for="item in items"
14
+ v-for="item in items"
15
15
  :key="idFor(item)"
16
+ class="apos-media-manager-display__cell"
16
17
  :class="{'apos-is-selected': checked.includes(item._id)}"
17
18
  :style="getCellStyles(item)"
18
19
  >
19
20
  <div class="apos-media-manager-display__checkbox">
20
21
  <AposCheckbox
21
22
  v-show="item._id !== 'placeholder' && !options.hideCheckboxes"
23
+ v-model="checkedProxy"
22
24
  tabindex="-1"
23
25
  :field="{
24
26
  name: item._id,
@@ -28,10 +30,10 @@
28
30
  disabled: options.disableUnchecked && !checked.includes(item._id)
29
31
  }"
30
32
  :choice="{ value: item._id }"
31
- v-model="checkedProxy"
32
33
  />
33
34
  </div>
34
35
  <button
36
+ :id="`btn-${item._id}`"
35
37
  :disabled="
36
38
  item._id === 'placeholder' ||
37
39
  (options.disableUnchecked && !checked.includes(item._id))
@@ -40,7 +42,6 @@
40
42
  @click.exact="$emit('select', item._id)"
41
43
  @click.shift="$emit('select-series', item._id)"
42
44
  @click.meta="$emit('select-another', item._id)"
43
- ref="btns"
44
45
  >
45
46
  <div
46
47
  v-if="item.dimensions"
@@ -66,7 +67,6 @@
66
67
  <button
67
68
  disabled="true"
68
69
  class="apos-media-manager-display__select"
69
- ref="btns"
70
70
  />
71
71
  </div>
72
72
  </div>
@@ -78,10 +78,6 @@ import cuid from 'cuid';
78
78
 
79
79
  export default {
80
80
  // Custom model to handle the v-model connection on the parent.
81
- model: {
82
- prop: 'checked',
83
- event: 'change'
84
- },
85
81
  props: {
86
82
  maxReached: {
87
83
  type: Boolean,
@@ -118,10 +114,10 @@ export default {
118
114
  }
119
115
  },
120
116
  emits: [
117
+ 'update:checked',
121
118
  'select',
122
119
  'select-series',
123
120
  'select-another',
124
- 'change',
125
121
  'upload-started',
126
122
  'upload-complete',
127
123
  'create-placeholder'
@@ -133,7 +129,7 @@ export default {
133
129
  return this.checked;
134
130
  },
135
131
  set(val) {
136
- this.$emit('change', val);
132
+ this.$emit('update:checked', val);
137
133
  }
138
134
  }
139
135
  },
@@ -141,7 +137,11 @@ export default {
141
137
  getPlaceholderStyles(item) {
142
138
  // Account for whether the refs have been set by the v-for or if on the
143
139
  // placeholder.
144
- const btn = Array.isArray(this.$refs.btns) ? this.$refs.btns[0] : this.$refs.btns;
140
+ /* const btn = Array.isArray(this.$refs.btns) ? this.$refs.btns[0] : this.$refs.btns; */
141
+ const btn = this.items.length && this.$el.querySelector(`#btn-${this.items[0]._id}`);
142
+ if (!btn) {
143
+ return {};
144
+ }
145
145
  const {
146
146
  width: parentWidth,
147
147
  height: parentHeight
@@ -5,24 +5,25 @@
5
5
  'apos-is-replacing': showReplace
6
6
  }"
7
7
  >
8
- <div class="apos-media-editor__inner" v-if="activeMedia">
8
+ <div v-if="activeMedia" class="apos-media-editor__inner">
9
9
  <div class="apos-media-editor__thumb-wrapper">
10
10
  <img
11
11
  v-if="activeMedia.attachment && activeMedia.attachment._urls"
12
12
  class="apos-media-editor__thumb"
13
- :src="activeMedia.attachment._urls[restoreOnly ? 'one-sixth' : 'one-third']" :alt="activeMedia.description"
13
+ :src="activeMedia.attachment._urls[restoreOnly ? 'one-sixth' : 'one-third']"
14
+ :alt="activeMedia.description"
14
15
  >
15
16
  </div>
16
17
  <ul class="apos-media-editor__details">
17
- <li class="apos-media-editor__detail" v-if="createdDate">
18
+ <li v-if="createdDate" class="apos-media-editor__detail">
18
19
  {{ $t('apostrophe:mediaCreatedDate', { createdDate }) }}
19
20
  </li>
20
- <li class="apos-media-editor__detail" v-if="fileSize">
21
+ <li v-if="fileSize" class="apos-media-editor__detail">
21
22
  {{ $t('apostrophe:mediaFileSize', { fileSize }) }}
22
23
  </li>
23
24
  <li
24
- class="apos-media-editor__detail"
25
25
  v-if="activeMedia.attachment && activeMedia.attachment.width"
26
+ class="apos-media-editor__detail"
26
27
  >
27
28
  {{
28
29
  $t('apostrophe:mediaDimensions', {
@@ -35,21 +36,24 @@
35
36
  <ul class="apos-media-editor__links">
36
37
  <li class="apos-media-editor__link" aria-hidden="true">
37
38
  <AposButton
38
- type="quiet" label="apostrophe:replace"
39
- @click="showReplace = true"
39
+ type="quiet"
40
+ label="apostrophe:replace"
40
41
  :disabled="isArchived"
42
+ @click="showReplace = true"
41
43
  />
42
44
  </li>
43
- <li class="apos-media-editor__link" v-if="activeMedia.attachment && activeMedia.attachment._urls">
45
+ <li v-if="activeMedia.attachment && activeMedia.attachment._urls" class="apos-media-editor__link">
44
46
  <AposButton
45
- type="quiet" label="apostrophe:view"
46
- @click="viewMedia"
47
+ type="quiet"
48
+ label="apostrophe:view"
47
49
  :disabled="isArchived"
50
+ @click="viewMedia"
48
51
  />
49
52
  </li>
50
- <li class="apos-media-editor__link" v-if="activeMedia.attachment && activeMedia.attachment._urls">
53
+ <li v-if="activeMedia.attachment && activeMedia.attachment._urls" class="apos-media-editor__link">
51
54
  <AposButton
52
- type="quiet" label="apostrophe:download"
55
+ type="quiet"
56
+ label="apostrophe:download"
53
57
  :href="!isArchived ? activeMedia.attachment._urls.original : false"
54
58
  :disabled="isArchived"
55
59
  download
@@ -58,16 +62,16 @@
58
62
  </ul>
59
63
  <AposSchema
60
64
  v-if="docFields.data.title !== undefined"
61
- :schema="schema"
65
+ ref="schema"
62
66
  v-model="docFields"
67
+ :schema="schema"
63
68
  :modifiers="['small', 'inverted']"
64
69
  :trigger-validation="triggerValidation"
65
70
  :doc-id="docFields.data._id"
66
71
  :following-values="followingValues()"
72
+ :server-errors="serverErrors"
67
73
  @validate="triggerValidate"
68
74
  @reset="$emit('modified', false)"
69
- ref="schema"
70
- :server-errors="serverErrors"
71
75
  />
72
76
  </div>
73
77
  <AposModalLip :refresh="lipKey">
@@ -84,13 +88,15 @@
84
88
  modifiers: [ 'small', 'no-motion' ]
85
89
  }"
86
90
  :menu="moreMenu"
87
- @item-clicked="moreMenuHandler"
88
91
  menu-placement="top-end"
92
+ @item-clicked="moreMenuHandler"
89
93
  />
90
94
  <AposButton
91
- @click="save" class="apos-media-editor__save"
95
+ class="apos-media-editor__save"
92
96
  :disabled="docFields.hasErrors"
93
- :label="restoreOnly ? 'apostrophe:restore' : 'apostrophe:save'" type="primary"
97
+ :label="restoreOnly ? 'apostrophe:restore' : 'apostrophe:save'"
98
+ type="primary"
99
+ @click="save"
94
100
  />
95
101
  </div>
96
102
  </AposModalLip>
@@ -216,6 +222,7 @@ export default {
216
222
  },
217
223
  watch: {
218
224
  'docFields.data': {
225
+ deep: true,
219
226
  handler(newData, oldData) {
220
227
  this.$nextTick(() => {
221
228
  // If either old or new state are an empty object, it's not "modified."
@@ -401,7 +408,7 @@ export default {
401
408
  max-height: 100%;
402
409
  }
403
410
 
404
- .apos-media-editor ::v-deep .apos-field {
411
+ .apos-media-editor :deep(.apos-field) {
405
412
  margin-bottom: $spacing-double;
406
413
  }
407
414
 
@@ -421,7 +428,7 @@ export default {
421
428
  display: flex;
422
429
  margin-bottom: $spacing-triple;
423
430
 
424
- ::v-deep .apos-button--quiet {
431
+ :deep(.apos-button--quiet) {
425
432
  display: inline;
426
433
  }
427
434
  }
@@ -433,7 +440,7 @@ export default {
433
440
  }
434
441
  }
435
442
 
436
- ::v-deep [data-apos-field='attachment'] {
443
+ :deep([data-apos-field='attachment']) {
437
444
  .apos-media-editor:not(.apos-is-replacing) & {
438
445
  position: absolute;
439
446
  left: -999rem;
@@ -6,14 +6,15 @@
6
6
  <AposButton
7
7
  label="apostrophe:clear"
8
8
  type="quiet"
9
- @click="clear"
10
9
  :modifiers="['no-motion']"
10
+ @click="clear"
11
11
  />
12
12
  </div>
13
13
  <ol class="apos-media-manager-selections__items">
14
14
  <li
15
15
  v-for="item in items"
16
- :key="item._id" class="apos-media-manager-selections__item"
16
+ :key="item._id"
17
+ class="apos-media-manager-selections__item"
17
18
  >
18
19
  <div
19
20
  v-if="item.attachment && item.attachment._urls"
@@ -91,7 +92,7 @@ export default {
91
92
  margin-bottom: $spacing-double;
92
93
  }
93
94
 
94
- .apos-media-manager-selections__heading ::v-deep .apos-button {
95
+ .apos-media-manager-selections__heading :deep(.apos-button) {
95
96
  margin-left: $spacing-base;
96
97
  }
97
98
 
@@ -28,13 +28,14 @@
28
28
  </div>
29
29
  </div>
30
30
  <input
31
- type="file" class="apos-sr-only"
32
31
  ref="upload"
33
- @input="uploadMedia"
32
+ type="file"
33
+ class="apos-sr-only"
34
34
  :accept="accept"
35
35
  multiple="true"
36
36
  :disabled="disabled"
37
37
  tabindex="-1"
38
+ @input="uploadMedia"
38
39
  >
39
40
  </label>
40
41
  </template>
@@ -49,7 +50,7 @@ export default {
49
50
  },
50
51
  disabled: {
51
52
  type: Boolean,
52
- required: false
53
+ default: false
53
54
  },
54
55
  accept: {
55
56
  type: String,
@@ -82,7 +83,7 @@ export default {
82
83
  mounted() {
83
84
  apos.bus.$on('command-menu-manager-create-new', this.create);
84
85
  },
85
- destroyed() {
86
+ unmounted() {
86
87
  apos.bus.$off('command-menu-manager-create-new', this.create);
87
88
  },
88
89
  methods: {
@@ -51,6 +51,10 @@ module.exports = {
51
51
  cascades: [ 'requirements' ],
52
52
  options: {
53
53
  alias: 'login',
54
+ placeholder: {
55
+ username: 'apostrophe:enterUsername',
56
+ password: 'apostrophe:enterPassword'
57
+ },
54
58
  localLogin: true,
55
59
  passwordReset: false,
56
60
  passwordResetHours: 48,
@@ -539,6 +543,7 @@ module.exports = {
539
543
 
540
544
  getBrowserData(req) {
541
545
  return {
546
+ schema: self.getSchema(),
542
547
  action: self.action,
543
548
  passwordResetEnabled: self.isPasswordResetEnabled(),
544
549
  ...(req.user ? {
@@ -909,8 +914,20 @@ module.exports = {
909
914
  last: true
910
915
  }
911
916
  );
912
- }
917
+ },
913
918
 
919
+ getSchema() {
920
+ return self.apos.user.schema
921
+ .filter(({ name }) => [ 'username', 'password' ].includes(name))
922
+ .map(field => ({
923
+ name: field.name,
924
+ label: field.label,
925
+ placeholder: self.options.placeholder[field.name],
926
+ type: field.type,
927
+ required: true
928
+ })
929
+ );
930
+ }
914
931
  };
915
932
  },
916
933
 
@@ -1,15 +1,14 @@
1
- import Vue from 'Modules/@apostrophecms/ui/lib/vue';
1
+ import createApp from 'Modules/@apostrophecms/ui/lib/vue';
2
2
 
3
3
  export default function() {
4
+ const component = apos.vueComponents.TheAposLogin;
4
5
  const el = document.querySelector('#apos-login');
5
6
  if (el) {
6
- return new Vue({
7
- el,
8
- render: function (h) {
9
- return h('TheAposLogin');
10
- }
11
- });
7
+ const app = createApp(component);
8
+
9
+ app.mount(el);
12
10
  }
11
+
13
12
  apos.bus.$on('admin-menu-click', async (item) => {
14
13
  if (item !== '@apostrophecms/login-logout') {
15
14
  return;
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div
3
- class="apos-login-form"
4
3
  v-if="passwordResetEnabled"
4
+ class="apos-login-form"
5
5
  >
6
6
  <TheAposLoginHeader
7
7
  :env="context.env"
@@ -23,8 +23,8 @@
23
23
  />
24
24
  <form v-else @submit.prevent="submit">
25
25
  <AposSchema
26
- :schema="schema"
27
26
  v-model="doc"
27
+ :schema="schema"
28
28
  />
29
29
  <AposButton
30
30
  data-apos-test="pwdResetRequestSubmit"
@@ -61,7 +61,7 @@ export default {
61
61
  }
62
62
  }
63
63
 
64
- .apos-login-form__submit ::v-deep .apos-button {
64
+ .apos-login-form__submit :deep(.apos-button) {
65
65
  height: 47px;
66
66
  }
67
67
  </style>
@@ -1,8 +1,8 @@
1
1
  <template>
2
2
  <div
3
+ v-if="phase === 'beforeSubmit' || phase === 'uponSubmit'"
3
4
  key="1"
4
5
  class="apos-login-form"
5
- v-if="phase === 'beforeSubmit' || phase === 'uponSubmit'"
6
6
  >
7
7
  <TheAposLoginHeader
8
8
  :env="context.env"
@@ -11,30 +11,30 @@
11
11
  />
12
12
 
13
13
  <div class="apos-login-form__body">
14
- <form @submit.prevent="submit" data-apos-test="loginForm">
14
+ <form data-apos-test="loginForm" @submit.prevent="submit">
15
15
  <AposSchema
16
- :schema="schema"
17
16
  v-model="doc"
17
+ :schema="schema"
18
18
  />
19
19
  <a
20
- href="#"
21
20
  v-if="passwordResetEnabled"
21
+ href="#"
22
22
  class="apos-login-form__link"
23
23
  @click.prevent="$emit('set-stage', 'forgotPassword')"
24
24
  >{{ $t('apostrophe:loginResetPassword') }}</a>
25
25
  <Component
26
+ v-bind="getRequirementProps(requirement.name)"
27
+ :is="requirement.component"
26
28
  v-for="requirement in beforeSubmitRequirements"
27
29
  :key="requirement.name"
28
- :is="requirement.component"
29
- v-bind="getRequirementProps(requirement.name)"
30
30
  @done="requirementDone(requirement, $event)"
31
31
  @block="requirementBlock(requirement)"
32
32
  />
33
33
  <template v-if="phase === 'uponSubmit'">
34
34
  <Component
35
+ :is="requirement.component"
35
36
  v-for="requirement in uponSubmitRequirements"
36
37
  :key="requirement.name"
37
- :is="requirement.component"
38
38
  v-bind="getRequirementProps(requirement.name)"
39
39
  @done="requirementDone(requirement, $event)"
40
40
  @block="requirementBlock(requirement)"
@@ -55,9 +55,9 @@
55
55
  </div>
56
56
  </div>
57
57
  <div
58
+ v-else-if="activeSoloRequirement"
58
59
  key="2"
59
60
  class="apos-login-form"
60
- v-else-if="activeSoloRequirement"
61
61
  >
62
62
  <TheAposLoginHeader
63
63
  :env="context.env"
@@ -67,9 +67,9 @@
67
67
  />
68
68
  <div class="apos-login-form__body">
69
69
  <Component
70
- v-if="!fetchingRequirementProps"
71
70
  v-bind="getRequirementProps(activeSoloRequirement.name)"
72
71
  :is="activeSoloRequirement.component"
72
+ v-if="!fetchingRequirementProps"
73
73
  :success="activeSoloRequirement.success"
74
74
  :error="activeSoloRequirement.error"
75
75
  @done="requirementDone(activeSoloRequirement, $event)"
@@ -115,7 +115,7 @@ export default {
115
115
  }
116
116
  }
117
117
 
118
- .apos-login-form__submit ::v-deep .apos-button {
118
+ .apos-login-form__submit :deep(.apos-button) {
119
119
  height: 47px;
120
120
  }
121
121
  </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div
3
- class="apos-login-form"
4
3
  v-if="passwordResetEnabled && ready"
4
+ class="apos-login-form"
5
5
  >
6
6
  <TheAposLoginHeader
7
7
  :env="context.env"
@@ -27,8 +27,8 @@
27
27
  @submit.prevent="submit"
28
28
  >
29
29
  <AposSchema
30
- :schema="schema"
31
30
  v-model="doc"
31
+ :schema="schema"
32
32
  />
33
33
  <AposButton
34
34
  data-apos-test="pwdResetSubmit"
@@ -64,7 +64,7 @@ export default {
64
64
  flex-direction: column;
65
65
  }
66
66
  }
67
- .apos-login-form__submit ::v-deep .apos-button {
67
+ .apos-login-form__submit :deep(.apos-button) {
68
68
  height: 47px;
69
69
  }
70
70
  </style>
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <transition name="fade-stage">
3
3
  <div
4
+ v-show="loaded"
4
5
  class="apos-login apos-theme-dark"
5
6
  data-apos-test="loginForm"
6
- v-show="loaded"
7
7
  :class="themeClass"
8
8
  >
9
9
  <transition name="fade-outer">
@@ -46,7 +46,7 @@
46
46
  </transition>
47
47
  </div>
48
48
  <transition name="fade-outer">
49
- <div class="apos-login__footer" v-show="loaded">
49
+ <div v-show="loaded" class="apos-login__footer">
50
50
  <AposLogo class="apos-login__logo" />
51
51
  <label class="apos-login__project-version">
52
52
  Version {{ context.version }}
@@ -12,22 +12,7 @@ export default {
12
12
  return {
13
13
  phase: 'beforeSubmit',
14
14
  busy: false,
15
- schema: [
16
- {
17
- name: 'username',
18
- label: 'Username',
19
- placeholder: 'Enter username',
20
- type: 'string',
21
- required: true
22
- },
23
- {
24
- name: 'password',
25
- label: 'Password',
26
- placeholder: 'Enter password',
27
- type: 'password',
28
- required: true
29
- }
30
- ],
15
+ schema: apos.login.schema,
31
16
  requirements: getRequirements(),
32
17
  requirementProps: {},
33
18
  fetchingRequirementProps: false
@@ -1,97 +1,70 @@
1
- import Vue from 'Modules/@apostrophecms/ui/lib/vue';
1
+ import createApp from 'Modules/@apostrophecms/ui/lib/vue';
2
2
 
3
3
  export default function() {
4
- const theAposModals = new Vue({
5
- el: '#apos-modals',
6
- computed: {
7
- apos () {
8
- return window.apos;
9
- }
10
- },
11
- methods: {
12
- async confirm(content, options = {}) {
13
- return this.execute(apos.modal.components.confirm, {
14
- content,
15
- mode: 'confirm',
16
- options
17
- });
18
- },
19
- async alert(alertContent, options = {}) {
20
- return this.execute(apos.modal.components.confirm, {
21
- content: alertContent,
22
- mode: 'alert',
23
- options
24
- });
25
- },
26
- execute(componentName, props) {
27
- return this.$refs.modals.execute(componentName, props);
28
- },
29
- getAt(index) {
30
- return this.$refs.modals.getAt(index);
31
- },
32
- getProperties(id) {
33
- return this.$refs.modals.getProperties(id);
34
- },
35
- // Returns true if el1 is "on top of" el2 in the
36
- // modal stack, as viewed by the user. If el1 is a
37
- // modal that appears later in the stack than el2
38
- // (visually stacked on top), this method returns true.
39
- // If el2 is `document` and el1 is a modal, this
40
- // method returns true. For convenenience, if el1
41
- // or el2 is not a modal, it is treated as its DOM
42
- // parent modal, or as `document`. If el1 has no
43
- // parent modal this method always returns false.
44
- //
45
- // If el1 is no longer connected to the DOM then it
46
- // is also considered to be "on top" e.g. not something
47
- // that should concern `v-click-outside-element` and
48
- // similar functionality. This is necessary because
49
- // sometimes Vue removes elements from the DOM before
50
- // we can examine their relationships.
51
- onTopOf(el1, el2) {
52
- if (!el1.isConnected) {
53
- // If el1 is no longer in the DOM we can't make a proper determination,
54
- // returning true prevents unwanted things like click-outside-element
55
- // events from firing
56
- return true;
57
- }
58
- if (!el1.matches('[data-apos-modal]')) {
59
- el1 = el1.closest('[data-apos-modal]') || document;
60
- }
61
- if (!el2.matches('[data-apos-modal]')) {
62
- el2 = el2.closest('[data-apos-modal]') || document;
63
- }
64
- if (el1 === document) {
65
- return false;
66
- }
67
- if (el2 === document) {
68
- return true;
69
- }
70
- const index1 = apos.modal.stack.findIndex(modal => modal.$el === el1);
71
- const index2 = apos.modal.stack.findIndex(modal => modal.$el === el2);
72
- if (index1 === -1) {
73
- throw new Error('apos.modal.onTopOf: el1 is not in the modal stack');
74
- }
75
- if (index2 === -1) {
76
- throw new Error('apos.modal.onTopOf: el2 is not in the modal stack');
77
- }
78
- return index1 > index2;
79
- }
80
- },
81
- render(h) {
82
- return h(apos.modal.components.the, {
83
- ref: 'modals',
84
- props: {
85
- modals: apos.modal.modals
86
- }
87
- });
88
- }
4
+ const component = apos.vueComponents.TheAposModals;
5
+ const el = document.querySelector('#apos-modals');
6
+ if (!el) {
7
+ return;
8
+ }
9
+ const app = createApp(component, {
10
+ modals: apos.modal.modals
89
11
  });
12
+ const theAposModals = app.mount(el);
13
+
90
14
  apos.modal.execute = theAposModals.execute;
91
15
  apos.modal.getAt = theAposModals.getAt;
92
16
  apos.modal.getProperties = theAposModals.getProperties;
93
- apos.modal.onTopOf = theAposModals.onTopOf;
17
+ apos.modal.onTopOf = onTopOf;
94
18
  apos.modal.stack = [];
95
19
  apos.confirm = theAposModals.confirm;
96
20
  apos.alert = theAposModals.alert;
97
21
  }
22
+
23
+ // Returns true if el1 is "on top of" el2 in the
24
+ // modal stack, as viewed by the user. If el1 is a
25
+ // modal that appears later in the stack than el2
26
+ // (visually stacked on top), this method returns true.
27
+ // If el2 is `document` and el1 is a modal, this
28
+ // method returns true. For convenenience, if el1
29
+ // or el2 is not a modal, it is treated as its DOM
30
+ // parent modal, or as `document`. If el1 has no
31
+ // parent modal this method always returns false.
32
+ //
33
+ // If el1 is no longer connected to the DOM then it
34
+ // is also considered to be "on top" e.g. not something
35
+ // that should concern `v-click-outside-element` and
36
+ // similar functionality. This is necessary because
37
+ // sometimes Vue removes elements from the DOM before
38
+ // we can examine their relationships.
39
+ function onTopOf(el1, el2) {
40
+ if (el2.matches('[data-apos-menu]')) {
41
+ return false;
42
+ }
43
+ if (!el1.isConnected) {
44
+ // If el1 is no longer in the DOM we can't make a proper determination,
45
+ // returning true prevents unwanted things like click-outside-element
46
+ // events from firing
47
+ return true;
48
+ }
49
+ if (!el1.matches('[data-apos-modal]')) {
50
+ el1 = el1.closest('[data-apos-modal]') || document;
51
+ }
52
+ if (!el2.matches('[data-apos-modal]')) {
53
+ el2 = el2.closest('[data-apos-modal]') || document;
54
+ }
55
+ if (el1 === document) {
56
+ return false;
57
+ }
58
+ if (el2 === document) {
59
+ return true;
60
+ }
61
+ const index1 = apos.modal.stack.findIndex(modal => modal.$el === el1);
62
+ const index2 = apos.modal.stack.findIndex(modal => modal.$el === el2);
63
+ if (index1 === -1) {
64
+ throw new Error('apos.modal.onTopOf: el1 is not in the modal stack');
65
+ }
66
+ if (index2 === -1) {
67
+ throw new Error('apos.modal.onTopOf: el2 is not in the modal stack');
68
+ }
69
+ return index1 > index2;
70
+ }