@webiny/app-website-builder 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 (167) hide show
  1. package/BaseEditor/config/Sidebar/Tab.d.ts +0 -4
  2. package/BaseEditor/config/Sidebar/Tab.js +5 -21
  3. package/BaseEditor/config/Sidebar/Tab.js.map +1 -1
  4. package/BaseEditor/defaultConfig/Content/AddressBar/PreviewDomain.js +6 -66
  5. package/BaseEditor/defaultConfig/Content/AddressBar/PreviewDomain.js.map +1 -1
  6. package/BaseEditor/defaultConfig/Content/Preview/DropZoneManager.js.map +1 -1
  7. package/BaseEditor/defaultConfig/Content/Preview/Iframe.d.ts +2 -2
  8. package/BaseEditor/defaultConfig/Content/Preview/Overlays/ElementOverlays.d.ts +2 -2
  9. package/BaseEditor/defaultConfig/Content/Preview/PreviewContainer.js +1 -1
  10. package/BaseEditor/defaultConfig/Content/Preview/PreviewContainer.js.map +1 -1
  11. package/BaseEditor/defaultConfig/Content/usePreviewDomain.d.ts +1 -6
  12. package/BaseEditor/defaultConfig/Content/usePreviewDomain.js +1 -26
  13. package/BaseEditor/defaultConfig/DocumentStateEditor/DocumentStateEditor.d.ts +2 -2
  14. package/BaseEditor/defaultConfig/ElementInputRenderers.js +12 -0
  15. package/BaseEditor/defaultConfig/ElementInputRenderers.js.map +1 -1
  16. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementSettingsGroup.js +2 -5
  17. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/ElementSettingsGroup.js.map +1 -1
  18. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/PreviewedBindings.d.ts +22 -0
  19. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/PreviewedBindings.js +17 -0
  20. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/PreviewedBindings.js.map +1 -0
  21. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/PreviewedBindings.test.d.ts +1 -0
  22. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/PreviewedBindings.test.js +64 -0
  23. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/PreviewedBindings.test.js.map +1 -0
  24. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/useInputValue.js +7 -2
  25. package/BaseEditor/defaultConfig/Sidebar/ElementSettings/useInputValue.js.map +1 -1
  26. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundColor.d.ts +6 -2
  27. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundImage.d.ts +6 -2
  28. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundImage.js +8 -1
  29. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundImage.js.map +1 -1
  30. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundPosition.d.ts +6 -2
  31. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Background/BackgroundScaling.d.ts +6 -2
  32. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderColor.d.ts +2 -2
  33. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderRadius.d.ts +2 -2
  34. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderStyle.d.ts +2 -2
  35. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Border/BorderWidth.d.ts +2 -2
  36. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Layout/Alignment.d.ts +6 -2
  37. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Layout/LengthWithUnitInput.d.ts +2 -2
  38. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/MarginPadding/Margin.d.ts +2 -2
  39. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/MarginPadding/Padding.d.ts +2 -2
  40. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/Groups/Visibility/Visibility.d.ts +2 -2
  41. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/SidebarRow.js +1 -1
  42. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/SidebarRow.js.map +1 -1
  43. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/StyleSettingsGroup.js +2 -5
  44. package/BaseEditor/defaultConfig/Sidebar/StyleSettings/StyleSettingsGroup.js.map +1 -1
  45. package/BaseEditor/defaultConfig/Toolbar/Navigator/Navigator.d.ts +2 -2
  46. package/DocumentEditor/DocumentEditor.d.ts +2 -2
  47. package/DocumentEditor/StateInspector.d.ts +4 -2
  48. package/Extension.js +3 -0
  49. package/Extension.js.map +1 -1
  50. package/domain/Page/Page.d.ts +2 -0
  51. package/domain/Page/Page.js +1 -0
  52. package/domain/Page/Page.js.map +1 -1
  53. package/domain/PageRevision/PageRevision.d.ts +11 -0
  54. package/domain/PageRevision/PageRevision.js +20 -0
  55. package/domain/PageRevision/PageRevision.js.map +1 -1
  56. package/ecommerce/components/ResourcePage.d.ts +6 -2
  57. package/ecommerce/components/ResourcesList.d.ts +4 -4
  58. package/ecommerce/components/ResourcesPicker.d.ts +9 -4
  59. package/editorSdk/CommandBus.js.map +1 -1
  60. package/features/pages/createPageRevisionFrom/CreatePageRevisionFrom.test.js +41 -1
  61. package/features/pages/createPageRevisionFrom/CreatePageRevisionFrom.test.js.map +1 -1
  62. package/features/pages/createPageRevisionFrom/CreatePageRevisionFromRepository.d.ts +3 -2
  63. package/features/pages/createPageRevisionFrom/CreatePageRevisionFromRepository.js +8 -2
  64. package/features/pages/createPageRevisionFrom/CreatePageRevisionFromRepository.js.map +1 -1
  65. package/features/pages/deletePageRevision/DeletePageRevision.test.d.ts +1 -0
  66. package/features/pages/deletePageRevision/DeletePageRevision.test.js +67 -0
  67. package/features/pages/deletePageRevision/DeletePageRevision.test.js.map +1 -0
  68. package/features/pages/deletePageRevision/DeletePageRevisionGateway.d.ts +1 -1
  69. package/features/pages/deletePageRevision/DeletePageRevisionGateway.js +2 -3
  70. package/features/pages/deletePageRevision/DeletePageRevisionGateway.js.map +1 -1
  71. package/features/pages/deletePageRevision/DeletePageRevisionRepository.d.ts +4 -2
  72. package/features/pages/deletePageRevision/DeletePageRevisionRepository.js +7 -3
  73. package/features/pages/deletePageRevision/DeletePageRevisionRepository.js.map +1 -1
  74. package/features/pages/deletePageRevision/DeletePageRevisionUseCase.js +1 -1
  75. package/features/pages/deletePageRevision/DeletePageRevisionUseCase.js.map +1 -1
  76. package/features/pages/deletePageRevision/abstractions.d.ts +2 -3
  77. package/features/pages/deletePageRevision/abstractions.js.map +1 -1
  78. package/features/pages/getPage/PageGatewayDto.d.ts +2 -0
  79. package/features/pages/publishPage/PublishPage.test.js +41 -1
  80. package/features/pages/publishPage/PublishPage.test.js.map +1 -1
  81. package/features/pages/publishPage/PublishPageRepository.d.ts +3 -2
  82. package/features/pages/publishPage/PublishPageRepository.js +15 -4
  83. package/features/pages/publishPage/PublishPageRepository.js.map +1 -1
  84. package/features/pages/shared/pageGraphQLFields.js +1 -0
  85. package/features/pages/shared/pageGraphQLFields.js.map +1 -1
  86. package/features/pages/unpublishPage/UnpublishPage.test.js +4 -1
  87. package/features/pages/unpublishPage/UnpublishPage.test.js.map +1 -1
  88. package/features/pages/unpublishPage/UnpublishPageRepository.d.ts +3 -2
  89. package/features/pages/unpublishPage/UnpublishPageRepository.js +12 -4
  90. package/features/pages/unpublishPage/UnpublishPageRepository.js.map +1 -1
  91. package/inputRenderers/DateTimeInput.d.ts +9 -0
  92. package/inputRenderers/DateTimeInput.js +21 -0
  93. package/inputRenderers/DateTimeInput.js.map +1 -0
  94. package/inputRenderers/DateTimeInput.test.d.ts +1 -0
  95. package/inputRenderers/DateTimeInput.test.js +27 -0
  96. package/inputRenderers/DateTimeInput.test.js.map +1 -0
  97. package/inputRenderers/FileInput.js +1 -1
  98. package/inputRenderers/FileInput.js.map +1 -1
  99. package/inputRenderers/RadioInput.d.ts +3 -0
  100. package/inputRenderers/RadioInput.js +20 -0
  101. package/inputRenderers/RadioInput.js.map +1 -0
  102. package/inputRenderers/TagsInput.d.ts +3 -0
  103. package/inputRenderers/TagsInput.js +22 -0
  104. package/inputRenderers/TagsInput.js.map +1 -0
  105. package/package.json +31 -31
  106. package/presentation/pages/CreatePage/CreatePageDialog.d.ts +2 -2
  107. package/presentation/pages/PageEditor/Revisions/RevisionListDrawer.js +4 -0
  108. package/presentation/pages/PageEditor/Revisions/RevisionListDrawer.js.map +1 -1
  109. package/presentation/pages/PageEditor/Revisions/RevisionListItem.d.ts +3 -3
  110. package/presentation/pages/PageEditor/Revisions/RevisionListItem.js +9 -20
  111. package/presentation/pages/PageEditor/Revisions/RevisionListItem.js.map +1 -1
  112. package/presentation/pages/PageEditor/Revisions/RevisionsList.js +7 -19
  113. package/presentation/pages/PageEditor/Revisions/RevisionsList.js.map +1 -1
  114. package/presentation/pages/PageEditor/Revisions/useRevision.d.ts +1 -1
  115. package/presentation/pages/PageEditor/Revisions/useRevision.js +84 -14
  116. package/presentation/pages/PageEditor/Revisions/useRevision.js.map +1 -1
  117. package/presentation/pages/PageEditor/Revisions/useRevisionList.d.ts +3 -0
  118. package/presentation/pages/PageEditor/Revisions/useRevisionList.js +31 -0
  119. package/presentation/pages/PageEditor/Revisions/useRevisionList.js.map +1 -0
  120. package/presentation/pages/PageEditor/TopBar/PageSettingsDrawer.d.ts +2 -2
  121. package/presentation/pages/PageEditor/TopBar/RevisionsMenu.js +7 -19
  122. package/presentation/pages/PageEditor/TopBar/RevisionsMenu.js.map +1 -1
  123. package/presentation/pages/PageList/PageListDataSource.js +1 -1
  124. package/presentation/pages/PageList/PageListDataSource.js.map +1 -1
  125. package/presentation/pages/PageList/PageListPresenter.test.d.ts +1 -0
  126. package/presentation/pages/PageList/PageListPresenter.test.js +293 -0
  127. package/presentation/pages/PageList/PageListPresenter.test.js.map +1 -0
  128. package/presentation/pages/PageList/components/BulkActions/BulkActionDelete.d.ts +2 -2
  129. package/presentation/pages/PageList/components/BulkActions/BulkActionDuplicate.d.ts +2 -2
  130. package/presentation/pages/PageList/components/BulkActions/BulkActionMovePage.d.ts +2 -2
  131. package/presentation/pages/PageList/components/BulkActions/BulkActionPublish.d.ts +2 -2
  132. package/presentation/pages/PageList/components/BulkActions/BulkActionUnpublish.d.ts +2 -2
  133. package/presentation/pages/PageList/components/DocumentList.d.ts +2 -2
  134. package/presentation/pages/PageList/components/Table/Table.d.ts +2 -2
  135. package/presentation/pages/RevisionList/RevisionListPresenter.d.ts +27 -0
  136. package/presentation/pages/RevisionList/RevisionListPresenter.js +73 -0
  137. package/presentation/pages/RevisionList/RevisionListPresenter.js.map +1 -0
  138. package/presentation/pages/RevisionList/RevisionListPresenter.test.d.ts +1 -0
  139. package/presentation/pages/RevisionList/RevisionListPresenter.test.js +219 -0
  140. package/presentation/pages/RevisionList/RevisionListPresenter.test.js.map +1 -0
  141. package/presentation/pages/RevisionList/abstractions.d.ts +34 -0
  142. package/presentation/pages/RevisionList/abstractions.js +5 -0
  143. package/presentation/pages/RevisionList/abstractions.js.map +1 -0
  144. package/presentation/pages/RevisionList/feature.d.ts +3 -0
  145. package/presentation/pages/RevisionList/feature.js +17 -0
  146. package/presentation/pages/RevisionList/feature.js.map +1 -0
  147. package/presentation/pages/RevisionList/index.d.ts +2 -0
  148. package/presentation/pages/RevisionList/index.js +1 -0
  149. package/presentation/pages/TrashBin/WbTrashBin.d.ts +2 -2
  150. package/presentation/redirects/RedirectList/RedirectListDataSource.js +1 -1
  151. package/presentation/redirects/RedirectList/RedirectListDataSource.js.map +1 -1
  152. package/presentation/redirects/RedirectList/RedirectListPresenter.js.map +1 -1
  153. package/presentation/redirects/RedirectList/RedirectListPresenter.test.d.ts +1 -0
  154. package/presentation/redirects/RedirectList/RedirectListPresenter.test.js +273 -0
  155. package/presentation/redirects/RedirectList/RedirectListPresenter.test.js.map +1 -0
  156. package/presentation/redirects/RedirectList/components/BulkActionDelete.d.ts +2 -2
  157. package/presentation/redirects/RedirectList/components/BulkActionMove.d.ts +2 -2
  158. package/presentation/redirects/RedirectList/components/CreateRedirectDialog.d.ts +2 -2
  159. package/presentation/redirects/RedirectList/components/DocumentList.d.ts +2 -2
  160. package/presentation/redirects/RedirectList/components/EditRedirectDialog.d.ts +2 -2
  161. package/presentation/redirects/RedirectList/components/Table/Table.d.ts +2 -2
  162. package/shared/fileManagerItemToValue.js +3 -1
  163. package/shared/fileManagerItemToValue.js.map +1 -1
  164. package/shared/fileManagerItemToValue.test.d.ts +1 -0
  165. package/shared/fileManagerItemToValue.test.js +73 -0
  166. package/shared/fileManagerItemToValue.test.js.map +1 -0
  167. package/BaseEditor/defaultConfig/Content/usePreviewDomain.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/pages/PageEditor/TopBar/RevisionsMenu.js","sources":["../../../../../src/presentation/pages/PageEditor/TopBar/RevisionsMenu.tsx"],"sourcesContent":["import React, { useState, useEffect, useCallback } from \"react\";\nimport { Button, DropdownMenu, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as ArrowDown } from \"@webiny/icons/keyboard_arrow_down.svg\";\nimport { ReactComponent as Draft } from \"@webiny/icons/draw.svg\";\nimport { ReactComponent as Unpublished } from \"@webiny/icons/lock.svg\";\nimport { ReactComponent as Published } from \"@webiny/icons/remove_red_eye.svg\";\nimport { useGetPageRevisions } from \"~/features/pages/index.js\";\nimport { useSelectFromDocument } from \"~/BaseEditor/hooks/useSelectFromDocument.js\";\nimport type { PageRevision } from \"~/domain/PageRevision/index.js\";\nimport type { EditorPage } from \"@webiny/website-builder-sdk\";\nimport { useRouter } from \"@webiny/app-admin\";\nimport { Routes } from \"~/routes.js\";\nimport { usePageEditorDrawer } from \"~/presentation/pages/PageEditor/Revisions/usePageEditorDrawer.js\";\n\nconst { Item } = DropdownMenu;\n\nconst statusIcon: Record<string, React.JSX.Element> = {\n draft: <Draft />,\n published: <Published />,\n unpublished: <Unpublished />\n};\n\nexport const RevisionsMenu = () => {\n const { getLink } = useRouter();\n const [revisions, setRevisions] = useState<PageRevision[]>([]);\n const { loading, getPageRevisions } = useGetPageRevisions();\n const id = useSelectFromDocument(document => document.id);\n const status = useSelectFromDocument<string, EditorPage>(document => document.status);\n\n const { openRevisionList } = usePageEditorDrawer();\n\n useEffect(() => {\n const [entryId] = id.split(\"#\");\n getPageRevisions({ entryId }).then(revisions => {\n setRevisions(\n revisions\n .sort((a, b) => {\n return new Date(a.savedOn).getTime() - new Date(b.savedOn).getTime();\n })\n .reverse()\n );\n });\n }, [id, status]);\n\n const currentRevision = revisions.find(r => r.id === id);\n\n const goToRevision = useCallback((id: string) => {\n // TODO: make this work without a full app reload\n window.location.pathname = getLink(Routes.Pages.Editor, { id });\n }, []);\n\n const onOpenRevisionList = useCallback(() => {\n openRevisionList(true);\n }, []);\n\n return (\n <DropdownMenu\n trigger={\n <Button\n disabled={loading}\n variant=\"ghost\"\n text={currentRevision ? currentRevision.getLabel() : \"Loading...\"}\n icon={<ArrowDown />}\n iconPosition={\"end\"}\n />\n }\n >\n {revisions.slice(0, 5).map(revision => (\n <Item\n key={revision.id}\n className={\"cursor-pointer\"}\n onClick={() => goToRevision(revision.id)}\n icon={\n <Item.Icon\n label={revision.getLabel()}\n element={statusIcon[revision.status]}\n />\n }\n text={<Text size={\"sm\"}>{revision.getLabel()}</Text>}\n />\n ))}\n\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n key={\"revisions-all\"}\n onClick={onOpenRevisionList}\n text={\n <>\n <Text size={\"sm\"}>Show All Revisions</Text>\n </>\n }\n />\n </DropdownMenu>\n );\n};\n"],"names":["Item","DropdownMenu","statusIcon","Draft","Published","Unpublished","RevisionsMenu","getLink","useRouter","revisions","setRevisions","useState","loading","getPageRevisions","useGetPageRevisions","id","useSelectFromDocument","document","status","openRevisionList","usePageEditorDrawer","useEffect","entryId","a","b","Date","currentRevision","r","goToRevision","useCallback","window","Routes","onOpenRevisionList","Button","ArrowDown","revision","Text"],"mappings":";;;;;;;;;;;AAcA,MAAM,EAAEA,MAAAA,IAAI,EAAE,GAAGC;AAEjB,MAAMC,aAAgD;IAClD,OAAO,WAAP,GAAO,oBAACC,yBAAKA;IACb,WAAW,WAAX,GAAW,oBAACC,mCAASA;IACrB,aAAa,WAAb,GAAa,oBAACC,yBAAWA;AAC7B;AAEO,MAAMC,gBAAgB;IACzB,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAM,CAACC,WAAWC,aAAa,GAAGC,SAAyB,EAAE;IAC7D,MAAM,EAAEC,OAAO,EAAEC,gBAAgB,EAAE,GAAGC;IACtC,MAAMC,KAAKC,sBAAsBC,CAAAA,WAAYA,SAAS,EAAE;IACxD,MAAMC,SAASF,sBAA0CC,CAAAA,WAAYA,SAAS,MAAM;IAEpF,MAAM,EAAEE,gBAAgB,EAAE,GAAGC;IAE7BC,UAAU;QACN,MAAM,CAACC,QAAQ,GAAGP,GAAG,KAAK,CAAC;QAC3BF,iBAAiB;YAAES;QAAQ,GAAG,IAAI,CAACb,CAAAA;YAC/BC,aACID,UACK,IAAI,CAAC,CAACc,GAAGC,IACC,IAAIC,KAAKF,EAAE,OAAO,EAAE,OAAO,KAAK,IAAIE,KAAKD,EAAE,OAAO,EAAE,OAAO,IAErE,OAAO;QAEpB;IACJ,GAAG;QAACT;QAAIG;KAAO;IAEf,MAAMQ,kBAAkBjB,UAAU,IAAI,CAACkB,CAAAA,IAAKA,EAAE,EAAE,KAAKZ;IAErD,MAAMa,eAAeC,YAAY,CAACd;QAE9Be,OAAO,QAAQ,CAAC,QAAQ,GAAGvB,QAAQwB,OAAO,KAAK,CAAC,MAAM,EAAE;YAAEhB;QAAG;IACjE,GAAG,EAAE;IAEL,MAAMiB,qBAAqBH,YAAY;QACnCV,iBAAiB;IACrB,GAAG,EAAE;IAEL,OAAO,WAAP,GACI,oBAAClB,cAAYA;QACT,uBACI,oBAACgC,QAAMA;YACH,UAAUrB;YACV,SAAQ;YACR,MAAMc,kBAAkBA,gBAAgB,QAAQ,KAAK;YACrD,oBAAM,oBAACQ,gBAASA;YAChB,cAAc;;OAIrBzB,UAAU,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC0B,CAAAA,WAAAA,WAAAA,GACvB,oBAACnC,MAAIA;YACD,KAAKmC,SAAS,EAAE;YAChB,WAAW;YACX,SAAS,IAAMP,aAAaO,SAAS,EAAE;YACvC,oBACI,oBAACnC,KAAK,IAAI;gBACN,OAAOmC,SAAS,QAAQ;gBACxB,SAASjC,UAAU,CAACiC,SAAS,MAAM,CAAC;;YAG5C,oBAAM,oBAACC,MAAIA;gBAAC,MAAM;eAAOD,SAAS,QAAQ;2BAIlD,oBAAClC,aAAa,SAAS,uBACvB,oBAACA,aAAa,IAAI;QACd,KAAK;QACL,SAAS+B;QACT,oBACI,wDACI,oBAACI,MAAIA;YAAC,MAAM;WAAM;;AAM1C"}
1
+ {"version":3,"file":"presentation/pages/PageEditor/TopBar/RevisionsMenu.js","sources":["../../../../../src/presentation/pages/PageEditor/TopBar/RevisionsMenu.tsx"],"sourcesContent":["import React, { useCallback } from \"react\";\nimport { Button, DropdownMenu, Text } from \"@webiny/admin-ui\";\nimport { ReactComponent as ArrowDown } from \"@webiny/icons/keyboard_arrow_down.svg\";\nimport { ReactComponent as Draft } from \"@webiny/icons/draw.svg\";\nimport { ReactComponent as Unpublished } from \"@webiny/icons/lock.svg\";\nimport { ReactComponent as Published } from \"@webiny/icons/remove_red_eye.svg\";\nimport { useSelectFromDocument } from \"~/BaseEditor/hooks/useSelectFromDocument.js\";\nimport { useRevisionList } from \"~/presentation/pages/PageEditor/Revisions/useRevisionList.js\";\nimport { useRouter } from \"@webiny/app-admin\";\nimport { Routes } from \"~/routes.js\";\nimport { usePageEditorDrawer } from \"~/presentation/pages/PageEditor/Revisions/usePageEditorDrawer.js\";\n\nconst { Item } = DropdownMenu;\n\nconst statusIcon: Record<string, React.JSX.Element> = {\n draft: <Draft />,\n published: <Published />,\n unpublished: <Unpublished />\n};\n\nexport const RevisionsMenu = () => {\n const { getLink } = useRouter();\n const id = useSelectFromDocument(document => document.id);\n\n const { openRevisionList } = usePageEditorDrawer();\n\n // Shares the presenter with the revisions drawer, so mutations made there are reflected here.\n const { vm } = useRevisionList(id);\n const { revisions, isLoading } = vm;\n\n const currentRevision = revisions.find(item => item.revision.id === id)?.revision;\n\n const goToRevision = useCallback((id: string) => {\n // TODO: make this work without a full app reload\n window.location.pathname = getLink(Routes.Pages.Editor, { id });\n }, []);\n\n const onOpenRevisionList = useCallback(() => {\n openRevisionList(true);\n }, []);\n\n return (\n <DropdownMenu\n trigger={\n <Button\n disabled={isLoading}\n variant=\"ghost\"\n text={currentRevision ? currentRevision.getLabel() : \"Loading...\"}\n icon={<ArrowDown />}\n iconPosition={\"end\"}\n />\n }\n >\n {revisions.slice(0, 5).map(({ revision }) => (\n <Item\n key={revision.id}\n className={\"cursor-pointer\"}\n onClick={() => goToRevision(revision.id)}\n icon={\n <Item.Icon\n label={revision.getLabel()}\n element={statusIcon[revision.status]}\n />\n }\n text={<Text size={\"sm\"}>{revision.getLabel()}</Text>}\n />\n ))}\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n key={\"revisions-all\"}\n onClick={onOpenRevisionList}\n text={\n <>\n <Text size={\"sm\"}>Show All Revisions</Text>\n </>\n }\n />\n </DropdownMenu>\n );\n};\n"],"names":["Item","DropdownMenu","statusIcon","Draft","Published","Unpublished","RevisionsMenu","getLink","useRouter","id","useSelectFromDocument","document","openRevisionList","usePageEditorDrawer","vm","useRevisionList","revisions","isLoading","currentRevision","item","goToRevision","useCallback","window","Routes","onOpenRevisionList","Button","ArrowDown","revision","Text"],"mappings":";;;;;;;;;;;AAYA,MAAM,EAAEA,MAAAA,IAAI,EAAE,GAAGC;AAEjB,MAAMC,aAAgD;IAClD,OAAO,WAAP,GAAO,oBAACC,yBAAKA;IACb,WAAW,WAAX,GAAW,oBAACC,mCAASA;IACrB,aAAa,WAAb,GAAa,oBAACC,yBAAWA;AAC7B;AAEO,MAAMC,gBAAgB;IACzB,MAAM,EAAEC,OAAO,EAAE,GAAGC;IACpB,MAAMC,KAAKC,sBAAsBC,CAAAA,WAAYA,SAAS,EAAE;IAExD,MAAM,EAAEC,gBAAgB,EAAE,GAAGC;IAG7B,MAAM,EAAEC,EAAE,EAAE,GAAGC,gBAAgBN;IAC/B,MAAM,EAAEO,SAAS,EAAEC,SAAS,EAAE,GAAGH;IAEjC,MAAMI,kBAAkBF,UAAU,IAAI,CAACG,CAAAA,OAAQA,KAAK,QAAQ,CAAC,EAAE,KAAKV,KAAK;IAEzE,MAAMW,eAAeC,YAAY,CAACZ;QAE9Ba,OAAO,QAAQ,CAAC,QAAQ,GAAGf,QAAQgB,OAAO,KAAK,CAAC,MAAM,EAAE;YAAEd;QAAG;IACjE,GAAG,EAAE;IAEL,MAAMe,qBAAqBH,YAAY;QACnCT,iBAAiB;IACrB,GAAG,EAAE;IAEL,OAAO,WAAP,GACI,oBAACX,cAAYA;QACT,uBACI,oBAACwB,QAAMA;YACH,UAAUR;YACV,SAAQ;YACR,MAAMC,kBAAkBA,gBAAgB,QAAQ,KAAK;YACrD,oBAAM,oBAACQ,gBAASA;YAChB,cAAc;;OAIrBV,UAAU,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,EAAEW,QAAQ,EAAE,iBACpC,oBAAC3B,MAAIA;YACD,KAAK2B,SAAS,EAAE;YAChB,WAAW;YACX,SAAS,IAAMP,aAAaO,SAAS,EAAE;YACvC,oBACI,oBAAC3B,KAAK,IAAI;gBACN,OAAO2B,SAAS,QAAQ;gBACxB,SAASzB,UAAU,CAACyB,SAAS,MAAM,CAAC;;YAG5C,oBAAM,oBAACC,MAAIA;gBAAC,MAAM;eAAOD,SAAS,QAAQ;2BAGlD,oBAAC1B,aAAa,SAAS,uBACvB,oBAACA,aAAa,IAAI;QACd,KAAK;QACL,SAASuB;QACT,oBACI,wDACI,oBAACI,MAAIA;YAAC,MAAM;WAAM;;AAM1C"}
@@ -7,7 +7,7 @@ class PageListDataSource extends FolderAwareDataSource {
7
7
  }), this.listPagesUseCase = listPagesUseCase, this.cache = cache;
8
8
  }
9
9
  get rows() {
10
- return this.queryMatcher.filter(this.cache.getItems());
10
+ return this.queryMatcher.select(this.cache.getItems());
11
11
  }
12
12
  async fetch(params) {
13
13
  return this.listPagesUseCase.execute({
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/pages/PageList/PageListDataSource.js","sources":["../../../../src/presentation/pages/PageList/PageListDataSource.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 { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { Page } from \"~/domain/Page/Page.js\";\nimport type { IListPagesUseCase } from \"~/features/pages/listPages/abstractions.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\n\nexport class PageListDataSource extends FolderAwareDataSource<Page> {\n constructor(\n private listPagesUseCase: IListPagesUseCase,\n private cache: IListCache<Page>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase\n ) {\n super({\n keyField: \"entryId\",\n getDescendantFolders: getDescendantFoldersUseCase\n });\n }\n\n get rows(): Page[] {\n return this.queryMatcher.filter(this.cache.getItems());\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<Page>> {\n return this.listPagesUseCase.execute({\n where: params.where,\n sort: params.sort,\n search: params.search,\n limit: params.limit,\n after: params.after\n });\n }\n}\n"],"names":["PageListDataSource","FolderAwareDataSource","listPagesUseCase","cache","getDescendantFoldersUseCase","params"],"mappings":";AAUO,MAAMA,2BAA2BC;IACpC,YACYC,gBAAmC,EACnCC,KAAuB,EAC/BC,2BAA0D,CAC5D;QACE,KAAK,CAAC;YACF,UAAU;YACV,sBAAsBA;QAC1B,SAPQF,gBAAgB,GAAhBA,kBAAAA,IAAAA,CACAC,KAAK,GAALA;IAOZ;IAEA,IAAI,OAAe;QACf,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;IACvD;IAEA,MAAM,MAAME,MAAmB,EAA8B;QACzD,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YACjC,OAAOA,OAAO,KAAK;YACnB,MAAMA,OAAO,IAAI;YACjB,QAAQA,OAAO,MAAM;YACrB,OAAOA,OAAO,KAAK;YACnB,OAAOA,OAAO,KAAK;QACvB;IACJ;AACJ"}
1
+ {"version":3,"file":"presentation/pages/PageList/PageListDataSource.js","sources":["../../../../src/presentation/pages/PageList/PageListDataSource.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 { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { Page } from \"~/domain/Page/Page.js\";\nimport type { IListPagesUseCase } from \"~/features/pages/listPages/abstractions.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\n\nexport class PageListDataSource extends FolderAwareDataSource<Page> {\n constructor(\n private listPagesUseCase: IListPagesUseCase,\n private cache: IListCache<Page>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase\n ) {\n super({\n keyField: \"entryId\",\n getDescendantFolders: getDescendantFoldersUseCase\n });\n }\n\n get rows(): Page[] {\n return this.queryMatcher.select(this.cache.getItems());\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<Page>> {\n return this.listPagesUseCase.execute({\n where: params.where,\n sort: params.sort,\n search: params.search,\n limit: params.limit,\n after: params.after\n });\n }\n}\n"],"names":["PageListDataSource","FolderAwareDataSource","listPagesUseCase","cache","getDescendantFoldersUseCase","params"],"mappings":";AAUO,MAAMA,2BAA2BC;IACpC,YACYC,gBAAmC,EACnCC,KAAuB,EAC/BC,2BAA0D,CAC5D;QACE,KAAK,CAAC;YACF,UAAU;YACV,sBAAsBA;QAC1B,SAPQF,gBAAgB,GAAhBA,kBAAAA,IAAAA,CACAC,KAAK,GAALA;IAOZ;IAEA,IAAI,OAAe;QACf,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;IACvD;IAEA,MAAM,MAAME,MAAmB,EAA8B;QACzD,OAAO,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YACjC,OAAOA,OAAO,KAAK;YACnB,MAAMA,OAAO,IAAI;YACjB,QAAQA,OAAO,MAAM;YACrB,OAAOA,OAAO,KAAK;YACnB,OAAOA,OAAO,KAAK;QACvB;IACJ;AACJ"}
@@ -0,0 +1,293 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import { observable } from "mobx";
3
+ import { Container } from "@webiny/di";
4
+ import { ListCache } from "@webiny/app-admin/features/listCache/index.js";
5
+ import { ListPresenter } from "@webiny/app-admin/presentation/listPresenter/ListPresenter.js";
6
+ import { FolderTreePresenter } from "@webiny/app-aco/presentation/folderTree/abstractions.js";
7
+ import { GetDescendantFoldersUseCase } from "@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js";
8
+ import { Confirmation } from "@webiny/app-admin/features/confirmation/abstractions.js";
9
+ import { Page } from "../../../domain/Page/Page.js";
10
+ import { pageRevisionsCacheFactory } from "../../../domain/PageRevision/index.js";
11
+ import { ListPagesGateway } from "../../../features/pages/listPages/abstractions.js";
12
+ import { ListPagesUseCase } from "../../../features/pages/listPages/ListPagesUseCase.js";
13
+ import { ListPagesRepository } from "../../../features/pages/listPages/ListPagesRepository.js";
14
+ import { FullPageCache, PageListCache, PageRevisionsCache } from "../../../features/pages/shared/abstractions.js";
15
+ import { PublishPageGateway } from "../../../features/pages/publishPage/abstractions.js";
16
+ import { PublishPageUseCase } from "../../../features/pages/publishPage/PublishPageUseCase.js";
17
+ import { PublishPageRepository } from "../../../features/pages/publishPage/PublishPageRepository.js";
18
+ import { DeletePageUseCase } from "../../../features/pages/deletePage/abstractions.js";
19
+ import { UnpublishPageUseCase } from "../../../features/pages/unpublishPage/abstractions.js";
20
+ import { MovePageUseCase } from "../../../features/pages/movePage/abstractions.js";
21
+ import { DuplicatePageUseCase } from "../../../features/pages/duplicatePage/abstractions.js";
22
+ import { PageListPresenter } from "./abstractions.js";
23
+ import { PageListPresenter as external_PageListPresenter_js_PageListPresenter } from "./PageListPresenter.js";
24
+ const TOTAL_PAGES = 300;
25
+ const PAGE_SIZE = 50;
26
+ const BASE_TIME = Date.UTC(2026, 0, 1);
27
+ const minutes = (n)=>new Date(BASE_TIME + 60000 * n).toISOString();
28
+ function createPages(count) {
29
+ return Array.from({
30
+ length: count
31
+ }, (_, i)=>Page.create({
32
+ id: `page-${i}#0001`,
33
+ entryId: `page-${i}`,
34
+ location: {
35
+ folderId: "root"
36
+ },
37
+ properties: {
38
+ title: `Page ${i}`
39
+ },
40
+ createdOn: minutes(count - i),
41
+ savedOn: minutes(i)
42
+ }));
43
+ }
44
+ function createGateway(pages) {
45
+ return {
46
+ execute: vi.fn(async (params)=>{
47
+ const [sort = "savedOn_DESC"] = params.sort ?? [];
48
+ const [field, direction] = sort.split("_");
49
+ const multiplier = "ASC" === direction ? 1 : -1;
50
+ const folderId = params.where?.location?.folderId;
51
+ const sorted = pages.filter((page)=>!folderId || page.location.folderId === folderId).sort((a, b)=>multiplier * String(a[field]).localeCompare(String(b[field])));
52
+ const offset = params.after ? Number(params.after) : 0;
53
+ const limit = params.limit ?? PAGE_SIZE;
54
+ const data = sorted.slice(offset, offset + limit);
55
+ const next = offset + data.length;
56
+ const hasMoreItems = next < sorted.length;
57
+ return {
58
+ data,
59
+ meta: {
60
+ cursor: hasMoreItems ? String(next) : null,
61
+ hasMoreItems,
62
+ totalCount: sorted.length
63
+ }
64
+ };
65
+ })
66
+ };
67
+ }
68
+ function createFolderTreePresenter() {
69
+ const vm = observable({
70
+ folders: [],
71
+ tree: [],
72
+ currentFolderId: null,
73
+ currentFolder: null,
74
+ loading: false,
75
+ operation: {
76
+ active: false,
77
+ mode: null
78
+ },
79
+ isRootFolder: true,
80
+ currentFolderTitle: "All pages",
81
+ childFolders: [],
82
+ loadingNodeIds: []
83
+ });
84
+ return {
85
+ get vm () {
86
+ return vm;
87
+ },
88
+ selectFolder: vi.fn(),
89
+ createFolder: vi.fn(),
90
+ editFolder: vi.fn(),
91
+ deleteFolder: vi.fn().mockResolvedValue(void 0),
92
+ moveFolder: vi.fn().mockResolvedValue(void 0),
93
+ loadChildFolders: vi.fn().mockResolvedValue(void 0),
94
+ canManageStructure: vi.fn().mockReturnValue(true),
95
+ getAncestorIds: vi.fn().mockReturnValue([]),
96
+ submitOperation: vi.fn().mockResolvedValue(true),
97
+ cancelOperation: vi.fn(),
98
+ onFolderChange: vi.fn().mockReturnValue(()=>{})
99
+ };
100
+ }
101
+ const noopUseCase = {
102
+ execute: vi.fn()
103
+ };
104
+ function range(from, to) {
105
+ const step = from <= to ? 1 : -1;
106
+ const ids = [];
107
+ for(let i = from; step > 0 ? i <= to : i >= to; i += step)ids.push(`page-${i}`);
108
+ return ids;
109
+ }
110
+ describe("PageListPresenter", ()=>{
111
+ let presenter;
112
+ let cache;
113
+ const publishGateway = {
114
+ execute: vi.fn(async (id)=>{
115
+ const page = cache.getItem((p)=>p.id === id);
116
+ return {
117
+ ...page,
118
+ status: "published"
119
+ };
120
+ })
121
+ };
122
+ const rowIds = ()=>presenter.list.vm.rows.map((row)=>row.entryId);
123
+ const waitForQuery = async (field, direction)=>{
124
+ await vi.waitFor(()=>{
125
+ const sort = presenter.list.vm.appliedQuery?.sort;
126
+ expect(sort).toEqual({
127
+ field,
128
+ direction
129
+ });
130
+ expect(presenter.list.vm.pagination.loading).toBe(false);
131
+ });
132
+ };
133
+ const initAndWait = async ()=>{
134
+ presenter.init();
135
+ await waitForQuery("savedOn", "DESC");
136
+ };
137
+ const loadAll = async ()=>{
138
+ while(presenter.list.vm.pagination.hasMore)await presenter.list.actions.loadMore();
139
+ };
140
+ beforeEach(()=>{
141
+ const container = new Container();
142
+ cache = new ListCache("entryId");
143
+ container.registerInstance(PageListCache, cache);
144
+ container.registerInstance(ListPagesGateway, createGateway(createPages(TOTAL_PAGES)));
145
+ container.register(ListPagesRepository).inSingletonScope();
146
+ container.register(ListPagesUseCase);
147
+ container.register(ListPresenter);
148
+ container.registerInstance(FolderTreePresenter, createFolderTreePresenter());
149
+ container.registerInstance(Confirmation, {
150
+ confirm: vi.fn()
151
+ });
152
+ container.registerInstance(GetDescendantFoldersUseCase, {
153
+ execute: ()=>[]
154
+ });
155
+ container.registerInstance(DeletePageUseCase, noopUseCase);
156
+ container.registerInstance(FullPageCache, new ListCache("id"));
157
+ container.registerInstance(PageRevisionsCache, pageRevisionsCacheFactory.getCache());
158
+ container.registerInstance(PublishPageGateway, publishGateway);
159
+ container.register(PublishPageRepository).inSingletonScope();
160
+ container.register(PublishPageUseCase);
161
+ container.registerInstance(UnpublishPageUseCase, noopUseCase);
162
+ container.registerInstance(MovePageUseCase, noopUseCase);
163
+ container.registerInstance(DuplicatePageUseCase, noopUseCase);
164
+ container.register(external_PageListPresenter_js_PageListPresenter);
165
+ presenter = container.resolve(PageListPresenter);
166
+ });
167
+ describe("pagination", ()=>{
168
+ it("should show the most recently saved pages first", async ()=>{
169
+ await initAndWait();
170
+ expect(rowIds()).toEqual(range(299, 250));
171
+ });
172
+ it("should append the next batch of pages to the bottom of the list", async ()=>{
173
+ await initAndWait();
174
+ await presenter.list.actions.loadMore();
175
+ expect(rowIds()).toEqual(range(299, 200));
176
+ });
177
+ it("should keep all pages in order after loading everything", async ()=>{
178
+ await initAndWait();
179
+ await loadAll();
180
+ expect(rowIds()).toEqual(range(299, 0));
181
+ });
182
+ });
183
+ describe("changing the sort", ()=>{
184
+ it("should show only the first batch, in the new direction", async ()=>{
185
+ await initAndWait();
186
+ presenter.list.actions.sort.set("savedOn", "ASC");
187
+ await waitForQuery("savedOn", "ASC");
188
+ expect(rowIds()).toEqual(range(0, 49));
189
+ });
190
+ it("should show only the first batch, sorted by the new field", async ()=>{
191
+ await initAndWait();
192
+ presenter.list.actions.sort.set("createdOn", "DESC");
193
+ await waitForQuery("createdOn", "DESC");
194
+ expect(rowIds()).toEqual(range(0, 49));
195
+ });
196
+ it("should paginate in the new order", async ()=>{
197
+ await initAndWait();
198
+ presenter.list.actions.sort.set("savedOn", "ASC");
199
+ await waitForQuery("savedOn", "ASC");
200
+ await presenter.list.actions.loadMore();
201
+ expect(rowIds()).toEqual(range(0, 99));
202
+ });
203
+ it("should restore the original order when switching back", async ()=>{
204
+ await initAndWait();
205
+ await presenter.list.actions.loadMore();
206
+ presenter.list.actions.sort.set("savedOn", "ASC");
207
+ await waitForQuery("savedOn", "ASC");
208
+ presenter.list.actions.sort.set("savedOn", "DESC");
209
+ await waitForQuery("savedOn", "DESC");
210
+ expect(rowIds()).toEqual(range(299, 250));
211
+ });
212
+ });
213
+ describe("local cache changes", ()=>{
214
+ const newPage = ()=>Page.create({
215
+ id: "page-new#0001",
216
+ entryId: "page-new",
217
+ location: {
218
+ folderId: "root"
219
+ },
220
+ properties: {
221
+ title: "New page"
222
+ },
223
+ createdOn: minutes(TOTAL_PAGES + 1),
224
+ savedOn: minutes(TOTAL_PAGES + 1)
225
+ });
226
+ it("should show a created page at the top when it sorts first", async ()=>{
227
+ await initAndWait();
228
+ cache.addItems([
229
+ newPage()
230
+ ]);
231
+ expect(rowIds()).toEqual([
232
+ "page-new",
233
+ ...range(299, 250)
234
+ ]);
235
+ });
236
+ it("should not show a created page that sorts past the loaded pages", async ()=>{
237
+ await initAndWait();
238
+ presenter.list.actions.sort.set("savedOn", "ASC");
239
+ await waitForQuery("savedOn", "ASC");
240
+ cache.addItems([
241
+ newPage()
242
+ ]);
243
+ expect(rowIds()).toEqual(range(0, 49));
244
+ });
245
+ it("should show a created page in its sort position once everything is loaded", async ()=>{
246
+ await initAndWait();
247
+ presenter.list.actions.sort.set("savedOn", "ASC");
248
+ await waitForQuery("savedOn", "ASC");
249
+ await loadAll();
250
+ cache.addItems([
251
+ newPage()
252
+ ]);
253
+ expect(rowIds()).toEqual([
254
+ ...range(0, 299),
255
+ "page-new"
256
+ ]);
257
+ });
258
+ it("should move an updated page to its new sort position", async ()=>{
259
+ await initAndWait();
260
+ const page = cache.getItem((p)=>"page-260" === p.entryId);
261
+ cache.addItems([
262
+ Page.create({
263
+ ...page,
264
+ savedOn: minutes(TOTAL_PAGES + 1)
265
+ })
266
+ ]);
267
+ expect(rowIds()).toEqual([
268
+ "page-260",
269
+ ...range(299, 261),
270
+ ...range(259, 250)
271
+ ]);
272
+ });
273
+ });
274
+ describe("publishing", ()=>{
275
+ it("should keep a published page in its position", async ()=>{
276
+ await initAndWait();
277
+ const before = rowIds();
278
+ await presenter.publishPage("page-260#0001");
279
+ expect(rowIds()).toEqual(before);
280
+ const published = presenter.list.vm.rows.find((row)=>"page-260" === row.entryId);
281
+ expect(published?.status).toBe("published");
282
+ });
283
+ it("should keep a published page in its position after loading more pages", async ()=>{
284
+ await initAndWait();
285
+ await presenter.list.actions.loadMore();
286
+ const before = rowIds();
287
+ await presenter.publishPage("page-210#0001");
288
+ expect(rowIds()).toEqual(before);
289
+ });
290
+ });
291
+ });
292
+
293
+ //# sourceMappingURL=PageListPresenter.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/pages/PageList/PageListPresenter.test.js","sources":["../../../../src/presentation/pages/PageList/PageListPresenter.test.ts"],"sourcesContent":["import { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { observable } from \"mobx\";\nimport { Container } from \"@webiny/di\";\nimport { ListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/ListPresenter.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 { Page } from \"~/domain/Page/Page.js\";\nimport { pageRevisionsCacheFactory } from \"~/domain/PageRevision/index.js\";\nimport {\n ListPagesGateway,\n type IListPagesGatewayParams,\n type IListPagesGatewayResult\n} from \"~/features/pages/listPages/abstractions.js\";\nimport { ListPagesUseCase } from \"~/features/pages/listPages/ListPagesUseCase.js\";\nimport { ListPagesRepository } from \"~/features/pages/listPages/ListPagesRepository.js\";\nimport {\n FullPageCache,\n PageListCache,\n PageRevisionsCache\n} from \"~/features/pages/shared/abstractions.js\";\nimport { PublishPageGateway } from \"~/features/pages/publishPage/abstractions.js\";\nimport { PublishPageUseCase as PublishPageUseCaseImpl } from \"~/features/pages/publishPage/PublishPageUseCase.js\";\nimport { PublishPageRepository } from \"~/features/pages/publishPage/PublishPageRepository.js\";\nimport { DeletePageUseCase } from \"~/features/pages/deletePage/abstractions.js\";\nimport { UnpublishPageUseCase } from \"~/features/pages/unpublishPage/abstractions.js\";\nimport { MovePageUseCase } from \"~/features/pages/movePage/abstractions.js\";\nimport { DuplicatePageUseCase } from \"~/features/pages/duplicatePage/abstractions.js\";\nimport { PageListPresenter as Abstraction } from \"./abstractions.js\";\nimport { PageListPresenter } from \"./PageListPresenter.js\";\n\nconst TOTAL_PAGES = 300;\nconst PAGE_SIZE = 50;\nconst BASE_TIME = Date.UTC(2026, 0, 1);\n\nconst minutes = (n: number) => new Date(BASE_TIME + n * 60_000).toISOString();\n\n/**\n * A higher index means a more recently *saved* page, but a less recently *created* one,\n * so sorting by `savedOn` and by `createdOn` produce opposite orders.\n */\nfunction createPages(count: number): Page[] {\n return Array.from({ length: count }, (_, i) =>\n Page.create({\n id: `page-${i}#0001`,\n entryId: `page-${i}`,\n location: { folderId: \"root\" },\n properties: { title: `Page ${i}` },\n createdOn: minutes(count - i),\n savedOn: minutes(i)\n })\n );\n}\n\n/**\n * Simulates the API: filters by folder, sorts by the requested field, and paginates\n * with an offset-based cursor.\n */\nfunction createGateway(pages: Page[]): ListPagesGateway.Interface {\n return {\n execute: vi.fn(\n async (params: IListPagesGatewayParams): Promise<IListPagesGatewayResult> => {\n const [sort = \"savedOn_DESC\"] = params.sort ?? [];\n const [field, direction] = sort.split(\"_\") as [keyof Page, \"ASC\" | \"DESC\"];\n const multiplier = direction === \"ASC\" ? 1 : -1;\n\n const folderId = (params.where?.location as { folderId?: string })?.folderId;\n const sorted = pages\n .filter(page => !folderId || page.location.folderId === folderId)\n .sort((a, b) => multiplier * String(a[field]).localeCompare(String(b[field])));\n\n const offset = params.after ? Number(params.after) : 0;\n const limit = params.limit ?? PAGE_SIZE;\n const data = sorted.slice(offset, offset + limit);\n const next = offset + data.length;\n const hasMoreItems = next < sorted.length;\n\n return {\n data,\n meta: {\n cursor: hasMoreItems ? String(next) : null,\n hasMoreItems,\n totalCount: sorted.length\n }\n };\n }\n )\n };\n}\n\nfunction createFolderTreePresenter(): FolderTreePresenter.Interface {\n const vm = observable({\n folders: [],\n tree: [],\n currentFolderId: null as string | null,\n currentFolder: null,\n loading: false,\n operation: { active: false, mode: null },\n isRootFolder: true,\n currentFolderTitle: \"All pages\",\n childFolders: [],\n loadingNodeIds: []\n });\n\n return {\n get vm() {\n return vm as unknown as FolderTreePresenter.Interface[\"vm\"];\n },\n selectFolder: vi.fn(),\n createFolder: vi.fn(),\n editFolder: vi.fn(),\n deleteFolder: vi.fn().mockResolvedValue(undefined),\n moveFolder: vi.fn().mockResolvedValue(undefined),\n loadChildFolders: vi.fn().mockResolvedValue(undefined),\n canManageStructure: vi.fn().mockReturnValue(true),\n getAncestorIds: vi.fn().mockReturnValue([]),\n submitOperation: vi.fn().mockResolvedValue(true),\n cancelOperation: vi.fn(),\n onFolderChange: vi.fn().mockReturnValue(() => {})\n };\n}\n\nconst noopUseCase = { execute: vi.fn() };\n\n/**\n * Expected entry IDs for a contiguous range of page indexes, in the given order.\n */\nfunction range(from: number, to: number): string[] {\n const step = from <= to ? 1 : -1;\n const ids: string[] = [];\n for (let i = from; step > 0 ? i <= to : i >= to; i += step) {\n ids.push(`page-${i}`);\n }\n return ids;\n}\n\ndescribe(\"PageListPresenter\", () => {\n let presenter: Abstraction.Interface;\n let cache: ListCache<Page>;\n\n /**\n * Simulates the publish API: publishing is not a content modification, so the page\n * comes back with its `savedOn` unchanged.\n */\n const publishGateway: PublishPageGateway.Interface = {\n execute: vi.fn(async (id: string) => {\n const page = cache.getItem(p => p.id === id)!;\n return { ...page, status: \"published\" } as any;\n })\n };\n\n const rowIds = () => presenter.list.vm.rows.map(row => row.entryId);\n\n const waitForQuery = async (field: string, direction: \"ASC\" | \"DESC\") => {\n await vi.waitFor(() => {\n const sort = presenter.list.vm.appliedQuery?.sort;\n expect(sort).toEqual({ field, direction });\n expect(presenter.list.vm.pagination.loading).toBe(false);\n });\n };\n\n const initAndWait = async () => {\n presenter.init();\n await waitForQuery(\"savedOn\", \"DESC\");\n };\n\n const loadAll = async () => {\n while (presenter.list.vm.pagination.hasMore) {\n await presenter.list.actions.loadMore();\n }\n };\n\n beforeEach(() => {\n const container = new Container();\n\n cache = new ListCache<Page>(\"entryId\");\n container.registerInstance(PageListCache, cache);\n container.registerInstance(ListPagesGateway, createGateway(createPages(TOTAL_PAGES)));\n container.register(ListPagesRepository).inSingletonScope();\n container.register(ListPagesUseCase);\n\n container.register(ListPresenter);\n container.registerInstance(FolderTreePresenter, createFolderTreePresenter());\n container.registerInstance(Confirmation, { confirm: vi.fn() } as Confirmation.Interface);\n container.registerInstance(GetDescendantFoldersUseCase, { execute: () => [] });\n container.registerInstance(DeletePageUseCase, noopUseCase as any);\n container.registerInstance(FullPageCache, new ListCache<Page>(\"id\"));\n container.registerInstance(PageRevisionsCache, pageRevisionsCacheFactory.getCache());\n container.registerInstance(PublishPageGateway, publishGateway);\n container.register(PublishPageRepository).inSingletonScope();\n container.register(PublishPageUseCaseImpl);\n container.registerInstance(UnpublishPageUseCase, noopUseCase as any);\n container.registerInstance(MovePageUseCase, noopUseCase as any);\n container.registerInstance(DuplicatePageUseCase, noopUseCase as any);\n\n container.register(PageListPresenter);\n\n presenter = container.resolve(Abstraction);\n });\n\n describe(\"pagination\", () => {\n it(\"should show the most recently saved pages first\", async () => {\n await initAndWait();\n\n expect(rowIds()).toEqual(range(299, 250));\n });\n\n it(\"should append the next batch of pages to the bottom of the list\", async () => {\n await initAndWait();\n\n await presenter.list.actions.loadMore();\n\n expect(rowIds()).toEqual(range(299, 200));\n });\n\n it(\"should keep all pages in order after loading everything\", async () => {\n await initAndWait();\n\n await loadAll();\n\n expect(rowIds()).toEqual(range(299, 0));\n });\n });\n\n describe(\"changing the sort\", () => {\n it(\"should show only the first batch, in the new direction\", async () => {\n await initAndWait();\n\n presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await waitForQuery(\"savedOn\", \"ASC\");\n\n expect(rowIds()).toEqual(range(0, 49));\n });\n\n it(\"should show only the first batch, sorted by the new field\", async () => {\n await initAndWait();\n\n presenter.list.actions.sort.set(\"createdOn\", \"DESC\");\n await waitForQuery(\"createdOn\", \"DESC\");\n\n // `createdOn` runs opposite to `savedOn`, so the newest created page is page-0.\n expect(rowIds()).toEqual(range(0, 49));\n });\n\n it(\"should paginate in the new order\", async () => {\n await initAndWait();\n\n presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await waitForQuery(\"savedOn\", \"ASC\");\n await presenter.list.actions.loadMore();\n\n expect(rowIds()).toEqual(range(0, 99));\n });\n\n it(\"should restore the original order when switching back\", async () => {\n await initAndWait();\n await presenter.list.actions.loadMore();\n\n presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await waitForQuery(\"savedOn\", \"ASC\");\n\n presenter.list.actions.sort.set(\"savedOn\", \"DESC\");\n await waitForQuery(\"savedOn\", \"DESC\");\n\n expect(rowIds()).toEqual(range(299, 250));\n });\n });\n\n describe(\"local cache changes\", () => {\n const newPage = () =>\n Page.create({\n id: \"page-new#0001\",\n entryId: \"page-new\",\n location: { folderId: \"root\" },\n properties: { title: \"New page\" },\n createdOn: minutes(TOTAL_PAGES + 1),\n savedOn: minutes(TOTAL_PAGES + 1)\n });\n\n it(\"should show a created page at the top when it sorts first\", async () => {\n await initAndWait();\n\n cache.addItems([newPage()]);\n\n expect(rowIds()).toEqual([\"page-new\", ...range(299, 250)]);\n });\n\n it(\"should not show a created page that sorts past the loaded pages\", async () => {\n await initAndWait();\n presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await waitForQuery(\"savedOn\", \"ASC\");\n\n cache.addItems([newPage()]);\n\n // The new page is the most recently saved, so in ASC order it belongs at the very\n // end, after 250 pages that are not loaded yet.\n expect(rowIds()).toEqual(range(0, 49));\n });\n\n it(\"should show a created page in its sort position once everything is loaded\", async () => {\n await initAndWait();\n presenter.list.actions.sort.set(\"savedOn\", \"ASC\");\n await waitForQuery(\"savedOn\", \"ASC\");\n await loadAll();\n\n cache.addItems([newPage()]);\n\n expect(rowIds()).toEqual([...range(0, 299), \"page-new\"]);\n });\n\n it(\"should move an updated page to its new sort position\", async () => {\n await initAndWait();\n\n const page = cache.getItem(p => p.entryId === \"page-260\")!;\n cache.addItems([Page.create({ ...page, savedOn: minutes(TOTAL_PAGES + 1) })]);\n\n expect(rowIds()).toEqual([\"page-260\", ...range(299, 261), ...range(259, 250)]);\n });\n });\n\n describe(\"publishing\", () => {\n it(\"should keep a published page in its position\", async () => {\n await initAndWait();\n const before = rowIds();\n\n await presenter.publishPage(\"page-260#0001\");\n\n expect(rowIds()).toEqual(before);\n const published = presenter.list.vm.rows.find(row => row.entryId === \"page-260\");\n expect(published?.status).toBe(\"published\");\n });\n\n it(\"should keep a published page in its position after loading more pages\", async () => {\n await initAndWait();\n await presenter.list.actions.loadMore();\n const before = rowIds();\n\n await presenter.publishPage(\"page-210#0001\");\n\n expect(rowIds()).toEqual(before);\n });\n });\n});\n"],"names":["TOTAL_PAGES","PAGE_SIZE","BASE_TIME","Date","minutes","n","createPages","count","Array","_","i","Page","createGateway","pages","vi","params","sort","field","direction","multiplier","folderId","sorted","page","a","b","String","offset","Number","limit","data","next","hasMoreItems","createFolderTreePresenter","vm","observable","undefined","noopUseCase","range","from","to","step","ids","describe","presenter","cache","publishGateway","id","p","rowIds","row","waitForQuery","expect","initAndWait","loadAll","beforeEach","container","Container","ListCache","PageListCache","ListPagesGateway","ListPagesRepository","ListPagesUseCase","ListPresenter","FolderTreePresenter","Confirmation","GetDescendantFoldersUseCase","DeletePageUseCase","FullPageCache","PageRevisionsCache","pageRevisionsCacheFactory","PublishPageGateway","PublishPageRepository","PublishPageUseCaseImpl","UnpublishPageUseCase","MovePageUseCase","DuplicatePageUseCase","PageListPresenter","Abstraction","it","newPage","before","published"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAgCA,MAAMA,cAAc;AACpB,MAAMC,YAAY;AAClB,MAAMC,YAAYC,KAAK,GAAG,CAAC,MAAM,GAAG;AAEpC,MAAMC,UAAU,CAACC,IAAc,IAAIF,KAAKD,YAAYG,AAAI,QAAJA,GAAY,WAAW;AAM3E,SAASC,YAAYC,KAAa;IAC9B,OAAOC,MAAM,IAAI,CAAC;QAAE,QAAQD;IAAM,GAAG,CAACE,GAAGC,IACrCC,KAAK,MAAM,CAAC;YACR,IAAI,CAAC,KAAK,EAAED,EAAE,KAAK,CAAC;YACpB,SAAS,CAAC,KAAK,EAAEA,GAAG;YACpB,UAAU;gBAAE,UAAU;YAAO;YAC7B,YAAY;gBAAE,OAAO,CAAC,KAAK,EAAEA,GAAG;YAAC;YACjC,WAAWN,QAAQG,QAAQG;YAC3B,SAASN,QAAQM;QACrB;AAER;AAMA,SAASE,cAAcC,KAAa;IAChC,OAAO;QACH,SAASC,GAAG,EAAE,CACV,OAAOC;YACH,MAAM,CAACC,OAAO,cAAc,CAAC,GAAGD,OAAO,IAAI,IAAI,EAAE;YACjD,MAAM,CAACE,OAAOC,UAAU,GAAGF,KAAK,KAAK,CAAC;YACtC,MAAMG,aAAaD,AAAc,UAAdA,YAAsB,IAAI;YAE7C,MAAME,WAAYL,OAAO,KAAK,EAAE,UAAoC;YACpE,MAAMM,SAASR,MACV,MAAM,CAACS,CAAAA,OAAQ,CAACF,YAAYE,KAAK,QAAQ,CAAC,QAAQ,KAAKF,UACvD,IAAI,CAAC,CAACG,GAAGC,IAAML,aAAaM,OAAOF,CAAC,CAACN,MAAM,EAAE,aAAa,CAACQ,OAAOD,CAAC,CAACP,MAAM;YAE/E,MAAMS,SAASX,OAAO,KAAK,GAAGY,OAAOZ,OAAO,KAAK,IAAI;YACrD,MAAMa,QAAQb,OAAO,KAAK,IAAId;YAC9B,MAAM4B,OAAOR,OAAO,KAAK,CAACK,QAAQA,SAASE;YAC3C,MAAME,OAAOJ,SAASG,KAAK,MAAM;YACjC,MAAME,eAAeD,OAAOT,OAAO,MAAM;YAEzC,OAAO;gBACHQ;gBACA,MAAM;oBACF,QAAQE,eAAeN,OAAOK,QAAQ;oBACtCC;oBACA,YAAYV,OAAO,MAAM;gBAC7B;YACJ;QACJ;IAER;AACJ;AAEA,SAASW;IACL,MAAMC,KAAKC,WAAW;QAClB,SAAS,EAAE;QACX,MAAM,EAAE;QACR,iBAAiB;QACjB,eAAe;QACf,SAAS;QACT,WAAW;YAAE,QAAQ;YAAO,MAAM;QAAK;QACvC,cAAc;QACd,oBAAoB;QACpB,cAAc,EAAE;QAChB,gBAAgB,EAAE;IACtB;IAEA,OAAO;QACH,IAAI;YACA,OAAOD;QACX;QACA,cAAcnB,GAAG,EAAE;QACnB,cAAcA,GAAG,EAAE;QACnB,YAAYA,GAAG,EAAE;QACjB,cAAcA,GAAG,EAAE,GAAG,iBAAiB,CAACqB;QACxC,YAAYrB,GAAG,EAAE,GAAG,iBAAiB,CAACqB;QACtC,kBAAkBrB,GAAG,EAAE,GAAG,iBAAiB,CAACqB;QAC5C,oBAAoBrB,GAAG,EAAE,GAAG,eAAe,CAAC;QAC5C,gBAAgBA,GAAG,EAAE,GAAG,eAAe,CAAC,EAAE;QAC1C,iBAAiBA,GAAG,EAAE,GAAG,iBAAiB,CAAC;QAC3C,iBAAiBA,GAAG,EAAE;QACtB,gBAAgBA,GAAG,EAAE,GAAG,eAAe,CAAC,KAAO;IACnD;AACJ;AAEA,MAAMsB,cAAc;IAAE,SAAStB,GAAG,EAAE;AAAG;AAKvC,SAASuB,MAAMC,IAAY,EAAEC,EAAU;IACnC,MAAMC,OAAOF,QAAQC,KAAK,IAAI;IAC9B,MAAME,MAAgB,EAAE;IACxB,IAAK,IAAI/B,IAAI4B,MAAME,OAAO,IAAI9B,KAAK6B,KAAK7B,KAAK6B,IAAI7B,KAAK8B,KAClDC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE/B,GAAG;IAExB,OAAO+B;AACX;AAEAC,SAAS,qBAAqB;IAC1B,IAAIC;IACJ,IAAIC;IAMJ,MAAMC,iBAA+C;QACjD,SAAS/B,GAAG,EAAE,CAAC,OAAOgC;YAClB,MAAMxB,OAAOsB,MAAM,OAAO,CAACG,CAAAA,IAAKA,EAAE,EAAE,KAAKD;YACzC,OAAO;gBAAE,GAAGxB,IAAI;gBAAE,QAAQ;YAAY;QAC1C;IACJ;IAEA,MAAM0B,SAAS,IAAML,UAAU,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAACM,CAAAA,MAAOA,IAAI,OAAO;IAElE,MAAMC,eAAe,OAAOjC,OAAeC;QACvC,MAAMJ,GAAG,OAAO,CAAC;YACb,MAAME,OAAO2B,UAAU,IAAI,CAAC,EAAE,CAAC,YAAY,EAAE;YAC7CQ,OAAOnC,MAAM,OAAO,CAAC;gBAAEC;gBAAOC;YAAU;YACxCiC,OAAOR,UAAU,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC;QACtD;IACJ;IAEA,MAAMS,cAAc;QAChBT,UAAU,IAAI;QACd,MAAMO,aAAa,WAAW;IAClC;IAEA,MAAMG,UAAU;QACZ,MAAOV,UAAU,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CACvC,MAAMA,UAAU,IAAI,CAAC,OAAO,CAAC,QAAQ;IAE7C;IAEAW,WAAW;QACP,MAAMC,YAAY,IAAIC;QAEtBZ,QAAQ,IAAIa,UAAgB;QAC5BF,UAAU,gBAAgB,CAACG,eAAed;QAC1CW,UAAU,gBAAgB,CAACI,kBAAkB/C,cAAcN,YAAYN;QACvEuD,UAAU,QAAQ,CAACK,qBAAqB,gBAAgB;QACxDL,UAAU,QAAQ,CAACM;QAEnBN,UAAU,QAAQ,CAACO;QACnBP,UAAU,gBAAgB,CAACQ,qBAAqB/B;QAChDuB,UAAU,gBAAgB,CAACS,cAAc;YAAE,SAASlD,GAAG,EAAE;QAAG;QAC5DyC,UAAU,gBAAgB,CAACU,6BAA6B;YAAE,SAAS,IAAM,EAAE;QAAC;QAC5EV,UAAU,gBAAgB,CAACW,mBAAmB9B;QAC9CmB,UAAU,gBAAgB,CAACY,eAAe,IAAIV,UAAgB;QAC9DF,UAAU,gBAAgB,CAACa,oBAAoBC,0BAA0B,QAAQ;QACjFd,UAAU,gBAAgB,CAACe,oBAAoBzB;QAC/CU,UAAU,QAAQ,CAACgB,uBAAuB,gBAAgB;QAC1DhB,UAAU,QAAQ,CAACiB;QACnBjB,UAAU,gBAAgB,CAACkB,sBAAsBrC;QACjDmB,UAAU,gBAAgB,CAACmB,iBAAiBtC;QAC5CmB,UAAU,gBAAgB,CAACoB,sBAAsBvC;QAEjDmB,UAAU,QAAQ,CAACqB;QAEnBjC,YAAYY,UAAU,OAAO,CAACsB;IAClC;IAEAnC,SAAS,cAAc;QACnBoC,GAAG,mDAAmD;YAClD,MAAM1B;YAEND,OAAOH,UAAU,OAAO,CAACX,MAAM,KAAK;QACxC;QAEAyC,GAAG,mEAAmE;YAClE,MAAM1B;YAEN,MAAMT,UAAU,IAAI,CAAC,OAAO,CAAC,QAAQ;YAErCQ,OAAOH,UAAU,OAAO,CAACX,MAAM,KAAK;QACxC;QAEAyC,GAAG,2DAA2D;YAC1D,MAAM1B;YAEN,MAAMC;YAENF,OAAOH,UAAU,OAAO,CAACX,MAAM,KAAK;QACxC;IACJ;IAEAK,SAAS,qBAAqB;QAC1BoC,GAAG,0DAA0D;YACzD,MAAM1B;YAENT,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;YAC3C,MAAMO,aAAa,WAAW;YAE9BC,OAAOH,UAAU,OAAO,CAACX,MAAM,GAAG;QACtC;QAEAyC,GAAG,6DAA6D;YAC5D,MAAM1B;YAENT,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa;YAC7C,MAAMO,aAAa,aAAa;YAGhCC,OAAOH,UAAU,OAAO,CAACX,MAAM,GAAG;QACtC;QAEAyC,GAAG,oCAAoC;YACnC,MAAM1B;YAENT,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;YAC3C,MAAMO,aAAa,WAAW;YAC9B,MAAMP,UAAU,IAAI,CAAC,OAAO,CAAC,QAAQ;YAErCQ,OAAOH,UAAU,OAAO,CAACX,MAAM,GAAG;QACtC;QAEAyC,GAAG,yDAAyD;YACxD,MAAM1B;YACN,MAAMT,UAAU,IAAI,CAAC,OAAO,CAAC,QAAQ;YAErCA,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;YAC3C,MAAMO,aAAa,WAAW;YAE9BP,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;YAC3C,MAAMO,aAAa,WAAW;YAE9BC,OAAOH,UAAU,OAAO,CAACX,MAAM,KAAK;QACxC;IACJ;IAEAK,SAAS,uBAAuB;QAC5B,MAAMqC,UAAU,IACZpE,KAAK,MAAM,CAAC;gBACR,IAAI;gBACJ,SAAS;gBACT,UAAU;oBAAE,UAAU;gBAAO;gBAC7B,YAAY;oBAAE,OAAO;gBAAW;gBAChC,WAAWP,QAAQJ,cAAc;gBACjC,SAASI,QAAQJ,cAAc;YACnC;QAEJ8E,GAAG,6DAA6D;YAC5D,MAAM1B;YAENR,MAAM,QAAQ,CAAC;gBAACmC;aAAU;YAE1B5B,OAAOH,UAAU,OAAO,CAAC;gBAAC;mBAAeX,MAAM,KAAK;aAAK;QAC7D;QAEAyC,GAAG,mEAAmE;YAClE,MAAM1B;YACNT,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;YAC3C,MAAMO,aAAa,WAAW;YAE9BN,MAAM,QAAQ,CAAC;gBAACmC;aAAU;YAI1B5B,OAAOH,UAAU,OAAO,CAACX,MAAM,GAAG;QACtC;QAEAyC,GAAG,6EAA6E;YAC5E,MAAM1B;YACNT,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;YAC3C,MAAMO,aAAa,WAAW;YAC9B,MAAMG;YAENT,MAAM,QAAQ,CAAC;gBAACmC;aAAU;YAE1B5B,OAAOH,UAAU,OAAO,CAAC;mBAAIX,MAAM,GAAG;gBAAM;aAAW;QAC3D;QAEAyC,GAAG,wDAAwD;YACvD,MAAM1B;YAEN,MAAM9B,OAAOsB,MAAM,OAAO,CAACG,CAAAA,IAAKA,AAAc,eAAdA,EAAE,OAAO;YACzCH,MAAM,QAAQ,CAAC;gBAACjC,KAAK,MAAM,CAAC;oBAAE,GAAGW,IAAI;oBAAE,SAASlB,QAAQJ,cAAc;gBAAG;aAAG;YAE5EmD,OAAOH,UAAU,OAAO,CAAC;gBAAC;mBAAeX,MAAM,KAAK;mBAASA,MAAM,KAAK;aAAK;QACjF;IACJ;IAEAK,SAAS,cAAc;QACnBoC,GAAG,gDAAgD;YAC/C,MAAM1B;YACN,MAAM4B,SAAShC;YAEf,MAAML,UAAU,WAAW,CAAC;YAE5BQ,OAAOH,UAAU,OAAO,CAACgC;YACzB,MAAMC,YAAYtC,UAAU,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAACM,CAAAA,MAAOA,AAAgB,eAAhBA,IAAI,OAAO;YAChEE,OAAO8B,WAAW,QAAQ,IAAI,CAAC;QACnC;QAEAH,GAAG,yEAAyE;YACxE,MAAM1B;YACN,MAAMT,UAAU,IAAI,CAAC,OAAO,CAAC,QAAQ;YACrC,MAAMqC,SAAShC;YAEf,MAAML,UAAU,WAAW,CAAC;YAE5BQ,OAAOH,UAAU,OAAO,CAACgC;QAC7B;IACJ;AACJ"}
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionDelete: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const BulkActionDelete: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionDuplicate: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const BulkActionDuplicate: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionMovePage: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const BulkActionMovePage: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionPublish: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const BulkActionPublish: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionUnpublish: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const BulkActionUnpublish: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const DocumentList: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const DocumentList: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const Table: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const Table: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -0,0 +1,27 @@
1
+ import { GetPageRevisionsUseCase } from "../../../features/pages/getPageRevisions/abstractions.js";
2
+ import { PageRevisionsCache, WbPageLoadingRepository, WbPageRevisionsLoadingRepository } from "../../../features/pages/shared/abstractions.js";
3
+ import { WbPermissions } from "../../../features/permissions/abstractions.js";
4
+ import { RevisionListPresenter as PresenterAbstraction } from "./abstractions.js";
5
+ declare class RevisionListPresenterImpl implements PresenterAbstraction.Interface {
6
+ private revisionsCache;
7
+ private loadingRepository;
8
+ private pageLoadingRepository;
9
+ private permissions;
10
+ private getPageRevisions;
11
+ private entryId;
12
+ constructor(revisionsCache: PageRevisionsCache.Interface, loadingRepository: WbPageRevisionsLoadingRepository.Interface, pageLoadingRepository: WbPageLoadingRepository.Interface, permissions: WbPermissions.Interface, getPageRevisions: GetPageRevisionsUseCase.Interface);
13
+ init(params: PresenterAbstraction.Init): void;
14
+ get vm(): PresenterAbstraction.ViewModel;
15
+ private getRevisions;
16
+ private getItemVm;
17
+ private getIsLoading;
18
+ /**
19
+ * Watching named actions rather than `hasLoading()`: the `WbPage` namespace is shared with
20
+ * the pages table, so that would also react to listing and fetching.
21
+ */
22
+ private getIsMutating;
23
+ }
24
+ export declare const RevisionListPresenter: typeof RevisionListPresenterImpl & {
25
+ __abstraction: import("@webiny/di").Abstraction<import("./abstractions.js").IRevisionListPresenter>;
26
+ };
27
+ export {};
@@ -0,0 +1,73 @@
1
+ import { makeAutoObservable } from "mobx";
2
+ import orderBy from "lodash/orderBy.js";
3
+ import { WbPageStatus, loadingActions } from "../../../constants.js";
4
+ import { GetPageRevisionsUseCase } from "../../../features/pages/getPageRevisions/abstractions.js";
5
+ import { PageRevisionsCache, WbPageLoadingRepository, WbPageRevisionsLoadingRepository } from "../../../features/pages/shared/abstractions.js";
6
+ import { WbPermissions } from "../../../features/permissions/abstractions.js";
7
+ import { RevisionListPresenter } from "./abstractions.js";
8
+ const MUTATION_ACTIONS = [
9
+ loadingActions.createRevisionFrom
10
+ ];
11
+ class RevisionListPresenterImpl {
12
+ constructor(revisionsCache, loadingRepository, pageLoadingRepository, permissions, getPageRevisions){
13
+ this.revisionsCache = revisionsCache;
14
+ this.loadingRepository = loadingRepository;
15
+ this.pageLoadingRepository = pageLoadingRepository;
16
+ this.permissions = permissions;
17
+ this.getPageRevisions = getPageRevisions;
18
+ this.entryId = void 0;
19
+ this.getRevisions = ()=>{
20
+ if (!this.entryId) return [];
21
+ const revisions = this.revisionsCache.getItems().filter((revision)=>revision.entryId === this.entryId);
22
+ return orderBy(revisions, [
23
+ "savedOn"
24
+ ], [
25
+ "desc"
26
+ ]).map((revision)=>this.getItemVm(revision));
27
+ };
28
+ this.getItemVm = (revision)=>{
29
+ const canEdit = this.permissions.canEdit("page", revision);
30
+ return {
31
+ revision,
32
+ canCreateFrom: canEdit,
33
+ canEdit: !revision.locked && canEdit,
34
+ canPublish: revision.status !== WbPageStatus.Published && this.permissions.canPublish("page"),
35
+ canUnpublish: revision.status === WbPageStatus.Published && this.permissions.canUnpublish("page"),
36
+ canDelete: this.permissions.canDelete("page", revision)
37
+ };
38
+ };
39
+ this.getIsLoading = ()=>Boolean(this.loadingRepository.isLoading(loadingActions.get));
40
+ this.getIsMutating = ()=>MUTATION_ACTIONS.some((action)=>this.pageLoadingRepository.isLoading(action));
41
+ makeAutoObservable(this);
42
+ }
43
+ init(params) {
44
+ if (this.entryId === params.entryId) return;
45
+ this.entryId = params.entryId;
46
+ this.getPageRevisions.execute({
47
+ entryId: params.entryId
48
+ });
49
+ }
50
+ get vm() {
51
+ const revisions = this.getRevisions();
52
+ const isLoading = this.getIsLoading();
53
+ return {
54
+ revisions,
55
+ isLoading,
56
+ isMutating: this.getIsMutating(),
57
+ isEmpty: !isLoading && 0 === revisions.length
58
+ };
59
+ }
60
+ }
61
+ const RevisionListPresenter_RevisionListPresenter = RevisionListPresenter.createImplementation({
62
+ implementation: RevisionListPresenterImpl,
63
+ dependencies: [
64
+ PageRevisionsCache,
65
+ WbPageRevisionsLoadingRepository,
66
+ WbPageLoadingRepository,
67
+ WbPermissions,
68
+ GetPageRevisionsUseCase
69
+ ]
70
+ });
71
+ export { RevisionListPresenter_RevisionListPresenter as RevisionListPresenter };
72
+
73
+ //# sourceMappingURL=RevisionListPresenter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presentation/pages/RevisionList/RevisionListPresenter.js","sources":["../../../../src/presentation/pages/RevisionList/RevisionListPresenter.ts"],"sourcesContent":["import { makeAutoObservable } from \"mobx\";\nimport orderBy from \"lodash/orderBy.js\";\nimport { loadingActions, WbPageStatus } from \"~/constants.js\";\nimport { GetPageRevisionsUseCase } from \"~/features/pages/getPageRevisions/abstractions.js\";\nimport {\n PageRevisionsCache,\n WbPageLoadingRepository,\n WbPageRevisionsLoadingRepository\n} from \"~/features/pages/shared/abstractions.js\";\nimport { WbPermissions } from \"~/features/permissions/abstractions.js\";\nimport type { PageRevision } from \"~/domain/PageRevision/PageRevision.js\";\nimport { RevisionListPresenter as PresenterAbstraction } from \"./abstractions.js\";\n\n/**\n * Only actions that run straight from the menu need the overlay. Delete, publish and unpublish\n * are confirmed through a dialog, which shows its own loader while the action runs.\n */\nconst MUTATION_ACTIONS = [loadingActions.createRevisionFrom];\n\nclass RevisionListPresenterImpl implements PresenterAbstraction.Interface {\n private entryId: string | undefined = undefined;\n\n constructor(\n private revisionsCache: PageRevisionsCache.Interface,\n private loadingRepository: WbPageRevisionsLoadingRepository.Interface,\n private pageLoadingRepository: WbPageLoadingRepository.Interface,\n private permissions: WbPermissions.Interface,\n private getPageRevisions: GetPageRevisionsUseCase.Interface\n ) {\n makeAutoObservable(this);\n }\n\n public init(params: PresenterAbstraction.Init) {\n if (this.entryId === params.entryId) {\n return;\n }\n\n this.entryId = params.entryId;\n void this.getPageRevisions.execute({ entryId: params.entryId });\n }\n\n public get vm(): PresenterAbstraction.ViewModel {\n const revisions = this.getRevisions();\n const isLoading = this.getIsLoading();\n\n return {\n revisions,\n isLoading,\n isMutating: this.getIsMutating(),\n isEmpty: !isLoading && revisions.length === 0\n };\n }\n\n private getRevisions = () => {\n if (!this.entryId) {\n return [];\n }\n\n // The cache is shared across pages, so it can hold revisions of previously opened pages.\n const revisions = this.revisionsCache\n .getItems()\n .filter(revision => revision.entryId === this.entryId);\n\n return orderBy(revisions, [\"savedOn\"], [\"desc\"]).map(revision => this.getItemVm(revision));\n };\n\n private getItemVm = (revision: PageRevision): PresenterAbstraction.ItemViewModel => {\n const canEdit = this.permissions.canEdit(\"page\", revision);\n\n return {\n revision,\n canCreateFrom: canEdit,\n // A locked revision has already been published, so its content can no longer change.\n canEdit: !revision.locked && canEdit,\n canPublish:\n revision.status !== WbPageStatus.Published && this.permissions.canPublish(\"page\"),\n canUnpublish:\n revision.status === WbPageStatus.Published && this.permissions.canUnpublish(\"page\"),\n // Deleting a published or locked revision is allowed, matching the API.\n canDelete: this.permissions.canDelete(\"page\", revision)\n };\n };\n\n private getIsLoading = () => {\n return Boolean(this.loadingRepository.isLoading(loadingActions.get));\n };\n\n /**\n * Watching named actions rather than `hasLoading()`: the `WbPage` namespace is shared with\n * the pages table, so that would also react to listing and fetching.\n */\n private getIsMutating = () => {\n return MUTATION_ACTIONS.some(action => this.pageLoadingRepository.isLoading(action));\n };\n}\n\nexport const RevisionListPresenter = PresenterAbstraction.createImplementation({\n implementation: RevisionListPresenterImpl,\n dependencies: [\n PageRevisionsCache,\n WbPageRevisionsLoadingRepository,\n WbPageLoadingRepository,\n WbPermissions,\n GetPageRevisionsUseCase\n ]\n});\n"],"names":["MUTATION_ACTIONS","loadingActions","RevisionListPresenterImpl","revisionsCache","loadingRepository","pageLoadingRepository","permissions","getPageRevisions","undefined","revisions","revision","orderBy","canEdit","WbPageStatus","Boolean","action","makeAutoObservable","params","isLoading","RevisionListPresenter","PresenterAbstraction","PageRevisionsCache","WbPageRevisionsLoadingRepository","WbPageLoadingRepository","WbPermissions","GetPageRevisionsUseCase"],"mappings":";;;;;;;AAiBA,MAAMA,mBAAmB;IAACC,eAAe,kBAAkB;CAAC;AAE5D,MAAMC;IAGF,YACYC,cAA4C,EAC5CC,iBAA6D,EAC7DC,qBAAwD,EACxDC,WAAoC,EACpCC,gBAAmD,CAC7D;aALUJ,cAAc,GAAdA;aACAC,iBAAiB,GAAjBA;aACAC,qBAAqB,GAArBA;aACAC,WAAW,GAAXA;aACAC,gBAAgB,GAAhBA;aAPJ,OAAO,GAAuBC;aAiC9B,YAAY,GAAG;YACnB,IAAI,CAAC,IAAI,CAAC,OAAO,EACb,OAAO,EAAE;YAIb,MAAMC,YAAY,IAAI,CAAC,cAAc,CAChC,QAAQ,GACR,MAAM,CAACC,CAAAA,WAAYA,SAAS,OAAO,KAAK,IAAI,CAAC,OAAO;YAEzD,OAAOC,QAAQF,WAAW;gBAAC;aAAU,EAAE;gBAAC;aAAO,EAAE,GAAG,CAACC,CAAAA,WAAY,IAAI,CAAC,SAAS,CAACA;QACpF;aAEQ,SAAS,GAAG,CAACA;YACjB,MAAME,UAAU,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQF;YAEjD,OAAO;gBACHA;gBACA,eAAeE;gBAEf,SAAS,CAACF,SAAS,MAAM,IAAIE;gBAC7B,YACIF,SAAS,MAAM,KAAKG,aAAa,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC;gBAC9E,cACIH,SAAS,MAAM,KAAKG,aAAa,SAAS,IAAI,IAAI,CAAC,WAAW,CAAC,YAAY,CAAC;gBAEhF,WAAW,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQH;YAClD;QACJ;aAEQ,YAAY,GAAG,IACZI,QAAQ,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAACb,eAAe,GAAG;QAMrE,KACO,aAAa,GAAG,IACbD,iBAAiB,IAAI,CAACe,CAAAA,SAAU,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAACA;QA/D5EC,mBAAmB,IAAI;IAC3B;IAEO,KAAKC,MAAiC,EAAE;QAC3C,IAAI,IAAI,CAAC,OAAO,KAAKA,OAAO,OAAO,EAC/B;QAGJ,IAAI,CAAC,OAAO,GAAGA,OAAO,OAAO;QACxB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;YAAE,SAASA,OAAO,OAAO;QAAC;IACjE;IAEA,IAAW,KAAqC;QAC5C,MAAMR,YAAY,IAAI,CAAC,YAAY;QACnC,MAAMS,YAAY,IAAI,CAAC,YAAY;QAEnC,OAAO;YACHT;YACAS;YACA,YAAY,IAAI,CAAC,aAAa;YAC9B,SAAS,CAACA,aAAaT,AAAqB,MAArBA,UAAU,MAAM;QAC3C;IACJ;AA2CJ;AAEO,MAAMU,8CAAwBC,sBAAAA,oBAAyC,CAAC;IAC3E,gBAAgBlB;IAChB,cAAc;QACVmB;QACAC;QACAC;QACAC;QACAC;KACH;AACL"}