apostrophe 4.3.2 → 4.4.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 (158) hide show
  1. package/.stylelintrc +1 -93
  2. package/CHANGELOG.md +56 -0
  3. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBar.vue +7 -1
  4. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarLocale.vue +6 -3
  5. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposAdminBarUser.vue +2 -1
  6. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextModeAndSettings.vue +1 -0
  7. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposContextTitle.vue +3 -2
  8. package/modules/@apostrophecms/admin-bar/ui/apos/components/TheAposSavingIndicator.vue +6 -2
  9. package/modules/@apostrophecms/any-page-type/index.js +2 -2
  10. package/modules/@apostrophecms/area/ui/apos/components/AposAreaContextualMenu.vue +13 -7
  11. package/modules/@apostrophecms/area/ui/apos/components/AposAreaEditor.vue +4 -4
  12. package/modules/@apostrophecms/area/ui/apos/components/AposAreaExpandedMenu.vue +17 -11
  13. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenu.vue +13 -7
  14. package/modules/@apostrophecms/area/ui/apos/components/AposAreaMenuItem.vue +3 -0
  15. package/modules/@apostrophecms/area/ui/apos/components/AposAreaWidget.vue +36 -20
  16. package/modules/@apostrophecms/area/ui/apos/components/AposWidgetControls.vue +18 -11
  17. package/modules/@apostrophecms/busy/ui/apos/components/TheAposBusy.vue +6 -8
  18. package/modules/@apostrophecms/command-menu/index.js +12 -7
  19. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuKey.vue +9 -7
  20. package/modules/@apostrophecms/command-menu/ui/apos/components/AposCommandMenuShortcut.vue +28 -15
  21. package/modules/@apostrophecms/command-menu/ui/apos/components/TheAposCommandMenu.vue +44 -42
  22. package/modules/@apostrophecms/doc-type/index.js +2 -1
  23. package/modules/@apostrophecms/doc-type/ui/apos/components/AposDocEditor.vue +4 -3
  24. package/modules/@apostrophecms/file-tag/index.js +1 -1
  25. package/modules/@apostrophecms/global/index.js +29 -0
  26. package/modules/@apostrophecms/i18n/i18n/de.json +20 -0
  27. package/modules/@apostrophecms/i18n/i18n/en.json +1 -0
  28. package/modules/@apostrophecms/i18n/i18n/es.json +1 -0
  29. package/modules/@apostrophecms/i18n/i18n/fr.json +1 -0
  30. package/modules/@apostrophecms/i18n/i18n/it.json +1 -0
  31. package/modules/@apostrophecms/i18n/i18n/pt-BR.json +1 -0
  32. package/modules/@apostrophecms/i18n/i18n/sk.json +1 -0
  33. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalize.vue +25 -17
  34. package/modules/@apostrophecms/i18n/ui/apos/components/AposI18nLocalizeErrors.vue +5 -4
  35. package/modules/@apostrophecms/image/index.js +2 -1
  36. package/modules/@apostrophecms/image/ui/apos/components/AposImageCropper.vue +1 -1
  37. package/modules/@apostrophecms/image/ui/apos/components/AposImageRelationshipEditor.vue +9 -8
  38. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManager.vue +13 -10
  39. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerDisplay.vue +11 -7
  40. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerEditor.vue +12 -2
  41. package/modules/@apostrophecms/image/ui/apos/components/AposMediaManagerSelections.vue +8 -5
  42. package/modules/@apostrophecms/image/ui/apos/components/AposMediaUploader.vue +17 -8
  43. package/modules/@apostrophecms/image-tag/index.js +1 -1
  44. package/modules/@apostrophecms/login/ui/apos/components/AposLoginForm.vue +1 -0
  45. package/modules/@apostrophecms/login/ui/apos/components/AposResetPasswordForm.vue +1 -0
  46. package/modules/@apostrophecms/login/ui/apos/components/TheAposLogin.vue +16 -14
  47. package/modules/@apostrophecms/login/ui/apos/components/TheAposLoginHeader.vue +9 -4
  48. package/modules/@apostrophecms/modal/ui/apos/apps/AposModals.js +11 -59
  49. package/modules/@apostrophecms/modal/ui/apos/components/AposDocsManagerToolbar.vue +1 -0
  50. package/modules/@apostrophecms/modal/ui/apos/components/AposModal.vue +59 -55
  51. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBody.vue +1 -0
  52. package/modules/@apostrophecms/modal/ui/apos/components/AposModalBreadcrumbs.vue +5 -0
  53. package/modules/@apostrophecms/modal/ui/apos/components/AposModalConfirm.vue +6 -10
  54. package/modules/@apostrophecms/modal/ui/apos/components/AposModalShareDraft.vue +14 -16
  55. package/modules/@apostrophecms/modal/ui/apos/components/AposModalTabs.vue +68 -5
  56. package/modules/@apostrophecms/modal/ui/apos/components/AposWidgetModalTabs.vue +15 -9
  57. package/modules/@apostrophecms/modal/ui/apos/components/TheAposModals.vue +48 -122
  58. package/modules/@apostrophecms/modal/ui/apos/composables/AposFocus.js +9 -6
  59. package/modules/@apostrophecms/modal/ui/apos/mixins/AposDocsManagerMixin.js +38 -36
  60. package/modules/@apostrophecms/notification/ui/apos/components/AposNotification.vue +15 -9
  61. package/modules/@apostrophecms/notification/ui/apos/components/TheAposNotifications.vue +2 -2
  62. package/modules/@apostrophecms/page/index.js +9 -6
  63. package/modules/@apostrophecms/page/ui/apos/components/AposPagesManager.vue +3 -4
  64. package/modules/@apostrophecms/page/ui/apos/logic/AposPagesManager.js +5 -10
  65. package/modules/@apostrophecms/page/views/notFound.html +5 -5
  66. package/modules/@apostrophecms/permission/ui/apos/components/AposPermissionGrid.vue +6 -2
  67. package/modules/@apostrophecms/piece-page-type/index.js +1 -0
  68. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManager.vue +8 -12
  69. package/modules/@apostrophecms/piece-type/ui/apos/components/AposDocsManagerSelectBox.vue +2 -2
  70. package/modules/@apostrophecms/piece-type/ui/apos/components/AposRelationshipEditor.vue +1 -2
  71. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposRichTextWidgetEditor.vue +59 -41
  72. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapDivider.vue +1 -0
  73. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapMarks.vue +3 -1
  74. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapStyles.vue +3 -1
  75. package/modules/@apostrophecms/rich-text-widget/ui/apos/components/AposTiptapTable.vue +2 -0
  76. package/modules/@apostrophecms/rich-text-widget/ui/apos/tiptap-extensions/Classes.js +1 -7
  77. package/modules/@apostrophecms/rich-text-widget/ui/apos/tiptap-extensions/Heading.js +10 -0
  78. package/modules/@apostrophecms/schema/lib/addFieldTypes.js +8 -3
  79. package/modules/@apostrophecms/schema/ui/apos/components/AposArrayEditor.vue +4 -6
  80. package/modules/@apostrophecms/schema/ui/apos/components/AposInputArea.vue +1 -0
  81. package/modules/@apostrophecms/schema/ui/apos/components/AposInputBoolean.vue +5 -2
  82. package/modules/@apostrophecms/schema/ui/apos/components/AposInputColor.vue +1 -0
  83. package/modules/@apostrophecms/schema/ui/apos/components/AposInputDateAndTime.vue +1 -1
  84. package/modules/@apostrophecms/schema/ui/apos/components/AposInputObject.vue +2 -0
  85. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue +1 -0
  86. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRange.vue +14 -8
  87. package/modules/@apostrophecms/schema/ui/apos/components/AposInputRelationship.vue +4 -2
  88. package/modules/@apostrophecms/schema/ui/apos/components/AposInputSlug.vue +7 -1
  89. package/modules/@apostrophecms/schema/ui/apos/components/AposInputString.vue +3 -1
  90. package/modules/@apostrophecms/schema/ui/apos/components/AposInputWrapper.vue +35 -5
  91. package/modules/@apostrophecms/schema/ui/apos/components/AposSchema.vue +7 -4
  92. package/modules/@apostrophecms/schema/ui/apos/components/AposSearchList.vue +50 -15
  93. package/modules/@apostrophecms/schema/ui/apos/components/AposSubform.vue +5 -10
  94. package/modules/@apostrophecms/schema/ui/apos/logic/AposArrayEditor.js +19 -31
  95. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputRelationship.js +3 -0
  96. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputString.js +9 -0
  97. package/modules/@apostrophecms/schema/ui/apos/logic/AposInputWrapper.js +7 -0
  98. package/modules/@apostrophecms/schema/ui/apos/logic/AposSchema.js +11 -2
  99. package/modules/@apostrophecms/schema/ui/apos/logic/AposSearchList.js +3 -0
  100. package/modules/@apostrophecms/schema/ui/apos/mixins/AposInputMixin.js +5 -0
  101. package/modules/@apostrophecms/schema/ui/apos/scss/AposInputArray.scss +42 -9
  102. package/modules/@apostrophecms/search/index.js +1 -0
  103. package/modules/@apostrophecms/settings/index.js +33 -0
  104. package/modules/@apostrophecms/settings/ui/apos/components/AposSettingsManager.vue +6 -7
  105. package/modules/@apostrophecms/settings/ui/apos/logic/AposSettingsManager.js +0 -1
  106. package/modules/@apostrophecms/submitted-draft/index.js +26 -0
  107. package/modules/@apostrophecms/submitted-draft/ui/apos/components/AposSubmittedDraftIcon.vue +4 -4
  108. package/modules/@apostrophecms/template/views/templateError.html +4 -4
  109. package/modules/@apostrophecms/translation/ui/apos/components/AposTranslationIndicator.vue +2 -1
  110. package/modules/@apostrophecms/ui/ui/apos/components/AposAvatar.vue +3 -2
  111. package/modules/@apostrophecms/ui/ui/apos/components/AposButton.vue +62 -15
  112. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonGroup.vue +8 -0
  113. package/modules/@apostrophecms/ui/ui/apos/components/AposButtonSplit.vue +9 -3
  114. package/modules/@apostrophecms/ui/ui/apos/components/AposCellContextMenu.vue +2 -0
  115. package/modules/@apostrophecms/ui/ui/apos/components/AposCellLabels.vue +1 -0
  116. package/modules/@apostrophecms/ui/ui/apos/components/AposCloudUploadIcon.vue +5 -5
  117. package/modules/@apostrophecms/ui/ui/apos/components/AposCombo.vue +7 -5
  118. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenu.vue +8 -5
  119. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuDialog.vue +5 -3
  120. package/modules/@apostrophecms/ui/ui/apos/components/AposContextMenuItem.vue +22 -2
  121. package/modules/@apostrophecms/ui/ui/apos/components/AposEmptyState.vue +3 -1
  122. package/modules/@apostrophecms/ui/ui/apos/components/AposFile.vue +5 -1
  123. package/modules/@apostrophecms/ui/ui/apos/components/AposFilterMenu.vue +2 -1
  124. package/modules/@apostrophecms/ui/ui/apos/components/AposLabel.vue +1 -0
  125. package/modules/@apostrophecms/ui/ui/apos/components/AposMinMaxCount.vue +1 -0
  126. package/modules/@apostrophecms/ui/ui/apos/components/AposPager.vue +1 -0
  127. package/modules/@apostrophecms/ui/ui/apos/components/AposPagerDots.vue +3 -1
  128. package/modules/@apostrophecms/ui/ui/apos/components/AposSlat.vue +15 -2
  129. package/modules/@apostrophecms/ui/ui/apos/components/AposSlatList.vue +3 -1
  130. package/modules/@apostrophecms/ui/ui/apos/components/AposSpinner.vue +33 -7
  131. package/modules/@apostrophecms/ui/ui/apos/components/AposSubformPreview.vue +3 -2
  132. package/modules/@apostrophecms/ui/ui/apos/components/AposTag.vue +5 -3
  133. package/modules/@apostrophecms/ui/ui/apos/components/AposTagApply.vue +5 -2
  134. package/modules/@apostrophecms/ui/ui/apos/components/AposTagList.vue +5 -1
  135. package/modules/@apostrophecms/ui/ui/apos/components/AposTagListItem.vue +9 -1
  136. package/modules/@apostrophecms/ui/ui/apos/components/AposToggle.vue +13 -13
  137. package/modules/@apostrophecms/ui/ui/apos/components/AposTree.vue +1 -0
  138. package/modules/@apostrophecms/ui/ui/apos/components/AposTreeRows.vue +17 -7
  139. package/modules/@apostrophecms/ui/ui/apos/lib/vue.js +4 -0
  140. package/modules/@apostrophecms/ui/ui/apos/scss/global/_admin.scss +1 -1
  141. package/modules/@apostrophecms/ui/ui/apos/scss/global/_inputs.scss +28 -5
  142. package/modules/@apostrophecms/ui/ui/apos/scss/global/_scrollbars.scss +16 -0
  143. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tables.scss +8 -3
  144. package/modules/@apostrophecms/ui/ui/apos/scss/global/_theme.scss +9 -8
  145. package/modules/@apostrophecms/ui/ui/apos/scss/global/_tooltips.scss +13 -7
  146. package/modules/@apostrophecms/ui/ui/apos/scss/global/import-all.scss +1 -1
  147. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_input_mixins.scss +5 -3
  148. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_mixins.scss +1 -0
  149. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_responsive.scss +4 -3
  150. package/modules/@apostrophecms/ui/ui/apos/scss/mixins/_theme_mixins.scss +6 -0
  151. package/modules/@apostrophecms/ui/ui/apos/scss/shared/_table-rows.scss +6 -3
  152. package/modules/@apostrophecms/ui/ui/apos/stores/modal.js +180 -0
  153. package/modules/@apostrophecms/widget-type/ui/apos/components/AposWidgetEditor.vue +2 -2
  154. package/package.json +4 -4
  155. package/test/modules/@apostrophecms/search/views/index.html +1 -0
  156. package/test/pages.js +227 -0
  157. package/test/schemas.js +184 -0
  158. package/test/search.js +49 -13
@@ -80,6 +80,9 @@ export default {
80
80
  // of a piece (i.e. AposMediaManager)
81
81
  isModified() {
82
82
  return this.relationshipIsModified();
83
+ },
84
+ manuallyPublished() {
85
+ return this.moduleOptions.localized && !this.moduleOptions.autopublish;
83
86
  }
84
87
  },
85
88
  mounted() {
@@ -108,34 +111,56 @@ export default {
108
111
  doc._fields = this.subfields[doc._id];
109
112
  }
110
113
  }
111
- },
112
- checked() {
113
- this.updateCheckedDocs();
114
114
  }
115
115
  },
116
116
  methods: {
117
- findDocById(docs, id) {
118
- return docs.find(p => p._id === id);
117
+ addCheckedDoc(docOrId) {
118
+ this.concatCheckedDocs([ docOrId ]);
119
+ },
120
+ setCheckedDocs(docsOrIds) {
121
+ const docs = this.getDocs(docsOrIds);
122
+
123
+ this.checked = docs.map(item => item._id);
124
+ this.checkedDocs = docs;
125
+ },
126
+ concatCheckedDocs(docsOrIds) {
127
+ const docs = this.getDocs(docsOrIds);
128
+
129
+ this.checked = [ ...this.checked, ...docs.map(({ _id }) => _id) ];
130
+ this.checkedDocs = [ ...this.checkedDocs, ...docs ];
131
+ },
132
+ removeCheckedDoc(id) {
133
+ this.checked = this.checked.filter((checkedId) => checkedId !== id);
134
+ this.checkedDocs = this.checkedDocs.filter((doc) => doc.id !== id);
135
+ },
136
+ getDocs(docsOrIds) {
137
+ const items = this.moduleOptions.name === '@apostrophecms/page'
138
+ ? this.pagesFlat
139
+ : this.items;
140
+
141
+ return docsOrIds.map(docOrId => {
142
+ return docOrId._id
143
+ ? docOrId
144
+ : items.find(item => item._id === docOrId);
145
+ });
119
146
  },
120
147
  // It would have been nice for this to be computed, however
121
148
  // AposMediaManagerDisplay does not re-render when it is
122
149
  // a computed prop rather than a method call in the template.
123
150
  maxReached() {
124
151
  // Reaching max and exceeding it are different things
125
- const result = this.relationshipField.max && this.checked.length >= this.relationshipField.max;
126
- return result;
152
+ return this.relationshipField.max &&
153
+ this.checked.length >= this.relationshipField.max;
127
154
  },
128
155
  selectAll() {
129
156
  if (!this.checked.length) {
130
157
  this.items.forEach((item) => {
131
- const relationshipsMaxedOrUnpublished = this.relationshipField &&
132
- (this.maxReached() || !item.lastPublishedAt);
133
-
134
- if (relationshipsMaxedOrUnpublished) {
158
+ const notPublished = this.manuallyPublished && !item.lastPublishedAt;
159
+ if (this.relationshipField && (this.maxReached() || notPublished)) {
135
160
  return;
136
161
  }
137
162
 
138
- this.checked.push(item._id);
163
+ this.addCheckedDoc(item);
139
164
  });
140
165
 
141
166
  return;
@@ -145,7 +170,7 @@ export default {
145
170
  this.allPiecesSelection.isSelected = false;
146
171
  }
147
172
 
148
- this.checked = [];
173
+ this.setCheckedDocs([]);
149
174
  },
150
175
  iconSize(header) {
151
176
  if (header.icon) {
@@ -212,29 +237,6 @@ export default {
212
237
  }
213
238
  }
214
239
  },
215
- // update this.checkedDocs based on this.checked. The default
216
- // implementation is suitable for paginated lists. Can be overridden
217
- // for other cases.
218
- updateCheckedDocs() {
219
- // Keep `checkedDocs` in sync with `checked`, first removing from
220
- // `checkedDocs` if no longer in `checked`
221
- this.checkedDocs = this.checkedDocs.filter(doc => {
222
- return this.checked.includes(doc._id);
223
- });
224
- // then adding to `checkedDocs` if not there yet. These should be in
225
- // `items` which is assumed to contain a flat list of items currently
226
- // visible.
227
- //
228
- // TODO: Once we have the option to select all docs of a type even if not
229
- // currently visible in the manager this will need to make calls to the
230
- // database.
231
- this.checked.forEach(id => {
232
- if (this.checkedDocs.findIndex(doc => doc._id === id) === -1) {
233
- const found = this.items.find(item => item._id === id);
234
- found && this.checkedDocs.push(found);
235
- }
236
- });
237
- },
238
240
  docsManagerAddEventHandlers() {
239
241
  apos.bus.$on('content-changed', this.docsManagerOnContentChanged);
240
242
  },
@@ -212,21 +212,24 @@ export default {
212
212
  <style lang="scss" scoped>
213
213
  .apos-notification {
214
214
  @include apos-transition();
215
- pointer-events: auto;
215
+
216
216
  position: relative;
217
217
  display: inline-flex;
218
218
  overflow: hidden;
219
- min-width: 200px;
220
- max-width: 500px;
219
+ align-items: center;
221
220
  padding: 8px 35px 8px 8px;
222
221
  color: var(--a-text-inverted);
223
222
  background: var(--a-background-inverted);
223
+ pointer-events: auto;
224
+ min-width: 200px;
225
+ max-width: 500px;
224
226
  border-radius: 200px;
225
227
  box-shadow: var(--a-box-shadow);
226
- align-items: center;
228
+
227
229
  & + .apos-notification {
228
230
  margin-top: 8px;
229
231
  }
232
+
230
233
  &:hover {
231
234
  transform: translateY(-1px);
232
235
  }
@@ -266,17 +269,18 @@ export default {
266
269
  }
267
270
 
268
271
  .apos-notification__button {
272
+ @include apos-transition(all);
273
+
269
274
  position: absolute;
270
275
  right: 2px;
271
276
  display: flex;
272
- align-items: center;
273
277
  box-sizing: border-box;
278
+ align-items: center;
274
279
  height: 100%;
275
280
  padding: 20px 10px;
276
281
  border: none;
277
- background-color: transparent;
278
282
  color: var(--a-text-inverted);
279
- @include apos-transition(all);
283
+ background-color: transparent;
280
284
 
281
285
  &:hover {
282
286
  cursor: pointer;
@@ -290,12 +294,14 @@ export default {
290
294
  .apos-notification__label,
291
295
  .apos-notification__progress-value {
292
296
  @include type-base;
297
+
293
298
  color: var(--a-text-inverted);
294
299
  line-height: var(--a-line-tallest);
295
300
  }
296
301
 
297
302
  .apos-notification__label :deep(button) {
298
303
  @include apos-button-reset();
304
+
299
305
  text-decoration: underline;
300
306
  text-decoration-color: var(--a-success);
301
307
  text-underline-offset: 3px;
@@ -304,8 +310,8 @@ export default {
304
310
 
305
311
  .apos-notification__progress {
306
312
  display: flex;
307
- align-items: center;
308
313
  flex-shrink: 0;
314
+ align-items: center;
309
315
  }
310
316
 
311
317
  .apos-notification__progress-bar {
@@ -320,7 +326,7 @@ export default {
320
326
  height: 100%;
321
327
  background-color: var(--a-brand-green);
322
328
  background-image: linear-gradient(46deg, var(--a-brand-gold) 0%, var(--a-brand-red) 26%, var(--a-brand-magenta) 47%, var(--a-brand-blue) 76%, var(--a-brand-green) 100%);
323
- transition: width 0.5s ease-out;
329
+ transition: width 500ms ease-out;
324
330
  }
325
331
 
326
332
  .apos-notification__progress-value {
@@ -116,13 +116,13 @@ export default {
116
116
  <style lang="scss" scoped>
117
117
  .apos-notifications {
118
118
  z-index: $z-index-notifications;
119
- pointer-events: none;
120
119
  position: fixed;
121
120
  bottom: 20px;
122
121
  display: flex;
123
- width: 100%;
124
122
  flex-direction: column;
125
123
  align-items: center;
124
+ width: 100%;
125
+ pointer-events: none;
126
126
  }
127
127
 
128
128
  .list-enter-active,
@@ -77,7 +77,7 @@ module.exports = {
77
77
  modal: {
78
78
  [`${self.__meta.name}:manager`]: {
79
79
  '@apostrophecms/command-menu:manager': {
80
- label: '',
80
+ label: 'apostrophe:commandMenuManager',
81
81
  commands: [
82
82
  `${self.__meta.name}:create-new`,
83
83
  `${self.__meta.name}:exit-manager`
@@ -1276,11 +1276,14 @@ database.`);
1276
1276
  if (parent._id !== oldParent._id) {
1277
1277
  const matchOldParentSlugPrefix = new RegExp('^' + self.apos.util.regExpQuote(self.apos.util.addSlashIfNeeded(oldParent.slug)));
1278
1278
  if (moved.slug.match(matchOldParentSlugPrefix)) {
1279
- let slugStem = parent.slug;
1280
- if (slugStem !== '/') {
1281
- slugStem += '/';
1282
- }
1283
- moved.slug = moved.slug.replace(matchOldParentSlugPrefix, self.apos.util.addSlashIfNeeded(parent.slug));
1279
+ const movedSlugCandidate = moved.slug
1280
+ .split('/')
1281
+ .slice(0, -1)
1282
+ .join('/');
1283
+
1284
+ moved.slug = parent.slug.endsWith(movedSlugCandidate)
1285
+ ? parent.slug.replace(movedSlugCandidate, '').concat(moved.slug)
1286
+ : moved.slug.replace(matchOldParentSlugPrefix, self.apos.util.addSlashIfNeeded(parent.slug));
1284
1287
  changed.push({
1285
1288
  _id: moved._id,
1286
1289
  slug: moved.slug
@@ -3,7 +3,6 @@
3
3
  :modal="modal"
4
4
  modal-title="apostrophe:managePages"
5
5
  @esc="confirmAndCancel"
6
- @no-modal="$emit('safe-close')"
7
6
  @inactive="modal.active = false"
8
7
  @show-modal="modal.showModal = true"
9
8
  >
@@ -80,12 +79,13 @@
80
79
  </template>
81
80
  <template #bodyMain>
82
81
  <AposTree
83
- v-model:checked="checked"
82
+ :checked="checked"
84
83
  :items="items"
85
84
  :headers="headers"
86
85
  :icons="icons"
87
86
  :options="treeOptions"
88
87
  :module-options="moduleOptions"
88
+ @update:checked="setCheckedDocs"
89
89
  @update="update"
90
90
  />
91
91
  </template>
@@ -101,9 +101,8 @@ export default {
101
101
  name: 'AposPagesManager',
102
102
  mixins: [ AposPagesManagerLogic ],
103
103
  // Keep it for linting
104
- emits: [ 'archive', 'search', 'safe-close', 'modal-result' ]
104
+ emits: [ 'archive', 'search', 'modal-result' ]
105
105
  };
106
- // TODO: check when child page is created and with what perm
107
106
  </script>
108
107
 
109
108
  <style lang="scss" scoped>
@@ -9,7 +9,7 @@ import { klona } from 'klona';
9
9
  export default {
10
10
  name: 'AposPagesManager',
11
11
  mixins: [ AposModifiedMixin, AposDocsManagerMixin, AposArchiveMixin, AposPublishMixin ],
12
- emits: [ 'archive', 'search', 'safe-close', 'modal-result' ],
12
+ emits: [ 'archive', 'search', 'modal-result' ],
13
13
  data() {
14
14
 
15
15
  return {
@@ -49,7 +49,8 @@ export default {
49
49
  treeOptions: {
50
50
  bulkSelect: !!this.relationshipField,
51
51
  draggable: true,
52
- ghostUnpublished: true
52
+ ghostUnpublished: true,
53
+ max: this.relationshipField.max || null
53
54
  },
54
55
  moreMenu: [
55
56
  {
@@ -252,9 +253,9 @@ export default {
252
253
  },
253
254
  toggleRowCheck(id) {
254
255
  if (this.checked.includes(id)) {
255
- this.checked = this.checked.filter(item => item !== id);
256
+ this.removeCheckedDoc(id);
256
257
  } else {
257
- this.checked.push(id);
258
+ this.addCheckedDoc(id);
258
259
  }
259
260
  },
260
261
  selectAll(event) {
@@ -287,12 +288,6 @@ export default {
287
288
  this.checkedDocs.push(doc);
288
289
  this.checked.push(doc._id);
289
290
  }
290
- },
291
- setCheckedDocs(checkedDocs) {
292
- this.checked = checkedDocs.map(doc => doc._id);
293
- },
294
- updateCheckedDocs() {
295
- this.checkedDocs = this.checked.map(_id => this.pagesFlat.find(page => page._id === _id));
296
291
  }
297
292
  }
298
293
  };
@@ -36,10 +36,10 @@
36
36
  flex-direction: column;
37
37
  align-items: center;
38
38
  justify-content: center;
39
- transition: opacity 0.3s ease;
40
- transition-delay: 0.5s;
41
- animation: fadeIn 1s;
42
- -webkit-animation: fadeIn 1s;
39
+ transition: opacity 300ms ease;
40
+ transition-delay: 500ms;
41
+ animation: fadeIn 1000ms;
42
+ -webkit-animation: fadeIn 1000ms;
43
43
  }
44
44
 
45
45
  .apos-not-found__home-link {
@@ -93,4 +93,4 @@
93
93
  100% {opacity:1;}
94
94
  }
95
95
  </style>
96
- {% endblock %}
96
+ {% endblock %}
@@ -132,6 +132,7 @@ export default {
132
132
  <style lang="scss" scoped>
133
133
  .apos-input__role__permission-grid {
134
134
  @include type-base;
135
+
135
136
  display: grid;
136
137
  margin-top: $spacing-triple;
137
138
  grid-template-columns: repeat(auto-fit, minmax(50%, 1fr));
@@ -140,20 +141,23 @@ export default {
140
141
  .apos-input__role__permission-grid__row {
141
142
  display: flex;
142
143
  align-items: center;
143
- padding-bottom: $spacing-three-quarters;
144
144
  margin-bottom: $spacing-three-quarters;
145
+ padding-bottom: $spacing-three-quarters;
145
146
  border-bottom: 1px solid var(--a-base-9);
146
147
  }
148
+
147
149
  .apos-input__role__permission-grid__list {
148
150
  margin-top: 0;
149
151
  }
152
+
150
153
  .apos-input__role__permission-grid__set {
151
- padding: 0 $spacing-base;
152
154
  margin-bottom: $spacing-double;
155
+ padding: 0 $spacing-base;
153
156
  }
154
157
 
155
158
  .apos-input__role__permission-grid__set-name {
156
159
  @include type-title;
160
+
157
161
  display: inline-flex;
158
162
  margin: 0 0 $spacing-double;
159
163
  }
@@ -250,6 +250,7 @@ module.exports = {
250
250
  const parentPage = self.chooseParentPage(req.aposParentPageCache[pieceName], piece);
251
251
  if (parentPage) {
252
252
  piece._url = self.buildUrl(req, parentPage, piece);
253
+ piece._parent = parentPage;
253
254
  piece._parentUrl = parentPage._url;
254
255
  piece._parentSlug = parentPage.slug;
255
256
  }
@@ -4,7 +4,6 @@
4
4
  :modal="modal"
5
5
  :modal-title="modalTitle"
6
6
  @esc="confirmAndCancel"
7
- @no-modal="$emit('safe-close')"
8
7
  @inactive="modal.active = false"
9
8
  @show-modal="modal.showModal = true"
10
9
  >
@@ -103,7 +102,7 @@
103
102
  <template #bodyMain>
104
103
  <AposDocsManagerDisplay
105
104
  v-if="items.length > 0"
106
- v-model:checked="checked"
105
+ :checked="checked"
107
106
  :items="items"
108
107
  :headers="headers"
109
108
  :options="{
@@ -112,6 +111,7 @@
112
111
  disableUnpublished: disableUnpublished,
113
112
  manuallyPublished: manuallyPublished
114
113
  }"
114
+ @update:checked="setCheckedDocs"
115
115
  @open="edit"
116
116
  />
117
117
  <div v-else class="apos-pieces-manager__empty">
@@ -124,9 +124,11 @@
124
124
  </template>
125
125
 
126
126
  <script>
127
+ import { mapState } from 'pinia';
127
128
  import AposDocsManagerMixin from 'Modules/@apostrophecms/modal/mixins/AposDocsManagerMixin';
128
129
  import AposModifiedMixin from 'Modules/@apostrophecms/ui/mixins/AposModifiedMixin';
129
130
  import AposPublishMixin from 'Modules/@apostrophecms/ui/mixins/AposPublishMixin';
131
+ import { useModalStore } from 'Modules/@apostrophecms/ui/stores/modal';
130
132
  import { debounce } from 'Modules/@apostrophecms/ui/utils';
131
133
 
132
134
  export default {
@@ -140,7 +142,7 @@ export default {
140
142
  required: true
141
143
  }
142
144
  },
143
- emits: [ 'archive', 'safe-close' ],
145
+ emits: [ 'archive' ],
144
146
  data() {
145
147
  return {
146
148
  modal: {
@@ -167,6 +169,7 @@ export default {
167
169
  };
168
170
  },
169
171
  computed: {
172
+ ...mapState(useModalStore, [ 'activeModal' ]),
170
173
  moduleOptions() {
171
174
  return window.apos.modules[this.moduleName];
172
175
  },
@@ -252,12 +255,6 @@ export default {
252
255
  apos.bus.$off('command-menu-manager-close', this.confirmAndCancel);
253
256
  },
254
257
  methods: {
255
- setCheckedDocs(checked) {
256
- this.checkedDocs = checked;
257
- this.checked = this.checkedDocs.map(item => {
258
- return item._id;
259
- });
260
- },
261
258
  async create() {
262
259
  await this.edit(null);
263
260
  },
@@ -405,11 +402,10 @@ export default {
405
402
  },
406
403
  shortcutNew(event) {
407
404
  const interesting = event.keyCode === 78; // N(ew)
408
- const topModalId = apos.modal.stack.at(-1)?.id;
409
405
  if (
410
406
  interesting &&
411
407
  document.activeElement.tagName !== 'INPUT' &&
412
- this.$refs.modal.id === topModalId
408
+ this.$refs.modal.id === this.activeModal?.id
413
409
  ) {
414
410
  this.create();
415
411
  }
@@ -490,8 +486,8 @@ export default {
490
486
  // `apos-media-manager__empty`. We should combine somehow.
491
487
  .apos-pieces-manager__empty {
492
488
  display: flex;
493
- justify-content: center;
494
489
  align-items: center;
490
+ justify-content: center;
495
491
  width: 100%;
496
492
  height: 100%;
497
493
  margin-top: 130px;
@@ -115,10 +115,10 @@ export default {
115
115
  </script>
116
116
  <style lang='scss' scoped>
117
117
  .apos-select-box {
118
- box-sizing: border-box;
119
118
  overflow: hidden;
120
- max-height: 65px;
119
+ box-sizing: border-box;
121
120
  transition: max-height 200ms ease-in;
121
+ max-height: 65px;
122
122
 
123
123
  &.collapse-enter, &.collapse-leave-to {
124
124
  max-height: 0;
@@ -6,7 +6,6 @@
6
6
  @inactive="modal.active = false"
7
7
  @show-modal="modal.showModal = true"
8
8
  @esc="confirmAndCancel"
9
- @no-modal="$emit('safe-close')"
10
9
  >
11
10
  <template #secondaryControls>
12
11
  <AposButton
@@ -93,7 +92,7 @@ export default {
93
92
  required: true
94
93
  }
95
94
  },
96
- emits: [ 'modal-result', 'safe-close' ],
95
+ emits: [ 'modal-result' ],
97
96
  data() {
98
97
  return {
99
98
  docReady: false,