@webiny/app-headless-cms 6.5.0-beta.0 → 6.5.0-beta.10

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 (208) hide show
  1. package/ContentEntriesModule.js +14 -2
  2. package/ContentEntriesModule.js.map +1 -1
  3. package/admin/components/ContentEntries/BulkActions/ActionDelete.d.ts +2 -2
  4. package/admin/components/ContentEntries/BulkActions/ActionDelete.js.map +1 -1
  5. package/admin/components/ContentEntries/BulkActions/ActionMove.d.ts +2 -2
  6. package/admin/components/ContentEntries/BulkActions/ActionMove.js.map +1 -1
  7. package/admin/components/ContentEntries/BulkActions/ActionPublish.d.ts +2 -2
  8. package/admin/components/ContentEntries/BulkActions/ActionPublish.js.map +1 -1
  9. package/admin/components/ContentEntries/BulkActions/ActionUnpublish.d.ts +2 -2
  10. package/admin/components/ContentEntries/BulkActions/ActionUnpublish.js.map +1 -1
  11. package/admin/components/ContentEntries/Filters/RefFieldRenderer.d.ts +2 -0
  12. package/admin/components/ContentEntries/Filters/RefFieldRenderer.js +84 -0
  13. package/admin/components/ContentEntries/Filters/RefFieldRenderer.js.map +1 -0
  14. package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.d.ts +2 -0
  15. package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.js +34 -0
  16. package/admin/components/ContentEntries/Table/Actions/DuplicateEntry.js.map +1 -0
  17. package/admin/components/ContentEntries/Table/Actions/index.d.ts +1 -0
  18. package/admin/components/ContentEntries/Table/Actions/index.js +1 -0
  19. package/admin/components/ContentModelEditor/ContentModelEditor.js +1 -1
  20. package/admin/components/ContentModelEditor/ContentModelEditor.js.map +1 -1
  21. package/admin/components/Dialogs/DuplicateEntryConfirmDialog.d.ts +2 -0
  22. package/admin/components/Dialogs/DuplicateEntryConfirmDialog.js +22 -0
  23. package/admin/components/Dialogs/DuplicateEntryConfirmDialog.js.map +1 -0
  24. package/admin/components/FieldEditor/EditFieldDialog.d.ts +2 -2
  25. package/admin/components/FieldEditor/Field.js +4 -4
  26. package/admin/components/FieldEditor/Field.js.map +1 -1
  27. package/features/contentEntry/CmsEntryError.d.ts +10 -0
  28. package/features/contentEntry/CmsEntryError.js +11 -0
  29. package/features/contentEntry/CmsEntryError.js.map +1 -0
  30. package/features/contentEntry/createEntry/CreateEntryGateway.d.ts +0 -1
  31. package/features/contentEntry/createEntry/CreateEntryGateway.js +3 -10
  32. package/features/contentEntry/createEntry/CreateEntryGateway.js.map +1 -1
  33. package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.d.ts +3 -1
  34. package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.js +8 -3
  35. package/features/contentEntry/createRevisionFrom/CreateRevisionFromGateway.js.map +1 -1
  36. package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.d.ts +14 -0
  37. package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.js +43 -0
  38. package/features/contentEntry/duplicateEntry/DuplicateEntryGateway.js.map +1 -0
  39. package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.d.ts +15 -0
  40. package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.js +34 -0
  41. package/features/contentEntry/duplicateEntry/DuplicateEntryRepository.js.map +1 -0
  42. package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.d.ts +11 -0
  43. package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.js +18 -0
  44. package/features/contentEntry/duplicateEntry/DuplicateEntryUseCase.js.map +1 -0
  45. package/features/contentEntry/duplicateEntry/abstractions.d.ts +26 -0
  46. package/features/contentEntry/duplicateEntry/abstractions.js +7 -0
  47. package/features/contentEntry/duplicateEntry/abstractions.js.map +1 -0
  48. package/features/contentEntry/duplicateEntry/feature.d.ts +3 -0
  49. package/features/contentEntry/duplicateEntry/feature.js +21 -0
  50. package/features/contentEntry/duplicateEntry/feature.js.map +1 -0
  51. package/features/contentEntry/entryValueGateways.test.d.ts +1 -0
  52. package/features/contentEntry/entryValueGateways.test.js +106 -0
  53. package/features/contentEntry/entryValueGateways.test.js.map +1 -0
  54. package/features/contentEntry/feature.js +2 -0
  55. package/features/contentEntry/feature.js.map +1 -1
  56. package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.d.ts +0 -1
  57. package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.js +3 -10
  58. package/features/contentEntry/singletonEntry/UpdateSingletonEntryGateway.js.map +1 -1
  59. package/features/contentEntry/updateEntry/UpdateEntryGateway.d.ts +0 -1
  60. package/features/contentEntry/updateEntry/UpdateEntryGateway.js +3 -10
  61. package/features/contentEntry/updateEntry/UpdateEntryGateway.js.map +1 -1
  62. package/features/contentEntry/valueTransformers/EntryDataPreparer.d.ts +9 -0
  63. package/features/contentEntry/valueTransformers/EntryDataPreparer.js +8 -0
  64. package/features/contentEntry/valueTransformers/EntryDataPreparer.js.map +1 -1
  65. package/features/contentEntry/valueTransformers/EntryDataPreparer.test.d.ts +1 -0
  66. package/features/contentEntry/valueTransformers/EntryDataPreparer.test.js +113 -0
  67. package/features/contentEntry/valueTransformers/EntryDataPreparer.test.js.map +1 -0
  68. package/features/contentEntry/valueTransformers/entryValueFixtures.d.ts +146 -0
  69. package/features/contentEntry/valueTransformers/entryValueFixtures.js +171 -0
  70. package/features/contentEntry/valueTransformers/entryValueFixtures.js.map +1 -0
  71. package/features/formModel/CmsFormModelBuilder.d.ts +9 -1
  72. package/features/formModel/CmsFormModelBuilder.js +26 -15
  73. package/features/formModel/CmsFormModelBuilder.js.map +1 -1
  74. package/features/formModel/CmsFormModelBuilder.test.d.ts +1 -0
  75. package/features/formModel/CmsFormModelBuilder.test.js +252 -0
  76. package/features/formModel/CmsFormModelBuilder.test.js.map +1 -0
  77. package/features/formModel/CmsLayoutMapper.d.ts +8 -1
  78. package/features/formModel/CmsLayoutMapper.js +23 -1
  79. package/features/formModel/CmsLayoutMapper.js.map +1 -1
  80. package/features/formModel/mappers/DynamicZoneFieldMapper.js +4 -0
  81. package/features/formModel/mappers/DynamicZoneFieldMapper.js.map +1 -1
  82. package/features/formModel/mappers/ObjectFieldMapper.js +11 -6
  83. package/features/formModel/mappers/ObjectFieldMapper.js.map +1 -1
  84. package/features/model/exportModels/ExportModelsGateway.d.ts +1 -1
  85. package/features/model/exportModels/ExportModelsGateway.js.map +1 -1
  86. package/features/model/exportModels/ExportModelsUseCase.js +7 -1
  87. package/features/model/exportModels/ExportModelsUseCase.js.map +1 -1
  88. package/features/model/exportModels/abstractions.d.ts +8 -2
  89. package/features/model/exportModels/abstractions.js.map +1 -1
  90. package/package.json +26 -26
  91. package/presentation/cloneContentModel/CloneContentModelPresenter.d.ts +1 -0
  92. package/presentation/cloneContentModel/CloneContentModelPresenter.js +8 -6
  93. package/presentation/cloneContentModel/CloneContentModelPresenter.js.map +1 -1
  94. package/presentation/contentEntries/form/ContentEntryFormPresenter.js +34 -29
  95. package/presentation/contentEntries/form/ContentEntryFormPresenter.js.map +1 -1
  96. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.d.ts +1 -0
  97. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js +210 -0
  98. package/presentation/contentEntries/form/ContentEntryFormPresenter.test.js.map +1 -0
  99. package/presentation/contentEntries/form/toFormErrors.d.ts +7 -0
  100. package/presentation/contentEntries/form/toFormErrors.js +49 -0
  101. package/presentation/contentEntries/form/toFormErrors.js.map +1 -0
  102. package/presentation/contentEntries/form/toFormErrors.test.d.ts +1 -0
  103. package/presentation/contentEntries/form/toFormErrors.test.js +175 -0
  104. package/presentation/contentEntries/form/toFormErrors.test.js.map +1 -0
  105. package/presentation/contentEntries/list/ContentEntriesDataSource.d.ts +5 -0
  106. package/presentation/contentEntries/list/ContentEntriesDataSource.js +11 -2
  107. package/presentation/contentEntries/list/ContentEntriesDataSource.js.map +1 -1
  108. package/presentation/contentEntries/list/ContentEntriesPresenter.d.ts +6 -2
  109. package/presentation/contentEntries/list/ContentEntriesPresenter.js +27 -2
  110. package/presentation/contentEntries/list/ContentEntriesPresenter.js.map +1 -1
  111. package/presentation/contentEntries/list/ContentEntriesPresenter.test.js +130 -5
  112. package/presentation/contentEntries/list/ContentEntriesPresenter.test.js.map +1 -1
  113. package/presentation/contentEntries/list/abstractions.d.ts +12 -0
  114. package/presentation/contentEntries/list/abstractions.js.map +1 -1
  115. package/presentation/contentEntries/preview/LivePreviewPresenter.d.ts +12 -1
  116. package/presentation/contentEntries/preview/LivePreviewPresenter.js +48 -5
  117. package/presentation/contentEntries/preview/LivePreviewPresenter.js.map +1 -1
  118. package/presentation/contentEntries/preview/LivePreviewPresenter.test.d.ts +1 -0
  119. package/presentation/contentEntries/preview/LivePreviewPresenter.test.js +81 -0
  120. package/presentation/contentEntries/preview/LivePreviewPresenter.test.js.map +1 -0
  121. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js +1 -1
  122. package/presentation/contentEntries/preview/ModelEditorComponentDiscovery.js.map +1 -1
  123. package/presentation/contentEntries/preview/PreviewDecorator.js +25 -6
  124. package/presentation/contentEntries/preview/PreviewDecorator.js.map +1 -1
  125. package/presentation/contentEntries/preview/PreviewDomainStatus.d.ts +10 -0
  126. package/presentation/contentEntries/preview/PreviewDomainStatus.js +19 -0
  127. package/presentation/contentEntries/preview/PreviewDomainStatus.js.map +1 -0
  128. package/presentation/contentEntries/preview/PreviewPane.d.ts +10 -1
  129. package/presentation/contentEntries/preview/PreviewPane.js +81 -45
  130. package/presentation/contentEntries/preview/PreviewPane.js.map +1 -1
  131. package/presentation/contentEntries/preview/abstractions.d.ts +8 -0
  132. package/presentation/contentEntries/preview/abstractions.js.map +1 -1
  133. package/presentation/contentEntries/preview/resolvePreviewUrl.d.ts +21 -0
  134. package/presentation/contentEntries/preview/resolvePreviewUrl.js +50 -1
  135. package/presentation/contentEntries/preview/resolvePreviewUrl.js.map +1 -1
  136. package/presentation/contentEntries/preview/resolvePreviewUrl.test.d.ts +1 -0
  137. package/presentation/contentEntries/preview/resolvePreviewUrl.test.js +127 -0
  138. package/presentation/contentEntries/preview/resolvePreviewUrl.test.js.map +1 -0
  139. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.js +9 -4
  140. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.js.map +1 -1
  141. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.d.ts +1 -0
  142. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js +122 -0
  143. package/presentation/contentEntries/singleEntry/SingleEntryPresenter.test.js.map +1 -0
  144. package/presentation/contentEntries/trashBin/CmsTrashBin.d.ts +2 -2
  145. package/presentation/contentEntries/views/CmsAdvancedSearch.d.ts +2 -2
  146. package/presentation/contentEntries/views/ContentEntriesListLayout.d.ts +2 -2
  147. package/presentation/contentEntries/views/ContentEntryFormView.d.ts +2 -2
  148. package/presentation/contentEntries/views/OlderRevisionAlert.d.ts +2 -2
  149. package/presentation/contentEntries/views/RevisionDrawer.d.ts +2 -2
  150. package/presentation/contentEntries/views/RevisionsList.d.ts +2 -2
  151. package/presentation/contentEntries/views/SingleEntryLayout.d.ts +2 -2
  152. package/presentation/contentEntries/views/Table/Table.d.ts +2 -2
  153. package/presentation/contentEntries/views/actions/CreateNewRevisionButton.d.ts +2 -2
  154. package/presentation/contentEntries/views/actions/DeleteEntryMenuItem.d.ts +2 -2
  155. package/presentation/contentEntries/views/actions/PublishOnlyButton.d.ts +2 -2
  156. package/presentation/contentEntries/views/actions/RevisionSelector.d.ts +2 -2
  157. package/presentation/contentEntries/views/actions/SaveAndPublishButton.d.ts +2 -2
  158. package/presentation/contentEntries/views/actions/SaveContentButton.d.ts +2 -2
  159. package/presentation/contentEntries/views/actions/ShowRevisionListMenuItem.d.ts +2 -2
  160. package/presentation/contentEntries/views/layout/ContentEntryForm.d.ts +12 -12
  161. package/presentation/contentModels/ContentModelsPresenter.d.ts +5 -5
  162. package/presentation/contentModels/ContentModelsPresenter.js +1 -1
  163. package/presentation/contentModels/ContentModelsPresenter.js.map +1 -1
  164. package/presentation/contentModels/abstractions.d.ts +7 -2
  165. package/presentation/contentModels/abstractions.js.map +1 -1
  166. package/presentation/contentModels/components/CloneContentModelDialog.d.ts +2 -2
  167. package/presentation/contentModels/components/ContentModels.d.ts +2 -2
  168. package/presentation/contentModels/components/ContentModelsDataList.d.ts +2 -2
  169. package/presentation/contentModels/components/ContentModelsDataList.js +6 -5
  170. package/presentation/contentModels/components/ContentModelsDataList.js.map +1 -1
  171. package/presentation/contentModels/components/NewContentModelDialog.d.ts +2 -2
  172. package/presentation/contentModels/components/fullDelete/dialog/Content.js +2 -2
  173. package/presentation/contentModels/components/fullDelete/dialog/Content.js.map +1 -1
  174. package/presentation/contentModels/components/fullDelete/types.js.map +1 -1
  175. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.d.ts +1 -0
  176. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js +133 -0
  177. package/presentation/fieldRenderers/ref/autocomplete/RefAutocompletePresenters.test.js.map +1 -0
  178. package/presentation/fieldRenderers/ref/autocomplete/multi/RefMultiAutocompletePresenter.js +1 -1
  179. package/presentation/fieldRenderers/ref/autocomplete/multi/RefMultiAutocompletePresenter.js.map +1 -1
  180. package/presentation/fieldRenderers/ref/autocomplete/single/RefSingleAutocompletePresenter.js +1 -1
  181. package/presentation/fieldRenderers/ref/autocomplete/single/RefSingleAutocompletePresenter.js.map +1 -1
  182. package/presentation/fieldRenderers/ref/components/RefFieldOptions.d.ts +2 -2
  183. package/presentation/fieldRenderers/ref/components/RefFieldOptions.js +3 -2
  184. package/presentation/fieldRenderers/ref/components/RefFieldOptions.js.map +1 -1
  185. package/presentation/importContentModels/ImportContentModelsDialog.d.ts +2 -2
  186. package/presentation/importContentModels/ImportContentModelsPresenter.js +1 -1
  187. package/presentation/importContentModels/ImportContentModelsPresenter.js.map +1 -1
  188. package/presentation/importContentModels/components/DataList.d.ts +2 -2
  189. package/presentation/importContentModels/components/FileUpload.d.ts +2 -2
  190. package/presentation/importContentModels/components/FileUpload.js +1 -1
  191. package/presentation/importContentModels/components/FileUpload.js.map +1 -1
  192. package/presentation/importContentModels/components/Model/DataListModelItem.js +3 -3
  193. package/presentation/importContentModels/components/Model/DataListModelItem.js.map +1 -1
  194. package/presentation/importContentModels/components/Model/DataListModelItemInfo.js +2 -2
  195. package/presentation/importContentModels/components/Model/DataListModelItemInfo.js.map +1 -1
  196. package/presentation/importContentModels/components/Model/DataListModels.d.ts +2 -2
  197. package/presentation/menus/ContentGroupsMenuItems.d.ts +2 -2
  198. package/presentation/modelGroup/ModelGroupPresenter.js +1 -2
  199. package/presentation/modelGroup/ModelGroupPresenter.js.map +1 -1
  200. package/presentation/modelGroup/components/ContentModelGroups.d.ts +2 -2
  201. package/presentation/modelGroup/components/ContentModelGroupsDataList.d.ts +6 -2
  202. package/presentation/modelGroup/components/ContentModelGroupsForm.d.ts +8 -2
  203. package/presentation/newContentModel/NewContentModelPresenter.d.ts +1 -0
  204. package/presentation/newContentModel/NewContentModelPresenter.js +8 -6
  205. package/presentation/newContentModel/NewContentModelPresenter.js.map +1 -1
  206. package/utils/normalizeIcon.d.ts +4 -0
  207. package/utils/normalizeIcon.js +9 -6
  208. package/utils/normalizeIcon.js.map +1 -1
@@ -5,11 +5,20 @@ class ContentEntriesDataSource extends FolderAwareDataSource {
5
5
  locationField: "wbyAco_location",
6
6
  keyField: "entryId",
7
7
  registeredFilterNames,
8
- getDescendantFolders: getDescendantFoldersUseCase
8
+ getDescendantFolders: getDescendantFoldersUseCase,
9
+ getSortValue: (entry, field)=>this.getSortValue(entry, field)
9
10
  }), this.model = model, this.listEntriesUseCase = listEntriesUseCase, this.cache = cache;
10
11
  }
11
12
  get rows() {
12
- return this.queryMatcher.filter(this.cache.getItems());
13
+ return this.queryMatcher.select(this.cache.getItems());
14
+ }
15
+ getSortValue(entry, field) {
16
+ if ("live" === field) return entry.lastPublishedOn;
17
+ if ("name" === field) {
18
+ const titleFieldId = this.model.titleFieldId;
19
+ return titleFieldId ? entry.values?.[titleFieldId] : entry.id;
20
+ }
21
+ return entry[field];
13
22
  }
14
23
  async fetch(params) {
15
24
  return this.listEntriesUseCase.execute({
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/list/ContentEntriesDataSource.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesDataSource.ts"],"sourcesContent":["import { FolderAwareDataSource } from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type {\n FetchParams,\n FetchResult\n} from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport type { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport type { IListEntriesUseCase } from \"~/features/contentEntry/listEntries/abstractions.js\";\n\nexport class ContentEntriesDataSource extends FolderAwareDataSource<CmsContentEntry> {\n constructor(\n private model: CmsModel,\n private listEntriesUseCase: IListEntriesUseCase,\n private cache: IListCache<CmsContentEntry>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase,\n registeredFilterNames: string[] = []\n ) {\n super({\n locationField: \"wbyAco_location\",\n keyField: \"entryId\",\n registeredFilterNames,\n getDescendantFolders: getDescendantFoldersUseCase\n });\n }\n\n get rows(): CmsContentEntry[] {\n return this.queryMatcher.filter(this.cache.getItems());\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<CmsContentEntry>> {\n return this.listEntriesUseCase.execute({\n model: this.model,\n where: params.where,\n sort: this.mapSort(params.sort),\n search: params.search,\n limit: params.limit,\n after: params.after\n });\n }\n\n private mapSort(sort: string[] | undefined): string[] | undefined {\n if (!sort) {\n return undefined;\n }\n\n const titleFieldId = this.model.titleFieldId;\n\n return sort.map(s => {\n if (s.startsWith(\"live_\")) {\n return s.replace(/^live_/, \"lastPublishedOn_\");\n }\n if (s.startsWith(\"name_\")) {\n return titleFieldId\n ? s.replace(/^name_/, `values_${titleFieldId}_`)\n : s.replace(/^name_/, \"id_\");\n }\n return s;\n });\n }\n}\n"],"names":["ContentEntriesDataSource","FolderAwareDataSource","model","listEntriesUseCase","cache","getDescendantFoldersUseCase","registeredFilterNames","params","sort","titleFieldId","s"],"mappings":";AAUO,MAAMA,iCAAiCC;IAC1C,YACYC,KAAe,EACfC,kBAAuC,EACvCC,KAAkC,EAC1CC,2BAA0D,EAC1DC,wBAAkC,EAAE,CACtC;QACE,KAAK,CAAC;YACF,eAAe;YACf,UAAU;YACVA;YACA,sBAAsBD;QAC1B,SAXQH,KAAK,GAALA,OAAAA,IAAAA,CACAC,kBAAkB,GAAlBA,oBAAAA,IAAAA,CACAC,KAAK,GAALA;IAUZ;IAEA,IAAI,OAA0B;QAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;IACvD;IAEA,MAAM,MAAMG,MAAmB,EAAyC;QACpE,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK;YACjB,OAAOA,OAAO,KAAK;YACnB,MAAM,IAAI,CAAC,OAAO,CAACA,OAAO,IAAI;YAC9B,QAAQA,OAAO,MAAM;YACrB,OAAOA,OAAO,KAAK;YACnB,OAAOA,OAAO,KAAK;QACvB;IACJ;IAEQ,QAAQC,IAA0B,EAAwB;QAC9D,IAAI,CAACA,MACD;QAGJ,MAAMC,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;QAE5C,OAAOD,KAAK,GAAG,CAACE,CAAAA;YACZ,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOA,EAAE,OAAO,CAAC,UAAU;YAE/B,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOD,eACDC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,EAAED,aAAa,CAAC,CAAC,IAC7CC,EAAE,OAAO,CAAC,UAAU;YAE9B,OAAOA;QACX;IACJ;AACJ"}
1
+ {"version":3,"file":"presentation/contentEntries/list/ContentEntriesDataSource.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesDataSource.ts"],"sourcesContent":["import { FolderAwareDataSource } from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type {\n FetchParams,\n FetchResult\n} from \"@webiny/app-admin/presentation/listPresenter/FolderAwareDataSource.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport type { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport type { IListEntriesUseCase } from \"~/features/contentEntry/listEntries/abstractions.js\";\n\nexport class ContentEntriesDataSource extends FolderAwareDataSource<CmsContentEntry> {\n constructor(\n private model: CmsModel,\n private listEntriesUseCase: IListEntriesUseCase,\n private cache: IListCache<CmsContentEntry>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase,\n registeredFilterNames: string[] = []\n ) {\n super({\n locationField: \"wbyAco_location\",\n keyField: \"entryId\",\n registeredFilterNames,\n getDescendantFolders: getDescendantFoldersUseCase,\n getSortValue: (entry, field) => this.getSortValue(entry, field)\n });\n }\n\n get rows(): CmsContentEntry[] {\n return this.queryMatcher.select(this.cache.getItems());\n }\n\n /**\n * Mirrors `mapSort`: the list's sort fields that are not entry fields map to the\n * fields the API sorts by.\n */\n private getSortValue(entry: CmsContentEntry, field: string): unknown {\n if (field === \"live\") {\n return entry.lastPublishedOn;\n }\n if (field === \"name\") {\n const titleFieldId = this.model.titleFieldId;\n return titleFieldId ? entry.values?.[titleFieldId] : entry.id;\n }\n return (entry as unknown as Record<string, unknown>)[field];\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<CmsContentEntry>> {\n return this.listEntriesUseCase.execute({\n model: this.model,\n where: params.where,\n sort: this.mapSort(params.sort),\n search: params.search,\n limit: params.limit,\n after: params.after\n });\n }\n\n private mapSort(sort: string[] | undefined): string[] | undefined {\n if (!sort) {\n return undefined;\n }\n\n const titleFieldId = this.model.titleFieldId;\n\n return sort.map(s => {\n if (s.startsWith(\"live_\")) {\n return s.replace(/^live_/, \"lastPublishedOn_\");\n }\n if (s.startsWith(\"name_\")) {\n return titleFieldId\n ? s.replace(/^name_/, `values_${titleFieldId}_`)\n : s.replace(/^name_/, \"id_\");\n }\n return s;\n });\n }\n}\n"],"names":["ContentEntriesDataSource","FolderAwareDataSource","model","listEntriesUseCase","cache","getDescendantFoldersUseCase","registeredFilterNames","entry","field","titleFieldId","params","sort","s"],"mappings":";AAUO,MAAMA,iCAAiCC;IAC1C,YACYC,KAAe,EACfC,kBAAuC,EACvCC,KAAkC,EAC1CC,2BAA0D,EAC1DC,wBAAkC,EAAE,CACtC;QACE,KAAK,CAAC;YACF,eAAe;YACf,UAAU;YACVA;YACA,sBAAsBD;YACtB,cAAc,CAACE,OAAOC,QAAU,IAAI,CAAC,YAAY,CAACD,OAAOC;QAC7D,SAZQN,KAAK,GAALA,OAAAA,IAAAA,CACAC,kBAAkB,GAAlBA,oBAAAA,IAAAA,CACAC,KAAK,GAALA;IAWZ;IAEA,IAAI,OAA0B;QAC1B,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;IACvD;IAMQ,aAAaG,KAAsB,EAAEC,KAAa,EAAW;QACjE,IAAIA,AAAU,WAAVA,OACA,OAAOD,MAAM,eAAe;QAEhC,IAAIC,AAAU,WAAVA,OAAkB;YAClB,MAAMC,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;YAC5C,OAAOA,eAAeF,MAAM,MAAM,EAAE,CAACE,aAAa,GAAGF,MAAM,EAAE;QACjE;QACA,OAAQA,KAA4C,CAACC,MAAM;IAC/D;IAEA,MAAM,MAAME,MAAmB,EAAyC;QACpE,OAAO,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK;YACjB,OAAOA,OAAO,KAAK;YACnB,MAAM,IAAI,CAAC,OAAO,CAACA,OAAO,IAAI;YAC9B,QAAQA,OAAO,MAAM;YACrB,OAAOA,OAAO,KAAK;YACnB,OAAOA,OAAO,KAAK;QACvB;IACJ;IAEQ,QAAQC,IAA0B,EAAwB;QAC9D,IAAI,CAACA,MACD;QAGJ,MAAMF,eAAe,IAAI,CAAC,KAAK,CAAC,YAAY;QAE5C,OAAOE,KAAK,GAAG,CAACC,CAAAA;YACZ,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOA,EAAE,OAAO,CAAC,UAAU;YAE/B,IAAIA,EAAE,UAAU,CAAC,UACb,OAAOH,eACDG,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,EAAEH,aAAa,CAAC,CAAC,IAC7CG,EAAE,OAAO,CAAC,UAAU;YAE9B,OAAOA;QACX;IACJ;AACJ"}
@@ -8,12 +8,14 @@ import { DeleteEntryUseCase } from "../../../features/contentEntry/deleteEntry/a
8
8
  import { PublishEntryUseCase } from "../../../features/contentEntry/publishEntry/abstractions.js";
9
9
  import { UnpublishEntryUseCase } from "../../../features/contentEntry/unpublishEntry/abstractions.js";
10
10
  import { MoveEntryUseCase } from "../../../features/contentEntry/moveEntry/abstractions.js";
11
+ import { DuplicateEntryUseCase } from "../../../features/contentEntry/duplicateEntry/abstractions.js";
11
12
  import { UpdateRevisionDescriptionUseCase } from "../../../features/contentEntry/updateRevisionDescription/abstractions.js";
12
13
  import { ContentEntriesCacheProvider, CmsModelContext } from "../../../features/contentEntry/abstractions.js";
13
- import { ContentEntriesPresenter as Abstraction, type IContentEntriesViewModel } from "./abstractions.js";
14
+ import { ContentEntriesPresenter as Abstraction, type IContentEntriesViewModel, type IDuplicateEntryResult } from "./abstractions.js";
14
15
  export declare const TRASH_ENTRY_DIALOG = "trash-entry";
15
16
  export declare const PUBLISH_ENTRY_DIALOG = "publish-entry";
16
17
  export declare const UNPUBLISH_ENTRY_DIALOG = "unpublish-entry";
18
+ export declare const DUPLICATE_ENTRY_DIALOG = "duplicate-entry";
17
19
  declare class ContentEntriesPresenterImpl implements Abstraction.Interface {
18
20
  private listPresenter;
19
21
  private foldersPresenter;
@@ -24,12 +26,13 @@ declare class ContentEntriesPresenterImpl implements Abstraction.Interface {
24
26
  private publishEntryUseCase;
25
27
  private unpublishEntryUseCase;
26
28
  private moveEntryUseCase;
29
+ private duplicateEntryUseCase;
27
30
  private updateRevisionDescriptionUseCase;
28
31
  private cacheProvider;
29
32
  private getDescendantFoldersUseCase;
30
33
  private selectedEntryId;
31
34
  private disposeReaction;
32
- constructor(listPresenter: ListPresenter.Interface<CmsContentEntry>, foldersPresenter: FolderTreePresenter.Interface, confirmation: Confirmation.Interface, modelAccessor: CmsModelContext.Interface, listEntriesUseCase: ListEntriesUseCase.Interface, deleteEntryUseCase: DeleteEntryUseCase.Interface, publishEntryUseCase: PublishEntryUseCase.Interface, unpublishEntryUseCase: UnpublishEntryUseCase.Interface, moveEntryUseCase: MoveEntryUseCase.Interface, updateRevisionDescriptionUseCase: UpdateRevisionDescriptionUseCase.Interface, cacheProvider: ContentEntriesCacheProvider.Interface, getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface);
35
+ constructor(listPresenter: ListPresenter.Interface<CmsContentEntry>, foldersPresenter: FolderTreePresenter.Interface, confirmation: Confirmation.Interface, modelAccessor: CmsModelContext.Interface, listEntriesUseCase: ListEntriesUseCase.Interface, deleteEntryUseCase: DeleteEntryUseCase.Interface, publishEntryUseCase: PublishEntryUseCase.Interface, unpublishEntryUseCase: UnpublishEntryUseCase.Interface, moveEntryUseCase: MoveEntryUseCase.Interface, duplicateEntryUseCase: DuplicateEntryUseCase.Interface, updateRevisionDescriptionUseCase: UpdateRevisionDescriptionUseCase.Interface, cacheProvider: ContentEntriesCacheProvider.Interface, getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface);
33
36
  private get model();
34
37
  get vm(): IContentEntriesViewModel;
35
38
  init(config?: Abstraction.InitConfig): void;
@@ -42,6 +45,7 @@ declare class ContentEntriesPresenterImpl implements Abstraction.Interface {
42
45
  publishEntry(id: string): Promise<boolean>;
43
46
  unpublishEntry(id: string): Promise<boolean>;
44
47
  moveEntry(id: string, folderId: string): Promise<boolean>;
48
+ duplicateEntry(entry: CmsContentEntry): Promise<IDuplicateEntryResult | false>;
45
49
  dispose(): void;
46
50
  }
47
51
  export declare const ContentEntriesPresenter: typeof ContentEntriesPresenterImpl & {
@@ -9,6 +9,7 @@ import { DeleteEntryUseCase } from "../../../features/contentEntry/deleteEntry/a
9
9
  import { PublishEntryUseCase } from "../../../features/contentEntry/publishEntry/abstractions.js";
10
10
  import { UnpublishEntryUseCase } from "../../../features/contentEntry/unpublishEntry/abstractions.js";
11
11
  import { MoveEntryUseCase } from "../../../features/contentEntry/moveEntry/abstractions.js";
12
+ import { DuplicateEntryUseCase } from "../../../features/contentEntry/duplicateEntry/abstractions.js";
12
13
  import { UpdateRevisionDescriptionUseCase } from "../../../features/contentEntry/updateRevisionDescription/abstractions.js";
13
14
  import { CmsModelContext, ContentEntriesCacheProvider } from "../../../features/contentEntry/abstractions.js";
14
15
  import { ContentEntriesPresenter } from "./abstractions.js";
@@ -16,8 +17,9 @@ import { ContentEntriesDataSource } from "./ContentEntriesDataSource.js";
16
17
  const TRASH_ENTRY_DIALOG = "trash-entry";
17
18
  const PUBLISH_ENTRY_DIALOG = "publish-entry";
18
19
  const UNPUBLISH_ENTRY_DIALOG = "unpublish-entry";
20
+ const DUPLICATE_ENTRY_DIALOG = "duplicate-entry";
19
21
  class ContentEntriesPresenterImpl {
20
- constructor(listPresenter, foldersPresenter, confirmation, modelAccessor, listEntriesUseCase, deleteEntryUseCase, publishEntryUseCase, unpublishEntryUseCase, moveEntryUseCase, updateRevisionDescriptionUseCase, cacheProvider, getDescendantFoldersUseCase){
22
+ constructor(listPresenter, foldersPresenter, confirmation, modelAccessor, listEntriesUseCase, deleteEntryUseCase, publishEntryUseCase, unpublishEntryUseCase, moveEntryUseCase, duplicateEntryUseCase, updateRevisionDescriptionUseCase, cacheProvider, getDescendantFoldersUseCase){
21
23
  this.listPresenter = listPresenter;
22
24
  this.foldersPresenter = foldersPresenter;
23
25
  this.confirmation = confirmation;
@@ -27,6 +29,7 @@ class ContentEntriesPresenterImpl {
27
29
  this.publishEntryUseCase = publishEntryUseCase;
28
30
  this.unpublishEntryUseCase = unpublishEntryUseCase;
29
31
  this.moveEntryUseCase = moveEntryUseCase;
32
+ this.duplicateEntryUseCase = duplicateEntryUseCase;
30
33
  this.updateRevisionDescriptionUseCase = updateRevisionDescriptionUseCase;
31
34
  this.cacheProvider = cacheProvider;
32
35
  this.getDescendantFoldersUseCase = getDescendantFoldersUseCase;
@@ -41,6 +44,7 @@ class ContentEntriesPresenterImpl {
41
44
  publishEntryUseCase: false,
42
45
  unpublishEntryUseCase: false,
43
46
  moveEntryUseCase: false,
47
+ duplicateEntryUseCase: false,
44
48
  updateRevisionDescriptionUseCase: false,
45
49
  cacheProvider: false,
46
50
  getDescendantFoldersUseCase: false,
@@ -153,6 +157,26 @@ class ContentEntriesPresenterImpl {
153
157
  });
154
158
  return true;
155
159
  }
160
+ async duplicateEntry(entry) {
161
+ const model = this.model;
162
+ return this.confirmation.confirm(DUPLICATE_ENTRY_DIALOG, {
163
+ entry
164
+ }, async ()=>{
165
+ try {
166
+ const duplicate = await this.duplicateEntryUseCase.execute({
167
+ model,
168
+ revisionId: entry.id
169
+ });
170
+ return {
171
+ entry: duplicate
172
+ };
173
+ } catch (error) {
174
+ return {
175
+ error: error
176
+ };
177
+ }
178
+ });
179
+ }
156
180
  dispose() {
157
181
  if (this.disposeReaction) {
158
182
  this.disposeReaction();
@@ -172,11 +196,12 @@ const ContentEntriesPresenter_ContentEntriesPresenter = ContentEntriesPresenter.
172
196
  PublishEntryUseCase,
173
197
  UnpublishEntryUseCase,
174
198
  MoveEntryUseCase,
199
+ DuplicateEntryUseCase,
175
200
  UpdateRevisionDescriptionUseCase,
176
201
  ContentEntriesCacheProvider,
177
202
  GetDescendantFoldersUseCase
178
203
  ]
179
204
  });
180
- export { ContentEntriesPresenter_ContentEntriesPresenter as ContentEntriesPresenter, PUBLISH_ENTRY_DIALOG, TRASH_ENTRY_DIALOG, UNPUBLISH_ENTRY_DIALOG };
205
+ export { ContentEntriesPresenter_ContentEntriesPresenter as ContentEntriesPresenter, DUPLICATE_ENTRY_DIALOG, PUBLISH_ENTRY_DIALOG, TRASH_ENTRY_DIALOG, UNPUBLISH_ENTRY_DIALOG };
181
206
 
182
207
  //# sourceMappingURL=ContentEntriesPresenter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/list/ContentEntriesPresenter.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, reaction } from \"mobx\";\nimport type { IReactionDisposer } from \"mobx\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { sortFolders } from \"@webiny/app-aco\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { ListEntriesUseCase } from \"~/features/contentEntry/listEntries/abstractions.js\";\nimport { DeleteEntryUseCase } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { PublishEntryUseCase } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryUseCase } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { MoveEntryUseCase } from \"~/features/contentEntry/moveEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionUseCase } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport {\n ContentEntriesCacheProvider,\n CmsModelContext\n} from \"~/features/contentEntry/abstractions.js\";\nimport {\n ContentEntriesPresenter as Abstraction,\n type IContentEntriesViewModel\n} from \"./abstractions.js\";\nimport { ContentEntriesDataSource } from \"./ContentEntriesDataSource.js\";\n\nexport const TRASH_ENTRY_DIALOG = \"trash-entry\";\nexport const PUBLISH_ENTRY_DIALOG = \"publish-entry\";\nexport const UNPUBLISH_ENTRY_DIALOG = \"unpublish-entry\";\n\nclass ContentEntriesPresenterImpl implements Abstraction.Interface {\n private selectedEntryId: string | null = null;\n private disposeReaction: IReactionDisposer | null = null;\n\n constructor(\n private listPresenter: ListPresenter.Interface<CmsContentEntry>,\n private foldersPresenter: FolderTreePresenter.Interface,\n private confirmation: Confirmation.Interface,\n private modelAccessor: CmsModelContext.Interface,\n private listEntriesUseCase: ListEntriesUseCase.Interface,\n private deleteEntryUseCase: DeleteEntryUseCase.Interface,\n private publishEntryUseCase: PublishEntryUseCase.Interface,\n private unpublishEntryUseCase: UnpublishEntryUseCase.Interface,\n private moveEntryUseCase: MoveEntryUseCase.Interface,\n private updateRevisionDescriptionUseCase: UpdateRevisionDescriptionUseCase.Interface,\n private cacheProvider: ContentEntriesCacheProvider.Interface,\n private getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface\n ) {\n makeAutoObservable<\n ContentEntriesPresenterImpl,\n | \"disposeReaction\"\n | \"confirmation\"\n | \"modelAccessor\"\n | \"listEntriesUseCase\"\n | \"deleteEntryUseCase\"\n | \"publishEntryUseCase\"\n | \"unpublishEntryUseCase\"\n | \"moveEntryUseCase\"\n | \"updateRevisionDescriptionUseCase\"\n | \"cacheProvider\"\n | \"getDescendantFoldersUseCase\"\n >(this, {\n disposeReaction: false,\n confirmation: false,\n modelAccessor: false,\n listEntriesUseCase: false,\n deleteEntryUseCase: false,\n publishEntryUseCase: false,\n unpublishEntryUseCase: false,\n moveEntryUseCase: false,\n updateRevisionDescriptionUseCase: false,\n cacheProvider: false,\n getDescendantFoldersUseCase: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): IContentEntriesViewModel {\n const appliedQuery = this.listPresenter.vm.appliedQuery;\n const hasSearch = !!appliedQuery?.search;\n const hasFilters = Object.keys(this.listPresenter.vm.filters).some(k => k !== \"folderId\");\n const showFolders = !hasSearch && !hasFilters;\n\n const childFolders = showFolders\n ? sortFolders(this.foldersPresenter.vm.childFolders ?? [], appliedQuery?.sort)\n : [];\n\n return {\n model: this.model,\n selectedEntryId: this.selectedEntryId,\n showingEntry: this.selectedEntryId !== null,\n showFolders,\n childFolders\n };\n }\n\n init(config: Abstraction.InitConfig = {}): void {\n const initialFolderId = config.initialFolderId ?? \"root\";\n\n const cache = this.cacheProvider.get(this.model.modelId);\n const dataSource = new ContentEntriesDataSource(\n this.model,\n this.listEntriesUseCase,\n cache,\n this.getDescendantFoldersUseCase,\n config.filterNames\n );\n\n this.listPresenter.init({\n dataSource,\n initialSort: { field: \"savedOn\", direction: \"DESC\" },\n initialFilters: { folderId: initialFolderId },\n initialSearch: config.initialSearch,\n limit: 50,\n itemLabel: { singular: \"entry\", plural: \"entries\" }\n });\n\n if (initialFolderId !== \"root\") {\n this.foldersPresenter.selectFolder(initialFolderId);\n }\n\n this.disposeReaction = reaction(\n () => this.foldersPresenter.vm.currentFolderId,\n folderId => {\n const effectiveFolderId = folderId ?? \"root\";\n this.listPresenter.actions.filter.set(\"folderId\", effectiveFolderId);\n }\n );\n }\n\n get list(): ListPresenter.Interface<CmsContentEntry> {\n return this.listPresenter;\n }\n\n get folders(): FolderTreePresenter.Interface {\n return this.foldersPresenter;\n }\n\n selectEntry(id: string): void {\n this.selectedEntryId = id;\n }\n\n deselectEntry(): void {\n this.selectedEntryId = null;\n }\n\n createEntry(): void {\n this.selectedEntryId = \"new\";\n }\n\n async deleteEntry(id: string): Promise<boolean> {\n const model = this.model;\n const result = await this.confirmation.confirm(TRASH_ENTRY_DIALOG, { entryId: id }, () =>\n this.deleteEntryUseCase.execute({ model, id })\n );\n return result !== false;\n }\n\n async publishEntry(id: string): Promise<boolean> {\n const model = this.model;\n const cache = this.cacheProvider.get(model.modelId);\n const entry = cache.getItem(item => item.id === id);\n if (!entry) {\n return false;\n }\n\n const result = await this.confirmation.confirm<{ revisionDescription: string }>(\n PUBLISH_ENTRY_DIALOG,\n { entry },\n async data => {\n if (data.revisionDescription) {\n await this.updateRevisionDescriptionUseCase.execute({\n model,\n id,\n revisionDescription: data.revisionDescription\n });\n }\n await this.publishEntryUseCase.execute({ model, revisionId: id });\n }\n );\n return result !== false;\n }\n\n async unpublishEntry(id: string): Promise<boolean> {\n const model = this.model;\n const result = await this.confirmation.confirm(\n UNPUBLISH_ENTRY_DIALOG,\n { entryId: id },\n () => this.unpublishEntryUseCase.execute({ model, revisionId: id })\n );\n return result !== false;\n }\n\n async moveEntry(id: string, folderId: string): Promise<boolean> {\n await this.moveEntryUseCase.execute({ model: this.model, id, folderId });\n return true;\n }\n\n dispose(): void {\n if (this.disposeReaction) {\n this.disposeReaction();\n this.disposeReaction = null;\n }\n }\n}\n\nexport const ContentEntriesPresenter = Abstraction.createImplementation({\n implementation: ContentEntriesPresenterImpl,\n dependencies: [\n ListPresenter,\n FolderTreePresenter,\n Confirmation,\n CmsModelContext,\n ListEntriesUseCase,\n DeleteEntryUseCase,\n PublishEntryUseCase,\n UnpublishEntryUseCase,\n MoveEntryUseCase,\n UpdateRevisionDescriptionUseCase,\n ContentEntriesCacheProvider,\n GetDescendantFoldersUseCase\n ]\n});\n"],"names":["TRASH_ENTRY_DIALOG","PUBLISH_ENTRY_DIALOG","UNPUBLISH_ENTRY_DIALOG","ContentEntriesPresenterImpl","listPresenter","foldersPresenter","confirmation","modelAccessor","listEntriesUseCase","deleteEntryUseCase","publishEntryUseCase","unpublishEntryUseCase","moveEntryUseCase","updateRevisionDescriptionUseCase","cacheProvider","getDescendantFoldersUseCase","makeAutoObservable","computed","appliedQuery","hasSearch","hasFilters","Object","k","showFolders","childFolders","sortFolders","config","initialFolderId","cache","dataSource","ContentEntriesDataSource","reaction","folderId","effectiveFolderId","id","model","result","entry","item","data","ContentEntriesPresenter","Abstraction","ListPresenter","FolderTreePresenter","Confirmation","CmsModelContext","ListEntriesUseCase","DeleteEntryUseCase","PublishEntryUseCase","UnpublishEntryUseCase","MoveEntryUseCase","UpdateRevisionDescriptionUseCase","ContentEntriesCacheProvider","GetDescendantFoldersUseCase"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/contentEntries/list/ContentEntriesPresenter.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesPresenter.ts"],"sourcesContent":["import { computed, makeAutoObservable, reaction } from \"mobx\";\nimport type { IReactionDisposer } from \"mobx\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { sortFolders } from \"@webiny/app-aco\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry } from \"~/types.js\";\nimport { ListEntriesUseCase } from \"~/features/contentEntry/listEntries/abstractions.js\";\nimport { DeleteEntryUseCase } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { PublishEntryUseCase } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryUseCase } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { MoveEntryUseCase } from \"~/features/contentEntry/moveEntry/abstractions.js\";\nimport { DuplicateEntryUseCase } from \"~/features/contentEntry/duplicateEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionUseCase } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport {\n ContentEntriesCacheProvider,\n CmsModelContext\n} from \"~/features/contentEntry/abstractions.js\";\nimport {\n ContentEntriesPresenter as Abstraction,\n type IContentEntriesViewModel,\n type IDuplicateEntryResult\n} from \"./abstractions.js\";\nimport { ContentEntriesDataSource } from \"./ContentEntriesDataSource.js\";\n\nexport const TRASH_ENTRY_DIALOG = \"trash-entry\";\nexport const PUBLISH_ENTRY_DIALOG = \"publish-entry\";\nexport const UNPUBLISH_ENTRY_DIALOG = \"unpublish-entry\";\nexport const DUPLICATE_ENTRY_DIALOG = \"duplicate-entry\";\n\nclass ContentEntriesPresenterImpl implements Abstraction.Interface {\n private selectedEntryId: string | null = null;\n private disposeReaction: IReactionDisposer | null = null;\n\n constructor(\n private listPresenter: ListPresenter.Interface<CmsContentEntry>,\n private foldersPresenter: FolderTreePresenter.Interface,\n private confirmation: Confirmation.Interface,\n private modelAccessor: CmsModelContext.Interface,\n private listEntriesUseCase: ListEntriesUseCase.Interface,\n private deleteEntryUseCase: DeleteEntryUseCase.Interface,\n private publishEntryUseCase: PublishEntryUseCase.Interface,\n private unpublishEntryUseCase: UnpublishEntryUseCase.Interface,\n private moveEntryUseCase: MoveEntryUseCase.Interface,\n private duplicateEntryUseCase: DuplicateEntryUseCase.Interface,\n private updateRevisionDescriptionUseCase: UpdateRevisionDescriptionUseCase.Interface,\n private cacheProvider: ContentEntriesCacheProvider.Interface,\n private getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface\n ) {\n makeAutoObservable<\n ContentEntriesPresenterImpl,\n | \"disposeReaction\"\n | \"confirmation\"\n | \"modelAccessor\"\n | \"listEntriesUseCase\"\n | \"deleteEntryUseCase\"\n | \"publishEntryUseCase\"\n | \"unpublishEntryUseCase\"\n | \"moveEntryUseCase\"\n | \"duplicateEntryUseCase\"\n | \"updateRevisionDescriptionUseCase\"\n | \"cacheProvider\"\n | \"getDescendantFoldersUseCase\"\n >(this, {\n disposeReaction: false,\n confirmation: false,\n modelAccessor: false,\n listEntriesUseCase: false,\n deleteEntryUseCase: false,\n publishEntryUseCase: false,\n unpublishEntryUseCase: false,\n moveEntryUseCase: false,\n duplicateEntryUseCase: false,\n updateRevisionDescriptionUseCase: false,\n cacheProvider: false,\n getDescendantFoldersUseCase: false,\n vm: computed\n });\n }\n\n private get model() {\n return this.modelAccessor.getModel();\n }\n\n get vm(): IContentEntriesViewModel {\n const appliedQuery = this.listPresenter.vm.appliedQuery;\n const hasSearch = !!appliedQuery?.search;\n const hasFilters = Object.keys(this.listPresenter.vm.filters).some(k => k !== \"folderId\");\n const showFolders = !hasSearch && !hasFilters;\n\n const childFolders = showFolders\n ? sortFolders(this.foldersPresenter.vm.childFolders ?? [], appliedQuery?.sort)\n : [];\n\n return {\n model: this.model,\n selectedEntryId: this.selectedEntryId,\n showingEntry: this.selectedEntryId !== null,\n showFolders,\n childFolders\n };\n }\n\n init(config: Abstraction.InitConfig = {}): void {\n const initialFolderId = config.initialFolderId ?? \"root\";\n\n const cache = this.cacheProvider.get(this.model.modelId);\n const dataSource = new ContentEntriesDataSource(\n this.model,\n this.listEntriesUseCase,\n cache,\n this.getDescendantFoldersUseCase,\n config.filterNames\n );\n\n this.listPresenter.init({\n dataSource,\n initialSort: { field: \"savedOn\", direction: \"DESC\" },\n initialFilters: { folderId: initialFolderId },\n initialSearch: config.initialSearch,\n limit: 50,\n itemLabel: { singular: \"entry\", plural: \"entries\" }\n });\n\n if (initialFolderId !== \"root\") {\n this.foldersPresenter.selectFolder(initialFolderId);\n }\n\n this.disposeReaction = reaction(\n () => this.foldersPresenter.vm.currentFolderId,\n folderId => {\n const effectiveFolderId = folderId ?? \"root\";\n this.listPresenter.actions.filter.set(\"folderId\", effectiveFolderId);\n }\n );\n }\n\n get list(): ListPresenter.Interface<CmsContentEntry> {\n return this.listPresenter;\n }\n\n get folders(): FolderTreePresenter.Interface {\n return this.foldersPresenter;\n }\n\n selectEntry(id: string): void {\n this.selectedEntryId = id;\n }\n\n deselectEntry(): void {\n this.selectedEntryId = null;\n }\n\n createEntry(): void {\n this.selectedEntryId = \"new\";\n }\n\n async deleteEntry(id: string): Promise<boolean> {\n const model = this.model;\n const result = await this.confirmation.confirm(TRASH_ENTRY_DIALOG, { entryId: id }, () =>\n this.deleteEntryUseCase.execute({ model, id })\n );\n return result !== false;\n }\n\n async publishEntry(id: string): Promise<boolean> {\n const model = this.model;\n const cache = this.cacheProvider.get(model.modelId);\n const entry = cache.getItem(item => item.id === id);\n if (!entry) {\n return false;\n }\n\n const result = await this.confirmation.confirm<{ revisionDescription: string }>(\n PUBLISH_ENTRY_DIALOG,\n { entry },\n async data => {\n if (data.revisionDescription) {\n await this.updateRevisionDescriptionUseCase.execute({\n model,\n id,\n revisionDescription: data.revisionDescription\n });\n }\n await this.publishEntryUseCase.execute({ model, revisionId: id });\n }\n );\n return result !== false;\n }\n\n async unpublishEntry(id: string): Promise<boolean> {\n const model = this.model;\n const result = await this.confirmation.confirm(\n UNPUBLISH_ENTRY_DIALOG,\n { entryId: id },\n () => this.unpublishEntryUseCase.execute({ model, revisionId: id })\n );\n return result !== false;\n }\n\n async moveEntry(id: string, folderId: string): Promise<boolean> {\n await this.moveEntryUseCase.execute({ model: this.model, id, folderId });\n return true;\n }\n\n async duplicateEntry(entry: CmsContentEntry): Promise<IDuplicateEntryResult | false> {\n const model = this.model;\n return this.confirmation.confirm(\n DUPLICATE_ENTRY_DIALOG,\n { entry },\n async (): Promise<IDuplicateEntryResult> => {\n try {\n const duplicate = await this.duplicateEntryUseCase.execute({\n model,\n revisionId: entry.id\n });\n return { entry: duplicate };\n } catch (error) {\n return { error: error as Error };\n }\n }\n );\n }\n\n dispose(): void {\n if (this.disposeReaction) {\n this.disposeReaction();\n this.disposeReaction = null;\n }\n }\n}\n\nexport const ContentEntriesPresenter = Abstraction.createImplementation({\n implementation: ContentEntriesPresenterImpl,\n dependencies: [\n ListPresenter,\n FolderTreePresenter,\n Confirmation,\n CmsModelContext,\n ListEntriesUseCase,\n DeleteEntryUseCase,\n PublishEntryUseCase,\n UnpublishEntryUseCase,\n MoveEntryUseCase,\n DuplicateEntryUseCase,\n UpdateRevisionDescriptionUseCase,\n ContentEntriesCacheProvider,\n GetDescendantFoldersUseCase\n ]\n});\n"],"names":["TRASH_ENTRY_DIALOG","PUBLISH_ENTRY_DIALOG","UNPUBLISH_ENTRY_DIALOG","DUPLICATE_ENTRY_DIALOG","ContentEntriesPresenterImpl","listPresenter","foldersPresenter","confirmation","modelAccessor","listEntriesUseCase","deleteEntryUseCase","publishEntryUseCase","unpublishEntryUseCase","moveEntryUseCase","duplicateEntryUseCase","updateRevisionDescriptionUseCase","cacheProvider","getDescendantFoldersUseCase","makeAutoObservable","computed","appliedQuery","hasSearch","hasFilters","Object","k","showFolders","childFolders","sortFolders","config","initialFolderId","cache","dataSource","ContentEntriesDataSource","reaction","folderId","effectiveFolderId","id","model","result","entry","item","data","duplicate","error","ContentEntriesPresenter","Abstraction","ListPresenter","FolderTreePresenter","Confirmation","CmsModelContext","ListEntriesUseCase","DeleteEntryUseCase","PublishEntryUseCase","UnpublishEntryUseCase","MoveEntryUseCase","DuplicateEntryUseCase","UpdateRevisionDescriptionUseCase","ContentEntriesCacheProvider","GetDescendantFoldersUseCase"],"mappings":";;;;;;;;;;;;;;;;AA0BO,MAAMA,qBAAqB;AAC3B,MAAMC,uBAAuB;AAC7B,MAAMC,yBAAyB;AAC/B,MAAMC,yBAAyB;AAEtC,MAAMC;IAIF,YACYC,aAAuD,EACvDC,gBAA+C,EAC/CC,YAAoC,EACpCC,aAAwC,EACxCC,kBAAgD,EAChDC,kBAAgD,EAChDC,mBAAkD,EAClDC,qBAAsD,EACtDC,gBAA4C,EAC5CC,qBAAsD,EACtDC,gCAA4E,EAC5EC,aAAoD,EACpDC,2BAAkE,CAC5E;aAbUZ,aAAa,GAAbA;aACAC,gBAAgB,GAAhBA;aACAC,YAAY,GAAZA;aACAC,aAAa,GAAbA;aACAC,kBAAkB,GAAlBA;aACAC,kBAAkB,GAAlBA;aACAC,mBAAmB,GAAnBA;aACAC,qBAAqB,GAArBA;aACAC,gBAAgB,GAAhBA;aACAC,qBAAqB,GAArBA;aACAC,gCAAgC,GAAhCA;aACAC,aAAa,GAAbA;aACAC,2BAA2B,GAA3BA;aAhBJ,eAAe,GAAkB;aACjC,eAAe,GAA6B;QAiBhDC,mBAcE,IAAI,EAAE;YACJ,iBAAiB;YACjB,cAAc;YACd,eAAe;YACf,oBAAoB;YACpB,oBAAoB;YACpB,qBAAqB;YACrB,uBAAuB;YACvB,kBAAkB;YAClB,uBAAuB;YACvB,kCAAkC;YAClC,eAAe;YACf,6BAA6B;YAC7B,IAAIC;QACR;IACJ;IAEA,IAAY,QAAQ;QAChB,OAAO,IAAI,CAAC,aAAa,CAAC,QAAQ;IACtC;IAEA,IAAI,KAA+B;QAC/B,MAAMC,eAAe,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,YAAY;QACvD,MAAMC,YAAY,CAAC,CAACD,cAAc;QAClC,MAAME,aAAaC,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAACC,CAAAA,IAAKA,AAAM,eAANA;QACxE,MAAMC,cAAc,CAACJ,aAAa,CAACC;QAEnC,MAAMI,eAAeD,cACfE,YAAY,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,YAAY,IAAI,EAAE,EAAEP,cAAc,QACvE,EAAE;QAER,OAAO;YACH,OAAO,IAAI,CAAC,KAAK;YACjB,iBAAiB,IAAI,CAAC,eAAe;YACrC,cAAc,AAAyB,SAAzB,IAAI,CAAC,eAAe;YAClCK;YACAC;QACJ;IACJ;IAEA,KAAKE,SAAiC,CAAC,CAAC,EAAQ;QAC5C,MAAMC,kBAAkBD,OAAO,eAAe,IAAI;QAElD,MAAME,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO;QACvD,MAAMC,aAAa,IAAIC,yBACnB,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,kBAAkB,EACvBF,OACA,IAAI,CAAC,2BAA2B,EAChCF,OAAO,WAAW;QAGtB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YACpBG;YACA,aAAa;gBAAE,OAAO;gBAAW,WAAW;YAAO;YACnD,gBAAgB;gBAAE,UAAUF;YAAgB;YAC5C,eAAeD,OAAO,aAAa;YACnC,OAAO;YACP,WAAW;gBAAE,UAAU;gBAAS,QAAQ;YAAU;QACtD;QAEA,IAAIC,AAAoB,WAApBA,iBACA,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAACA;QAGvC,IAAI,CAAC,eAAe,GAAGI,SACnB,IAAM,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,eAAe,EAC9CC,CAAAA;YACI,MAAMC,oBAAoBD,YAAY;YACtC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,YAAYC;QACtD;IAER;IAEA,IAAI,OAAiD;QACjD,OAAO,IAAI,CAAC,aAAa;IAC7B;IAEA,IAAI,UAAyC;QACzC,OAAO,IAAI,CAAC,gBAAgB;IAChC;IAEA,YAAYC,EAAU,EAAQ;QAC1B,IAAI,CAAC,eAAe,GAAGA;IAC3B;IAEA,gBAAsB;QAClB,IAAI,CAAC,eAAe,GAAG;IAC3B;IAEA,cAAoB;QAChB,IAAI,CAAC,eAAe,GAAG;IAC3B;IAEA,MAAM,YAAYA,EAAU,EAAoB;QAC5C,MAAMC,QAAQ,IAAI,CAAC,KAAK;QACxB,MAAMC,SAAS,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAACtC,oBAAoB;YAAE,SAASoC;QAAG,GAAG,IAChF,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC;gBAAEC;gBAAOD;YAAG;QAEhD,OAAOE,AAAW,UAAXA;IACX;IAEA,MAAM,aAAaF,EAAU,EAAoB;QAC7C,MAAMC,QAAQ,IAAI,CAAC,KAAK;QACxB,MAAMP,QAAQ,IAAI,CAAC,aAAa,CAAC,GAAG,CAACO,MAAM,OAAO;QAClD,MAAME,QAAQT,MAAM,OAAO,CAACU,CAAAA,OAAQA,KAAK,EAAE,KAAKJ;QAChD,IAAI,CAACG,OACD,OAAO;QAGX,MAAMD,SAAS,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAC1CrC,sBACA;YAAEsC;QAAM,GACR,OAAME;YACF,IAAIA,KAAK,mBAAmB,EACxB,MAAM,IAAI,CAAC,gCAAgC,CAAC,OAAO,CAAC;gBAChDJ;gBACAD;gBACA,qBAAqBK,KAAK,mBAAmB;YACjD;YAEJ,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC;gBAAEJ;gBAAO,YAAYD;YAAG;QACnE;QAEJ,OAAOE,AAAW,UAAXA;IACX;IAEA,MAAM,eAAeF,EAAU,EAAoB;QAC/C,MAAMC,QAAQ,IAAI,CAAC,KAAK;QACxB,MAAMC,SAAS,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,CAC1CpC,wBACA;YAAE,SAASkC;QAAG,GACd,IAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;gBAAEC;gBAAO,YAAYD;YAAG;QAErE,OAAOE,AAAW,UAAXA;IACX;IAEA,MAAM,UAAUF,EAAU,EAAEF,QAAgB,EAAoB;QAC5D,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAAE,OAAO,IAAI,CAAC,KAAK;YAAEE;YAAIF;QAAS;QACtE,OAAO;IACX;IAEA,MAAM,eAAeK,KAAsB,EAA0C;QACjF,MAAMF,QAAQ,IAAI,CAAC,KAAK;QACxB,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,CAC5BlC,wBACA;YAAEoC;QAAM,GACR;YACI,IAAI;gBACA,MAAMG,YAAY,MAAM,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC;oBACvDL;oBACA,YAAYE,MAAM,EAAE;gBACxB;gBACA,OAAO;oBAAE,OAAOG;gBAAU;YAC9B,EAAE,OAAOC,OAAO;gBACZ,OAAO;oBAAE,OAAOA;gBAAe;YACnC;QACJ;IAER;IAEA,UAAgB;QACZ,IAAI,IAAI,CAAC,eAAe,EAAE;YACtB,IAAI,CAAC,eAAe;YACpB,IAAI,CAAC,eAAe,GAAG;QAC3B;IACJ;AACJ;AAEO,MAAMC,kDAA0BC,wBAAAA,oBAAgC,CAAC;IACpE,gBAAgBzC;IAChB,cAAc;QACV0C;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}
@@ -13,12 +13,14 @@ import { DeleteEntryFeature } from "../../../features/contentEntry/deleteEntry/f
13
13
  import { PublishEntryFeature } from "../../../features/contentEntry/publishEntry/feature.js";
14
14
  import { UnpublishEntryFeature } from "../../../features/contentEntry/unpublishEntry/feature.js";
15
15
  import { MoveEntryFeature } from "../../../features/contentEntry/moveEntry/feature.js";
16
+ import { DuplicateEntryFeature } from "../../../features/contentEntry/duplicateEntry/feature.js";
16
17
  import { UpdateRevisionDescriptionFeature } from "../../../features/contentEntry/updateRevisionDescription/feature.js";
17
18
  import { ListEntriesGateway } from "../../../features/contentEntry/listEntries/abstractions.js";
18
19
  import { DeleteEntryGateway } from "../../../features/contentEntry/deleteEntry/abstractions.js";
19
- import { PublishEntryGateway } from "../../../features/contentEntry/publishEntry/abstractions.js";
20
+ import { PublishEntryGateway, PublishEntryUseCase } from "../../../features/contentEntry/publishEntry/abstractions.js";
20
21
  import { UnpublishEntryGateway } from "../../../features/contentEntry/unpublishEntry/abstractions.js";
21
22
  import { MoveEntryGateway } from "../../../features/contentEntry/moveEntry/abstractions.js";
23
+ import { DuplicateEntryGateway } from "../../../features/contentEntry/duplicateEntry/abstractions.js";
22
24
  import { UpdateRevisionDescriptionGateway } from "../../../features/contentEntry/updateRevisionDescription/abstractions.js";
23
25
  import { EventPublisher } from "@webiny/app/features/eventPublisher/index.js";
24
26
  import { ContentEntriesPresenter } from "./abstractions.js";
@@ -112,7 +114,7 @@ function setup() {
112
114
  container.registerInstance(FolderTreePresenter, foldersPresenter);
113
115
  container.registerInstance(Confirmation, {
114
116
  confirm: vi.fn(async (_name, _params, execute)=>{
115
- if (execute) await execute(void 0);
117
+ if (execute) return await execute(void 0);
116
118
  return true;
117
119
  })
118
120
  });
@@ -131,6 +133,7 @@ function setup() {
131
133
  PublishEntryFeature.register(container);
132
134
  UnpublishEntryFeature.register(container);
133
135
  MoveEntryFeature.register(container);
136
+ DuplicateEntryFeature.register(container);
134
137
  UpdateRevisionDescriptionFeature.register(container);
135
138
  const listEntriesGateway = {
136
139
  execute: vi.fn()
@@ -144,9 +147,14 @@ function setup() {
144
147
  container.registerInstance(ListEntriesGateway, listEntriesGateway);
145
148
  container.registerInstance(MoveEntryGateway, moveEntryGateway);
146
149
  container.registerInstance(DeleteEntryGateway, deleteEntryGateway);
147
- container.registerInstance(PublishEntryGateway, {
150
+ const duplicateEntryGateway = {
148
151
  execute: vi.fn()
149
- });
152
+ };
153
+ container.registerInstance(DuplicateEntryGateway, duplicateEntryGateway);
154
+ const publishEntryGateway = {
155
+ execute: vi.fn()
156
+ };
157
+ container.registerInstance(PublishEntryGateway, publishEntryGateway);
150
158
  container.registerInstance(UnpublishEntryGateway, {
151
159
  execute: vi.fn()
152
160
  });
@@ -160,8 +168,11 @@ function setup() {
160
168
  listEntriesGateway,
161
169
  moveEntryGateway,
162
170
  deleteEntryGateway,
171
+ duplicateEntryGateway,
163
172
  getDescendantFolders,
164
- foldersPresenter
173
+ foldersPresenter,
174
+ publishEntryGateway,
175
+ container
165
176
  };
166
177
  }
167
178
  async function initPresenter(t, gatewayResponse) {
@@ -514,6 +525,55 @@ describe("ContentEntriesPresenter", ()=>{
514
525
  });
515
526
  });
516
527
  });
528
+ describe("duplicate entry", ()=>{
529
+ it("should add the duplicated entry to the current view", async ()=>{
530
+ const entries = [
531
+ createEntry("entry-2", "root", {
532
+ savedOn: "2024-01-02T00:00:00.000Z"
533
+ }),
534
+ createEntry("entry-1", "root", {
535
+ savedOn: "2024-01-01T00:00:00.000Z"
536
+ })
537
+ ];
538
+ await initPresenter(t, {
539
+ data: entries
540
+ });
541
+ const duplicate = createEntry("entry-3", "root", {
542
+ savedOn: "2024-01-03T00:00:00.000Z"
543
+ });
544
+ t.duplicateEntryGateway.execute.mockResolvedValueOnce(duplicate);
545
+ const result = await t.presenter.duplicateEntry(entries[1]);
546
+ expect(result).toEqual({
547
+ entry: duplicate
548
+ });
549
+ expect(t.duplicateEntryGateway.execute).toHaveBeenCalledWith({
550
+ model: MODEL,
551
+ revisionId: "entry-1#0001"
552
+ });
553
+ await vi.waitFor(()=>{
554
+ expect(t.presenter.list.vm.rows.map((r)=>r.entryId)).toEqual([
555
+ "entry-3",
556
+ "entry-2",
557
+ "entry-1"
558
+ ]);
559
+ });
560
+ });
561
+ it("should return the error when duplication fails", async ()=>{
562
+ const entries = [
563
+ createEntry("entry-1", "root")
564
+ ];
565
+ await initPresenter(t, {
566
+ data: entries
567
+ });
568
+ const error = new Error("Not allowed.");
569
+ t.duplicateEntryGateway.execute.mockRejectedValueOnce(error);
570
+ const result = await t.presenter.duplicateEntry(entries[0]);
571
+ expect(result).toEqual({
572
+ error
573
+ });
574
+ expect(t.presenter.list.vm.rows).toHaveLength(1);
575
+ });
576
+ });
517
577
  describe("delete entry", ()=>{
518
578
  it("should remove entry from current view after delete", async ()=>{
519
579
  const entries = [
@@ -582,6 +642,71 @@ describe("ContentEntriesPresenter", ()=>{
582
642
  });
583
643
  });
584
644
  });
645
+ describe("publish entry", ()=>{
646
+ const entries = [
647
+ createEntry("entry-3", "root", {
648
+ savedOn: "2024-01-03T00:00:00.000Z"
649
+ }),
650
+ createEntry("entry-2", "root", {
651
+ savedOn: "2024-01-02T00:00:00.000Z"
652
+ }),
653
+ createEntry("entry-1", "root", {
654
+ savedOn: "2024-01-01T00:00:00.000Z"
655
+ })
656
+ ];
657
+ const publish = async (entry)=>{
658
+ t.publishEntryGateway.execute.mockResolvedValueOnce({
659
+ ...entry,
660
+ meta: {
661
+ ...entry.meta,
662
+ status: "published",
663
+ locked: true
664
+ }
665
+ });
666
+ await t.container.resolve(PublishEntryUseCase).execute({
667
+ model: MODEL,
668
+ revisionId: entry.id
669
+ });
670
+ };
671
+ it("should keep a published entry in its position", async ()=>{
672
+ await initPresenter(t, {
673
+ data: entries
674
+ });
675
+ await publish(entries[1]);
676
+ const rows = t.presenter.list.vm.rows;
677
+ expect(rows.map((r)=>r.entryId)).toEqual([
678
+ "entry-3",
679
+ "entry-2",
680
+ "entry-1"
681
+ ]);
682
+ expect(rows[1].meta.status).toBe("published");
683
+ });
684
+ it("should keep a published entry in its position when sorted ascending", async ()=>{
685
+ await initPresenter(t, {
686
+ data: entries
687
+ });
688
+ t.listEntriesGateway.execute.mockResolvedValueOnce({
689
+ data: [
690
+ ...entries
691
+ ].reverse(),
692
+ meta: {
693
+ cursor: null,
694
+ hasMoreItems: false,
695
+ totalCount: entries.length
696
+ }
697
+ });
698
+ t.presenter.list.actions.sort.set("savedOn", "ASC");
699
+ await vi.waitFor(()=>{
700
+ expect(t.presenter.list.vm.appliedQuery?.sort?.direction).toBe("ASC");
701
+ });
702
+ await publish(entries[1]);
703
+ expect(t.presenter.list.vm.rows.map((r)=>r.entryId)).toEqual([
704
+ "entry-1",
705
+ "entry-2",
706
+ "entry-3"
707
+ ]);
708
+ });
709
+ });
585
710
  });
586
711
 
587
712
  //# sourceMappingURL=ContentEntriesPresenter.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/contentEntries/list/ContentEntriesPresenter.test.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesPresenter.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { makeAutoObservable } from \"mobx\";\nimport { ListPresenterFeature } from \"@webiny/app-admin/presentation/listPresenter/index.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport { ContentEntriesCacheProvider } from \"~/features/contentEntry/ContentEntriesCacheProvider.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport { CmsModelContext as CmsModelContextImpl } from \"~/features/contentEntry/CmsModelContext.js\";\nimport { ListEntriesFeature } from \"~/features/contentEntry/listEntries/feature.js\";\nimport { DeleteEntryFeature } from \"~/features/contentEntry/deleteEntry/feature.js\";\nimport { PublishEntryFeature } from \"~/features/contentEntry/publishEntry/feature.js\";\nimport { UnpublishEntryFeature } from \"~/features/contentEntry/unpublishEntry/feature.js\";\nimport { MoveEntryFeature } from \"~/features/contentEntry/moveEntry/feature.js\";\nimport { UpdateRevisionDescriptionFeature } from \"~/features/contentEntry/updateRevisionDescription/feature.js\";\nimport { ListEntriesGateway } from \"~/features/contentEntry/listEntries/abstractions.js\";\nimport { DeleteEntryGateway } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport { PublishEntryGateway } from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryGateway } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { MoveEntryGateway } from \"~/features/contentEntry/moveEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionGateway } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { EventPublisher } from \"@webiny/app/features/eventPublisher/index.js\";\nimport { ContentEntriesPresenter as Abstraction } from \"./abstractions.js\";\nimport { ContentEntriesPresenter } from \"./ContentEntriesPresenter.js\";\nimport type { IContentEntriesPresenter } from \"./abstractions.js\";\nimport type {\n IFolderTreeViewModel,\n IFolderOperationState\n} from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\n\nconst MODEL: CmsModel = {\n modelId: \"testModel\",\n name: \"Test Model\",\n singularApiName: \"TestModel\",\n pluralApiName: \"TestModels\",\n fields: [],\n layout: [],\n group: \"group-1\",\n titleFieldId: \"title\",\n descriptionFieldId: null,\n imageFieldId: null,\n tags: [],\n savedOn: \"\"\n} as unknown as CmsModel;\n\nfunction createEntry(\n entryId: string,\n folderId: string,\n overrides: Partial<CmsContentEntry> = {}\n): CmsContentEntry {\n return {\n id: `${entryId}#0001`,\n entryId,\n meta: {\n title: entryId,\n status: \"draft\",\n version: 1,\n locked: false\n },\n wbyAco_location: { folderId },\n values: {},\n createdBy: { id: \"user-1\", displayName: \"Test\", type: \"admin\" },\n createdOn: \"2024-01-01T00:00:00Z\",\n savedOn: \"2024-01-01T00:00:00Z\",\n ...overrides\n } as unknown as CmsContentEntry;\n}\n\nclass MockFolderTreePresenter implements FolderTreePresenter.Interface {\n private _currentFolderId: string | null = null;\n\n constructor() {\n makeAutoObservable(this);\n }\n\n get vm(): IFolderTreeViewModel {\n return {\n folders: [],\n tree: [],\n currentFolderId: this._currentFolderId,\n currentFolder: null,\n isRootFolder: this._currentFolderId === null,\n currentFolderTitle: \"Home\",\n childFolders: [],\n loading: false,\n loadingNodeIds: [],\n operation: { active: false, mode: null } as IFolderOperationState\n };\n }\n\n selectFolder(folderId: string | null): void {\n this._currentFolderId = folderId;\n }\n\n createFolder(): void {}\n editFolder(): void {}\n async deleteFolder(): Promise<void> {}\n async moveFolder(): Promise<void> {}\n async loadChildFolders(): Promise<void> {}\n canManageStructure(): boolean {\n return true;\n }\n getAncestorIds(): string[] {\n return [];\n }\n async submitOperation(): Promise<boolean> {\n return true;\n }\n cancelOperation(): void {}\n onFolderChange(): () => void {\n return () => {};\n }\n}\n\ninterface TestSetup {\n presenter: IContentEntriesPresenter;\n listEntriesGateway: { execute: ReturnType<typeof vi.fn> };\n moveEntryGateway: { execute: ReturnType<typeof vi.fn> };\n deleteEntryGateway: { execute: ReturnType<typeof vi.fn> };\n getDescendantFolders: ReturnType<typeof vi.fn>;\n foldersPresenter: MockFolderTreePresenter;\n}\n\nfunction setup(): TestSetup {\n const container = new Container();\n\n ListPresenterFeature.register(container);\n\n const foldersPresenter = new MockFolderTreePresenter();\n container.registerInstance(FolderTreePresenter, foldersPresenter);\n\n container.registerInstance(Confirmation, {\n confirm: vi.fn(async (_name, _params, execute) => {\n if (execute) {\n await execute(undefined);\n }\n return true;\n })\n } as unknown as Confirmation.Interface);\n\n const getDescendantFolders = vi.fn().mockReturnValue([]);\n container.registerInstance(GetDescendantFoldersUseCase, {\n execute: getDescendantFolders\n });\n\n container.registerInstance(EventPublisher, { publish: vi.fn() });\n container.register(ContentEntriesCacheProvider).inSingletonScope();\n container.register(CmsModelContextImpl).inSingletonScope();\n container.resolve(CmsModelContext).setModel(MODEL);\n\n ListEntriesFeature.register(container);\n DeleteEntryFeature.register(container);\n PublishEntryFeature.register(container);\n UnpublishEntryFeature.register(container);\n MoveEntryFeature.register(container);\n UpdateRevisionDescriptionFeature.register(container);\n\n const listEntriesGateway = { execute: vi.fn() };\n const moveEntryGateway = { execute: vi.fn() };\n const deleteEntryGateway = { execute: vi.fn() };\n\n container.registerInstance(ListEntriesGateway, listEntriesGateway);\n container.registerInstance(MoveEntryGateway, moveEntryGateway);\n container.registerInstance(DeleteEntryGateway, deleteEntryGateway);\n container.registerInstance(PublishEntryGateway, { execute: vi.fn() });\n container.registerInstance(UnpublishEntryGateway, { execute: vi.fn() });\n container.registerInstance(UpdateRevisionDescriptionGateway, { execute: vi.fn() });\n\n container.register(ContentEntriesPresenter).inSingletonScope();\n const presenter = container.resolve(Abstraction);\n\n return {\n presenter,\n listEntriesGateway,\n moveEntryGateway,\n deleteEntryGateway,\n getDescendantFolders,\n foldersPresenter\n };\n}\n\nasync function initPresenter(\n t: TestSetup,\n gatewayResponse: { data: CmsContentEntry[]; meta?: object }\n) {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: gatewayResponse.data,\n meta: gatewayResponse.meta ?? {\n cursor: null,\n hasMoreItems: false,\n totalCount: gatewayResponse.data.length\n }\n });\n\n t.presenter.init();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n}\n\ndescribe(\"ContentEntriesPresenter\", () => {\n let t: TestSetup;\n\n beforeEach(() => {\n t = setup();\n });\n\n describe(\"initial load\", () => {\n it(\"should show root entries after setModel\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n\n await initPresenter(t, { data: entries });\n\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"entry-1\", \"entry-2\"]);\n });\n\n it(\"should send folderId=root in the gateway query\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.listEntriesGateway.execute).toHaveBeenCalledWith(\n expect.objectContaining({\n where: expect.objectContaining({\n wbyAco_location: { folderId: \"root\" }\n })\n })\n );\n });\n\n it(\"should set model after init\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n });\n\n describe(\"folder navigation\", () => {\n it(\"should filter to folder entries when navigating to a subfolder\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"folder-2\", \"folder-a\")\n ];\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"folder-1\", \"folder-2\"]);\n });\n\n it(\"should show only root entries when navigating back to root\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"folder-1\");\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n\n it(\"should not leak subfolder entries into root view\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"folder-1\", \"folder-a\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n });\n\n describe(\"search\", () => {\n it(\"should show only search results from API\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const searchResults = [createEntry(\"entry-1\", \"root\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-1\");\n });\n\n it(\"should include entries from subfolders when searching from root\", async () => {\n await initPresenter(t, { data: [] });\n\n const searchResults = [\n createEntry(\"root-1\", \"root\"),\n createEntry(\"folder-1\", \"folder-a\")\n ];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n\n it(\"should search with folderId_in containing all descendant folders when in a subfolder\", async () => {\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.init({ initialFolderId: \"folder-a\" });\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n\n t.getDescendantFolders.mockReturnValue([\n { id: \"folder-a\" },\n { id: \"folder-a-1\" },\n { id: \"folder-a-2\" }\n ]);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"sub-1\", \"folder-a-1\"),\n createEntry(\"sub-2\", \"folder-a-2\")\n ],\n meta: { cursor: null, hasMoreItems: false, totalCount: 3 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(3);\n });\n\n expect(t.getDescendantFolders).toHaveBeenCalledWith(\"folder-a\");\n\n const searchCall = t.listEntriesGateway.execute.mock.calls.at(-1) ?? [];\n expect(searchCall[0].where).toEqual(\n expect.objectContaining({\n wbyAco_location: {\n folderId_in: [\"folder-a\", \"folder-a-1\", \"folder-a-2\"]\n }\n })\n );\n });\n\n it(\"should restore folder view when clearing search\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"entry-1\", \"root\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.clear();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n });\n\n describe(\"status filter\", () => {\n it(\"should filter by status locally\", async () => {\n const entries = [\n createEntry(\"draft-1\", \"root\", {\n meta: {\n title: \"draft-1\",\n status: \"draft\",\n version: 1,\n locked: false\n }\n }),\n createEntry(\"published-1\", \"root\", {\n meta: {\n title: \"published-1\",\n status: \"published\",\n version: 1,\n locked: false\n }\n })\n ];\n await initPresenter(t, { data: entries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: entries.filter(e => (e.meta as { status: string }).status === \"published\"),\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.filter.set(\"status\", \"published\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"published-1\");\n });\n });\n });\n\n describe(\"move entry\", () => {\n it(\"should remove entry from current view after move\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.moveEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.moveEntry(\"entry-1#0001\", \"folder-b\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"delete entry\", () => {\n it(\"should remove entry from current view after delete\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.deleteEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.deleteEntry(\"entry-1#0001\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"vm\", () => {\n it(\"should set model on init\", () => {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n t.presenter.init();\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n\n it(\"should track selected entry\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showingEntry).toBe(false);\n\n t.presenter.selectEntry(\"some-id\");\n expect(t.presenter.vm.selectedEntryId).toBe(\"some-id\");\n expect(t.presenter.vm.showingEntry).toBe(true);\n\n t.presenter.deselectEntry();\n expect(t.presenter.vm.selectedEntryId).toBeNull();\n expect(t.presenter.vm.showingEntry).toBe(false);\n });\n\n it(\"should set selectedEntryId to 'new' on createEntry\", async () => {\n await initPresenter(t, { data: [] });\n\n t.presenter.createEntry();\n expect(t.presenter.vm.selectedEntryId).toBe(\"new\");\n });\n\n it(\"should show folders when no search or non-folder filters active\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showFolders).toBe(true);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.vm.showFolders).toBe(false);\n });\n });\n });\n});\n"],"names":["MODEL","createEntry","entryId","folderId","overrides","MockFolderTreePresenter","makeAutoObservable","setup","container","Container","ListPresenterFeature","foldersPresenter","FolderTreePresenter","Confirmation","vi","_name","_params","execute","undefined","getDescendantFolders","GetDescendantFoldersUseCase","EventPublisher","ContentEntriesCacheProvider","CmsModelContextImpl","CmsModelContext","ListEntriesFeature","DeleteEntryFeature","PublishEntryFeature","UnpublishEntryFeature","MoveEntryFeature","UpdateRevisionDescriptionFeature","listEntriesGateway","moveEntryGateway","deleteEntryGateway","ListEntriesGateway","MoveEntryGateway","DeleteEntryGateway","PublishEntryGateway","UnpublishEntryGateway","UpdateRevisionDescriptionGateway","ContentEntriesPresenter","presenter","Abstraction","initPresenter","t","gatewayResponse","expect","describe","beforeEach","it","entries","r","rootEntries","folderEntries","searchResults","searchCall","e"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/contentEntries/list/ContentEntriesPresenter.test.js","sources":["../../../../src/presentation/contentEntries/list/ContentEntriesPresenter.test.ts"],"sourcesContent":["/**\n * @vitest-environment jsdom\n */\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { Container } from \"@webiny/di\";\nimport { makeAutoObservable } from \"mobx\";\nimport { ListPresenterFeature } from \"@webiny/app-admin/presentation/listPresenter/index.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { Confirmation } from \"@webiny/app-admin/features/confirmation/abstractions.js\";\nimport type { CmsContentEntry, CmsModel } from \"~/types.js\";\nimport { ContentEntriesCacheProvider } from \"~/features/contentEntry/ContentEntriesCacheProvider.js\";\nimport { CmsModelContext } from \"~/features/contentEntry/abstractions.js\";\nimport { CmsModelContext as CmsModelContextImpl } from \"~/features/contentEntry/CmsModelContext.js\";\nimport { ListEntriesFeature } from \"~/features/contentEntry/listEntries/feature.js\";\nimport { DeleteEntryFeature } from \"~/features/contentEntry/deleteEntry/feature.js\";\nimport { PublishEntryFeature } from \"~/features/contentEntry/publishEntry/feature.js\";\nimport { UnpublishEntryFeature } from \"~/features/contentEntry/unpublishEntry/feature.js\";\nimport { MoveEntryFeature } from \"~/features/contentEntry/moveEntry/feature.js\";\nimport { DuplicateEntryFeature } from \"~/features/contentEntry/duplicateEntry/feature.js\";\nimport { UpdateRevisionDescriptionFeature } from \"~/features/contentEntry/updateRevisionDescription/feature.js\";\nimport { ListEntriesGateway } from \"~/features/contentEntry/listEntries/abstractions.js\";\nimport { DeleteEntryGateway } from \"~/features/contentEntry/deleteEntry/abstractions.js\";\nimport {\n PublishEntryGateway,\n PublishEntryUseCase\n} from \"~/features/contentEntry/publishEntry/abstractions.js\";\nimport { UnpublishEntryGateway } from \"~/features/contentEntry/unpublishEntry/abstractions.js\";\nimport { MoveEntryGateway } from \"~/features/contentEntry/moveEntry/abstractions.js\";\nimport { DuplicateEntryGateway } from \"~/features/contentEntry/duplicateEntry/abstractions.js\";\nimport { UpdateRevisionDescriptionGateway } from \"~/features/contentEntry/updateRevisionDescription/abstractions.js\";\nimport { EventPublisher } from \"@webiny/app/features/eventPublisher/index.js\";\nimport { ContentEntriesPresenter as Abstraction } from \"./abstractions.js\";\nimport { ContentEntriesPresenter } from \"./ContentEntriesPresenter.js\";\nimport type { IContentEntriesPresenter } from \"./abstractions.js\";\nimport type {\n IFolderTreeViewModel,\n IFolderOperationState\n} from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\n\nconst MODEL: CmsModel = {\n modelId: \"testModel\",\n name: \"Test Model\",\n singularApiName: \"TestModel\",\n pluralApiName: \"TestModels\",\n fields: [],\n layout: [],\n group: \"group-1\",\n titleFieldId: \"title\",\n descriptionFieldId: null,\n imageFieldId: null,\n tags: [],\n savedOn: \"\"\n} as unknown as CmsModel;\n\nfunction createEntry(\n entryId: string,\n folderId: string,\n overrides: Partial<CmsContentEntry> = {}\n): CmsContentEntry {\n return {\n id: `${entryId}#0001`,\n entryId,\n meta: {\n title: entryId,\n status: \"draft\",\n version: 1,\n locked: false\n },\n wbyAco_location: { folderId },\n values: {},\n createdBy: { id: \"user-1\", displayName: \"Test\", type: \"admin\" },\n createdOn: \"2024-01-01T00:00:00Z\",\n savedOn: \"2024-01-01T00:00:00Z\",\n ...overrides\n } as unknown as CmsContentEntry;\n}\n\nclass MockFolderTreePresenter implements FolderTreePresenter.Interface {\n private _currentFolderId: string | null = null;\n\n constructor() {\n makeAutoObservable(this);\n }\n\n get vm(): IFolderTreeViewModel {\n return {\n folders: [],\n tree: [],\n currentFolderId: this._currentFolderId,\n currentFolder: null,\n isRootFolder: this._currentFolderId === null,\n currentFolderTitle: \"Home\",\n childFolders: [],\n loading: false,\n loadingNodeIds: [],\n operation: { active: false, mode: null } as IFolderOperationState\n };\n }\n\n selectFolder(folderId: string | null): void {\n this._currentFolderId = folderId;\n }\n\n createFolder(): void {}\n editFolder(): void {}\n async deleteFolder(): Promise<void> {}\n async moveFolder(): Promise<void> {}\n async loadChildFolders(): Promise<void> {}\n canManageStructure(): boolean {\n return true;\n }\n getAncestorIds(): string[] {\n return [];\n }\n async submitOperation(): Promise<boolean> {\n return true;\n }\n cancelOperation(): void {}\n onFolderChange(): () => void {\n return () => {};\n }\n}\n\ninterface TestSetup {\n presenter: IContentEntriesPresenter;\n listEntriesGateway: { execute: ReturnType<typeof vi.fn> };\n moveEntryGateway: { execute: ReturnType<typeof vi.fn> };\n deleteEntryGateway: { execute: ReturnType<typeof vi.fn> };\n duplicateEntryGateway: { execute: ReturnType<typeof vi.fn> };\n getDescendantFolders: ReturnType<typeof vi.fn>;\n foldersPresenter: MockFolderTreePresenter;\n publishEntryGateway: { execute: ReturnType<typeof vi.fn> };\n container: Container;\n}\n\nfunction setup(): TestSetup {\n const container = new Container();\n\n ListPresenterFeature.register(container);\n\n const foldersPresenter = new MockFolderTreePresenter();\n container.registerInstance(FolderTreePresenter, foldersPresenter);\n\n container.registerInstance(Confirmation, {\n confirm: vi.fn(async (_name, _params, execute) => {\n if (execute) {\n return await execute(undefined);\n }\n return true;\n })\n } as unknown as Confirmation.Interface);\n\n const getDescendantFolders = vi.fn().mockReturnValue([]);\n container.registerInstance(GetDescendantFoldersUseCase, {\n execute: getDescendantFolders\n });\n\n container.registerInstance(EventPublisher, { publish: vi.fn() });\n container.register(ContentEntriesCacheProvider).inSingletonScope();\n container.register(CmsModelContextImpl).inSingletonScope();\n container.resolve(CmsModelContext).setModel(MODEL);\n\n ListEntriesFeature.register(container);\n DeleteEntryFeature.register(container);\n PublishEntryFeature.register(container);\n UnpublishEntryFeature.register(container);\n MoveEntryFeature.register(container);\n DuplicateEntryFeature.register(container);\n UpdateRevisionDescriptionFeature.register(container);\n\n const listEntriesGateway = { execute: vi.fn() };\n const moveEntryGateway = { execute: vi.fn() };\n const deleteEntryGateway = { execute: vi.fn() };\n\n container.registerInstance(ListEntriesGateway, listEntriesGateway);\n container.registerInstance(MoveEntryGateway, moveEntryGateway);\n container.registerInstance(DeleteEntryGateway, deleteEntryGateway);\n const duplicateEntryGateway = { execute: vi.fn() };\n container.registerInstance(DuplicateEntryGateway, duplicateEntryGateway);\n const publishEntryGateway = { execute: vi.fn() };\n container.registerInstance(PublishEntryGateway, publishEntryGateway);\n container.registerInstance(UnpublishEntryGateway, { execute: vi.fn() });\n container.registerInstance(UpdateRevisionDescriptionGateway, { execute: vi.fn() });\n\n container.register(ContentEntriesPresenter).inSingletonScope();\n const presenter = container.resolve(Abstraction);\n\n return {\n presenter,\n listEntriesGateway,\n moveEntryGateway,\n deleteEntryGateway,\n duplicateEntryGateway,\n getDescendantFolders,\n foldersPresenter,\n publishEntryGateway,\n container\n };\n}\n\nasync function initPresenter(\n t: TestSetup,\n gatewayResponse: { data: CmsContentEntry[]; meta?: object }\n) {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: gatewayResponse.data,\n meta: gatewayResponse.meta ?? {\n cursor: null,\n hasMoreItems: false,\n totalCount: gatewayResponse.data.length\n }\n });\n\n t.presenter.init();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n}\n\ndescribe(\"ContentEntriesPresenter\", () => {\n let t: TestSetup;\n\n beforeEach(() => {\n t = setup();\n });\n\n describe(\"initial load\", () => {\n it(\"should show root entries after setModel\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n\n await initPresenter(t, { data: entries });\n\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"entry-1\", \"entry-2\"]);\n });\n\n it(\"should send folderId=root in the gateway query\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.listEntriesGateway.execute).toHaveBeenCalledWith(\n expect.objectContaining({\n where: expect.objectContaining({\n wbyAco_location: { folderId: \"root\" }\n })\n })\n );\n });\n\n it(\"should set model after init\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n });\n\n describe(\"folder navigation\", () => {\n it(\"should filter to folder entries when navigating to a subfolder\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"folder-2\", \"folder-a\")\n ];\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\"folder-1\", \"folder-2\"]);\n });\n\n it(\"should show only root entries when navigating back to root\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"folder-1\");\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n\n it(\"should not leak subfolder entries into root view\", async () => {\n const rootEntries = [createEntry(\"root-1\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"folder-1\", \"folder-a\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(\"folder-a\");\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.foldersPresenter.selectFolder(null);\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"root-1\");\n });\n });\n });\n\n describe(\"search\", () => {\n it(\"should show only search results from API\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n const searchResults = [createEntry(\"entry-1\", \"root\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-1\");\n });\n\n it(\"should include entries from subfolders when searching from root\", async () => {\n await initPresenter(t, { data: [] });\n\n const searchResults = [\n createEntry(\"root-1\", \"root\"),\n createEntry(\"folder-1\", \"folder-a\")\n ];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: searchResults,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n\n it(\"should search with folderId_in containing all descendant folders when in a subfolder\", async () => {\n const folderEntries = [createEntry(\"folder-1\", \"folder-a\")];\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: folderEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.init({ initialFolderId: \"folder-a\" });\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.pagination.loading).toBe(false);\n });\n\n t.getDescendantFolders.mockReturnValue([\n { id: \"folder-a\" },\n { id: \"folder-a-1\" },\n { id: \"folder-a-2\" }\n ]);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [\n createEntry(\"folder-1\", \"folder-a\"),\n createEntry(\"sub-1\", \"folder-a-1\"),\n createEntry(\"sub-2\", \"folder-a-2\")\n ],\n meta: { cursor: null, hasMoreItems: false, totalCount: 3 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(3);\n });\n\n expect(t.getDescendantFolders).toHaveBeenCalledWith(\"folder-a\");\n\n const searchCall = t.listEntriesGateway.execute.mock.calls.at(-1) ?? [];\n expect(searchCall[0].where).toEqual(\n expect.objectContaining({\n wbyAco_location: {\n folderId_in: [\"folder-a\", \"folder-a-1\", \"folder-a-2\"]\n }\n })\n );\n });\n\n it(\"should restore folder view when clearing search\", async () => {\n const rootEntries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: rootEntries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [createEntry(\"entry-1\", \"root\")],\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.search.set(\"entry-1\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: rootEntries,\n meta: { cursor: null, hasMoreItems: false, totalCount: 2 }\n });\n\n t.presenter.list.actions.search.clear();\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(2);\n });\n });\n });\n\n describe(\"status filter\", () => {\n it(\"should filter by status locally\", async () => {\n const entries = [\n createEntry(\"draft-1\", \"root\", {\n meta: {\n title: \"draft-1\",\n status: \"draft\",\n version: 1,\n locked: false\n }\n }),\n createEntry(\"published-1\", \"root\", {\n meta: {\n title: \"published-1\",\n status: \"published\",\n version: 1,\n locked: false\n }\n })\n ];\n await initPresenter(t, { data: entries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: entries.filter(e => (e.meta as { status: string }).status === \"published\"),\n meta: { cursor: null, hasMoreItems: false, totalCount: 1 }\n });\n\n t.presenter.list.actions.filter.set(\"status\", \"published\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"published-1\");\n });\n });\n });\n\n describe(\"move entry\", () => {\n it(\"should remove entry from current view after move\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.moveEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.moveEntry(\"entry-1#0001\", \"folder-b\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"duplicate entry\", () => {\n it(\"should add the duplicated entry to the current view\", async () => {\n const entries = [\n createEntry(\"entry-2\", \"root\", { savedOn: \"2024-01-02T00:00:00.000Z\" }),\n createEntry(\"entry-1\", \"root\", { savedOn: \"2024-01-01T00:00:00.000Z\" })\n ];\n await initPresenter(t, { data: entries });\n\n const duplicate = createEntry(\"entry-3\", \"root\", {\n savedOn: \"2024-01-03T00:00:00.000Z\"\n });\n t.duplicateEntryGateway.execute.mockResolvedValueOnce(duplicate);\n\n const result = await t.presenter.duplicateEntry(entries[1]);\n\n expect(result).toEqual({ entry: duplicate });\n expect(t.duplicateEntryGateway.execute).toHaveBeenCalledWith({\n model: MODEL,\n revisionId: \"entry-1#0001\"\n });\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\n \"entry-3\",\n \"entry-2\",\n \"entry-1\"\n ]);\n });\n });\n\n it(\"should return the error when duplication fails\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\")];\n await initPresenter(t, { data: entries });\n\n const error = new Error(\"Not allowed.\");\n t.duplicateEntryGateway.execute.mockRejectedValueOnce(error);\n\n const result = await t.presenter.duplicateEntry(entries[0]);\n\n expect(result).toEqual({ error });\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n });\n });\n\n describe(\"delete entry\", () => {\n it(\"should remove entry from current view after delete\", async () => {\n const entries = [createEntry(\"entry-1\", \"root\"), createEntry(\"entry-2\", \"root\")];\n await initPresenter(t, { data: entries });\n\n t.deleteEntryGateway.execute.mockResolvedValueOnce(true);\n\n await t.presenter.deleteEntry(\"entry-1#0001\");\n\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.rows).toHaveLength(1);\n expect(t.presenter.list.vm.rows[0].entryId).toBe(\"entry-2\");\n });\n });\n });\n\n describe(\"vm\", () => {\n it(\"should set model on init\", () => {\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n t.presenter.init();\n expect(t.presenter.vm.model).toStrictEqual(MODEL);\n });\n\n it(\"should track selected entry\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showingEntry).toBe(false);\n\n t.presenter.selectEntry(\"some-id\");\n expect(t.presenter.vm.selectedEntryId).toBe(\"some-id\");\n expect(t.presenter.vm.showingEntry).toBe(true);\n\n t.presenter.deselectEntry();\n expect(t.presenter.vm.selectedEntryId).toBeNull();\n expect(t.presenter.vm.showingEntry).toBe(false);\n });\n\n it(\"should set selectedEntryId to 'new' on createEntry\", async () => {\n await initPresenter(t, { data: [] });\n\n t.presenter.createEntry();\n expect(t.presenter.vm.selectedEntryId).toBe(\"new\");\n });\n\n it(\"should show folders when no search or non-folder filters active\", async () => {\n await initPresenter(t, { data: [] });\n\n expect(t.presenter.vm.showFolders).toBe(true);\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n });\n\n t.presenter.list.actions.search.set(\"test\");\n\n await vi.waitFor(() => {\n expect(t.presenter.vm.showFolders).toBe(false);\n });\n });\n });\n\n describe(\"publish entry\", () => {\n /**\n * Publishing is not a content modification: the API returns the entry with its\n * `savedOn` unchanged, so the entry must keep its position in a list sorted by `savedOn`.\n */\n const entries = [\n createEntry(\"entry-3\", \"root\", { savedOn: \"2024-01-03T00:00:00.000Z\" }),\n createEntry(\"entry-2\", \"root\", { savedOn: \"2024-01-02T00:00:00.000Z\" }),\n createEntry(\"entry-1\", \"root\", { savedOn: \"2024-01-01T00:00:00.000Z\" })\n ];\n\n const publish = async (entry: CmsContentEntry) => {\n t.publishEntryGateway.execute.mockResolvedValueOnce({\n ...entry,\n meta: { ...entry.meta, status: \"published\", locked: true }\n });\n await t.container\n .resolve(PublishEntryUseCase)\n .execute({ model: MODEL, revisionId: entry.id });\n };\n\n it(\"should keep a published entry in its position\", async () => {\n await initPresenter(t, { data: entries });\n\n await publish(entries[1]);\n\n const rows = t.presenter.list.vm.rows;\n expect(rows.map(r => r.entryId)).toEqual([\"entry-3\", \"entry-2\", \"entry-1\"]);\n expect((rows[1].meta as { status: string }).status).toBe(\"published\");\n });\n\n it(\"should keep a published entry in its position when sorted ascending\", async () => {\n await initPresenter(t, { data: entries });\n\n t.listEntriesGateway.execute.mockResolvedValueOnce({\n data: [...entries].reverse(),\n meta: { cursor: null, hasMoreItems: false, totalCount: entries.length }\n });\n t.presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await vi.waitFor(() => {\n expect(t.presenter.list.vm.appliedQuery?.sort?.direction).toBe(\"ASC\");\n });\n\n await publish(entries[1]);\n\n expect(t.presenter.list.vm.rows.map(r => r.entryId)).toEqual([\n \"entry-1\",\n \"entry-2\",\n \"entry-3\"\n ]);\n });\n });\n});\n"],"names":["MODEL","createEntry","entryId","folderId","overrides","MockFolderTreePresenter","makeAutoObservable","setup","container","Container","ListPresenterFeature","foldersPresenter","FolderTreePresenter","Confirmation","vi","_name","_params","execute","undefined","getDescendantFolders","GetDescendantFoldersUseCase","EventPublisher","ContentEntriesCacheProvider","CmsModelContextImpl","CmsModelContext","ListEntriesFeature","DeleteEntryFeature","PublishEntryFeature","UnpublishEntryFeature","MoveEntryFeature","DuplicateEntryFeature","UpdateRevisionDescriptionFeature","listEntriesGateway","moveEntryGateway","deleteEntryGateway","ListEntriesGateway","MoveEntryGateway","DeleteEntryGateway","duplicateEntryGateway","DuplicateEntryGateway","publishEntryGateway","PublishEntryGateway","UnpublishEntryGateway","UpdateRevisionDescriptionGateway","ContentEntriesPresenter","presenter","Abstraction","initPresenter","t","gatewayResponse","expect","describe","beforeEach","it","entries","r","rootEntries","folderEntries","searchResults","searchCall","e","duplicate","result","error","Error","publish","entry","PublishEntryUseCase","rows"],"mappings":"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"}