@webiny/app-aco 6.4.12-beta.5 → 6.5.0-beta.1

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 (180) hide show
  1. package/components/Actions/DeleteFolder/DeleteFolder.js +1 -1
  2. package/components/Actions/DeleteFolder/DeleteFolder.js.map +1 -1
  3. package/components/AdvancedSearch/AdvancedSearch.d.ts +2 -2
  4. package/components/AdvancedSearch/QueryBuilderDrawer/QueryBuilder/components/OperationSelector.js +1 -1
  5. package/components/AdvancedSearch/QueryBuilderDrawer/QueryBuilder/components/OperationSelector.js.map +1 -1
  6. package/components/AdvancedSearch/QueryBuilderDrawer/QueryBuilderDrawer.d.ts +2 -2
  7. package/components/AdvancedSearch/domain/Filter.d.ts +1 -1
  8. package/components/AdvancedSearch/domain/FilterRepositoryFactory.d.ts +2 -2
  9. package/components/AdvancedSearch/domain/FilterRepositoryFactory.js.map +1 -1
  10. package/components/AdvancedSearch/gateways/FiltersGraphQLGateway.d.ts +2 -2
  11. package/components/AdvancedSearch/gateways/FiltersGraphQLGateway.js +9 -10
  12. package/components/AdvancedSearch/gateways/FiltersGraphQLGateway.js.map +1 -1
  13. package/components/AdvancedSearch/gateways/filters.gql.d.ts +5 -5
  14. package/components/AdvancedSearch/gateways/filters.gql.js +5 -6
  15. package/components/AdvancedSearch/gateways/filters.gql.js.map +1 -1
  16. package/components/AdvancedSearch/useFilterRepository.js +7 -2
  17. package/components/AdvancedSearch/useFilterRepository.js.map +1 -1
  18. package/components/FolderTree/List/List.js +1 -1
  19. package/components/FolderTree/List/List.js.map +1 -1
  20. package/components/Table/cells/CellAuthor.d.ts +2 -0
  21. package/components/Table/cells/CellAuthor.js +10 -0
  22. package/components/Table/cells/CellAuthor.js.map +1 -0
  23. package/components/Table/cells/CellCreated.d.ts +2 -0
  24. package/components/Table/cells/CellCreated.js +13 -0
  25. package/components/Table/cells/CellCreated.js.map +1 -0
  26. package/components/Table/cells/CellModified.d.ts +2 -0
  27. package/components/Table/cells/CellModified.js +13 -0
  28. package/components/Table/cells/CellModified.js.map +1 -0
  29. package/components/Table/cells/index.d.ts +3 -0
  30. package/components/Table/cells/index.js +3 -0
  31. package/components/Table/components/Table/TableInner.d.ts +2 -2
  32. package/components/Table/createTableData.d.ts +7 -5
  33. package/components/Table/createTableData.js +22 -7
  34. package/components/Table/createTableData.js.map +1 -1
  35. package/components/Table/index.d.ts +2 -2
  36. package/components/Table/index.js +2 -2
  37. package/components/index.d.ts +0 -1
  38. package/components/index.js +0 -1
  39. package/config/AcoConfig.d.ts +8 -12
  40. package/config/advanced-search/FieldRenderer.d.ts +3 -1
  41. package/config/folder/Action.d.ts +1 -1
  42. package/config/folder/index.d.ts +3 -2
  43. package/config/index.d.ts +0 -1
  44. package/config/index.js +0 -1
  45. package/config/record/Action.d.ts +1 -1
  46. package/config/record/index.d.ts +1 -1
  47. package/config/table/Column.d.ts +8 -39
  48. package/config/table/Column.js +4 -67
  49. package/config/table/Column.js.map +1 -1
  50. package/config/table/Sorting.d.ts +2 -11
  51. package/config/table/Sorting.js +1 -28
  52. package/config/table/index.d.ts +5 -9
  53. package/contexts/index.d.ts +0 -3
  54. package/contexts/index.js +0 -3
  55. package/dialogs/DialogSetPermissions/graphql.d.ts +1 -1
  56. package/dialogs/DialogSetPermissions/graphql.js +1 -2
  57. package/dialogs/DialogSetPermissions/graphql.js.map +1 -1
  58. package/dialogs/useCreateDialog.js +2 -2
  59. package/dialogs/useCreateDialog.js.map +1 -1
  60. package/dialogs/useEditDialog.js +2 -2
  61. package/dialogs/useEditDialog.js.map +1 -1
  62. package/dialogs/useSetPermissionsDialog.js +16 -4
  63. package/dialogs/useSetPermissionsDialog.js.map +1 -1
  64. package/domain/folder/Folder.d.ts +2 -1
  65. package/domain/folder/Folder.js.map +1 -1
  66. package/features/folders/createFolder/CreateFolderGqlGateway.d.ts +3 -3
  67. package/features/folders/createFolder/CreateFolderGqlGateway.js +15 -16
  68. package/features/folders/createFolder/CreateFolderGqlGateway.js.map +1 -1
  69. package/features/folders/deleteFolder/DeleteFolderGqlGateway.d.ts +3 -3
  70. package/features/folders/deleteFolder/DeleteFolderGqlGateway.js +5 -6
  71. package/features/folders/deleteFolder/DeleteFolderGqlGateway.js.map +1 -1
  72. package/features/folders/folderModelProvider/FolderModelProvider.js +29 -31
  73. package/features/folders/folderModelProvider/FolderModelProvider.js.map +1 -1
  74. package/features/folders/folderModelProvider/GetFolderModelGqlGateway.d.ts +3 -3
  75. package/features/folders/folderModelProvider/GetFolderModelGqlGateway.js +5 -7
  76. package/features/folders/folderModelProvider/GetFolderModelGqlGateway.js.map +1 -1
  77. package/features/folders/getFolder/GetFolderGqlGateway.d.ts +3 -3
  78. package/features/folders/getFolder/GetFolderGqlGateway.js +5 -7
  79. package/features/folders/getFolder/GetFolderGqlGateway.js.map +1 -1
  80. package/features/folders/getFolderExtensionsFields/GetFolderExtensionsFieldsUseCase.d.ts +4 -3
  81. package/features/folders/getFolderExtensionsFields/useFolderExtensionsFields.d.ts +4 -3
  82. package/features/folders/listFolders/ListFoldersGqlGateway.d.ts +1 -1
  83. package/features/folders/listFolders/ListFoldersGqlGateway.js +1 -2
  84. package/features/folders/listFolders/ListFoldersGqlGateway.js.map +1 -1
  85. package/features/folders/listFolders/useListFolders.d.ts +1 -1
  86. package/features/folders/listFoldersByParentIds/ListFoldersByParentIdsGqlGateway.d.ts +3 -3
  87. package/features/folders/listFoldersByParentIds/ListFoldersByParentIdsGqlGateway.js +5 -7
  88. package/features/folders/listFoldersByParentIds/ListFoldersByParentIdsGqlGateway.js.map +1 -1
  89. package/features/folders/listFoldersByParentIds/useListFoldersByParentIds.d.ts +2 -2
  90. package/features/folders/loadFolderHierarchy/useLoadFolderHierarchy.d.ts +2 -2
  91. package/features/folders/updateFolder/UpdateFolderGqlGateway.d.ts +3 -3
  92. package/features/folders/updateFolder/UpdateFolderGqlGateway.js +5 -6
  93. package/features/folders/updateFolder/UpdateFolderGqlGateway.js.map +1 -1
  94. package/hooks/index.d.ts +0 -6
  95. package/hooks/index.js +0 -6
  96. package/index.d.ts +3 -2
  97. package/index.js +2 -2
  98. package/package.json +21 -28
  99. package/presentation/folderTree/FolderTree.js +12 -4
  100. package/presentation/folderTree/FolderTree.js.map +1 -1
  101. package/presentation/folderTree/FolderTreePresenter.d.ts +2 -0
  102. package/presentation/folderTree/FolderTreePresenter.js +40 -14
  103. package/presentation/folderTree/FolderTreePresenter.js.map +1 -1
  104. package/presentation/folderTree/FolderTreePresenter.test.js +106 -7
  105. package/presentation/folderTree/FolderTreePresenter.test.js.map +1 -1
  106. package/table.types.d.ts +2 -9
  107. package/types.d.ts +5 -26
  108. package/types.js.map +1 -1
  109. package/components/Extensions/Extensions.d.ts +0 -2
  110. package/components/Extensions/Extensions.js +0 -30
  111. package/components/Extensions/Extensions.js.map +0 -1
  112. package/components/Extensions/index.d.ts +0 -1
  113. package/components/Extensions/index.js +0 -1
  114. package/config/folder/createFolderFieldDecoratorFactory.d.ts +0 -13
  115. package/config/folder/createFolderFieldDecoratorFactory.js +0 -17
  116. package/config/folder/createFolderFieldDecoratorFactory.js.map +0 -1
  117. package/config/table/Sorting.js.map +0 -1
  118. package/contexts/acoList.d.ts +0 -49
  119. package/contexts/acoList.js +0 -303
  120. package/contexts/acoList.js.map +0 -1
  121. package/contexts/app.d.ts +0 -33
  122. package/contexts/app.js +0 -47
  123. package/contexts/app.js.map +0 -1
  124. package/contexts/folders.d.ts +0 -12
  125. package/contexts/folders.js +0 -32
  126. package/contexts/folders.js.map +0 -1
  127. package/contexts/navigateFolder.d.ts +0 -17
  128. package/contexts/navigateFolder.js +0 -54
  129. package/contexts/navigateFolder.js.map +0 -1
  130. package/contexts/records.d.ts +0 -31
  131. package/contexts/records.js +0 -316
  132. package/contexts/records.js.map +0 -1
  133. package/exports/admin/aco.d.ts +0 -2
  134. package/exports/admin/aco.js +0 -2
  135. package/graphql/app.gql.d.ts +0 -17
  136. package/graphql/app.gql.js +0 -22
  137. package/graphql/app.gql.js.map +0 -1
  138. package/graphql/records/common.d.ts +0 -4
  139. package/graphql/records/common.js +0 -57
  140. package/graphql/records/common.js.map +0 -1
  141. package/graphql/records/getRecord.d.ts +0 -2
  142. package/graphql/records/getRecord.js +0 -5
  143. package/graphql/records/getRecord.js.map +0 -1
  144. package/graphql/records/listRecords.d.ts +0 -2
  145. package/graphql/records/listRecords.js +0 -26
  146. package/graphql/records/listRecords.js.map +0 -1
  147. package/graphql/records/moveRecord.d.ts +0 -2
  148. package/graphql/records/moveRecord.js +0 -16
  149. package/graphql/records/moveRecord.js.map +0 -1
  150. package/graphql/records/types.d.ts +0 -108
  151. package/graphql/records/types.js +0 -0
  152. package/graphql/records.gql.d.ts +0 -3
  153. package/graphql/records.gql.js +0 -3
  154. package/handlers.d.ts +0 -23
  155. package/handlers.js +0 -22
  156. package/handlers.js.map +0 -1
  157. package/hooks/useAcoApp.d.ts +0 -2
  158. package/hooks/useAcoApp.js +0 -16
  159. package/hooks/useAcoApp.js.map +0 -1
  160. package/hooks/useAcoList.d.ts +0 -3
  161. package/hooks/useAcoList.js +0 -10
  162. package/hooks/useAcoList.js.map +0 -1
  163. package/hooks/useFolderModel.d.ts +0 -2
  164. package/hooks/useFolderModel.js +0 -16
  165. package/hooks/useFolderModel.js.map +0 -1
  166. package/hooks/useFoldersType.d.ts +0 -1
  167. package/hooks/useFoldersType.js +0 -12
  168. package/hooks/useFoldersType.js.map +0 -1
  169. package/hooks/useNavigateFolder.d.ts +0 -2
  170. package/hooks/useNavigateFolder.js +0 -10
  171. package/hooks/useNavigateFolder.js.map +0 -1
  172. package/hooks/useRecords.d.ts +0 -62
  173. package/hooks/useRecords.js +0 -64
  174. package/hooks/useRecords.js.map +0 -1
  175. package/hooks/useTags.d.ts +0 -14
  176. package/hooks/useTags.js +0 -27
  177. package/hooks/useTags.js.map +0 -1
  178. package/sorting.d.ts +0 -9
  179. package/sorting.js +0 -31
  180. package/sorting.js.map +0 -1
@@ -1,9 +1,8 @@
1
- import graphql_tag from "graphql-tag";
2
- import { ApolloClient } from "@webiny/app-admin/features/apolloClient/abstraction.js";
1
+ import { MainGraphQLClient } from "@webiny/app/features/mainGraphQLClient/index.js";
3
2
  import { FolderModelProvider } from "../abstractions.js";
4
3
  import { UpdateFolderGateway } from "./abstractions.js";
5
4
  import { ROOT_FOLDER } from "../../../constants.js";
6
- const UPDATE_FOLDER = (FOLDER_FIELDS)=>graphql_tag`
5
+ const UPDATE_FOLDER = (FOLDER_FIELDS)=>`
7
6
  mutation UpdateFolder($id: ID!, $data: FolderUpdateInput!) {
8
7
  aco {
9
8
  updateFolder(id: $id, data: $data) {
@@ -25,8 +24,8 @@ class UpdateFolderGqlGatewayImpl {
25
24
  async execute(folder) {
26
25
  const fields = await this.folderModelProvider.getGraphQLSelection();
27
26
  const { id, title, slug, permissions, parentId, extensions } = folder;
28
- const { data: response } = await this.client.mutate({
29
- mutation: UPDATE_FOLDER(fields),
27
+ const response = await this.client.execute({
28
+ query: UPDATE_FOLDER(fields),
30
29
  variables: {
31
30
  id,
32
31
  data: {
@@ -47,7 +46,7 @@ class UpdateFolderGqlGatewayImpl {
47
46
  const UpdateFolderGqlGateway = UpdateFolderGateway.createImplementation({
48
47
  implementation: UpdateFolderGqlGatewayImpl,
49
48
  dependencies: [
50
- ApolloClient,
49
+ MainGraphQLClient,
51
50
  FolderModelProvider
52
51
  ]
53
52
  });
@@ -1 +1 @@
1
- {"version":3,"file":"features/folders/updateFolder/UpdateFolderGqlGateway.js","sources":["../../../../src/features/folders/updateFolder/UpdateFolderGqlGateway.ts"],"sourcesContent":["import gql from \"graphql-tag\";\nimport { ApolloClient } from \"@webiny/app-admin/features/apolloClient/abstraction.js\";\nimport type { FolderDto } from \"~/domain/folder/FolderDto.js\";\nimport { FolderModelProvider } from \"~/features/folders/abstractions.js\";\nimport type { FolderGatewayDto } from \"./abstractions.js\";\nimport { UpdateFolderGateway as GatewayAbstraction } from \"./abstractions.js\";\nimport type { AcoError } from \"~/types.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\n\nexport interface UpdateFolderResponse {\n aco: {\n updateFolder: {\n data: FolderDto;\n error: AcoError | null;\n };\n };\n}\n\nexport interface UpdateFolderVariables {\n id: string;\n data: Partial<\n Omit<\n FolderDto,\n \"id\" | \"createdOn\" | \"createdBy\" | \"savedOn\" | \"savedBy\" | \"modifiedOn\" | \"modifiedBy\"\n >\n >;\n}\n\nexport const UPDATE_FOLDER = (FOLDER_FIELDS: string) => gql`\n mutation UpdateFolder($id: ID!, $data: FolderUpdateInput!) {\n aco {\n updateFolder(id: $id, data: $data) {\n data ${FOLDER_FIELDS}\n error {\n code\n data\n message\n }\n }\n }\n }\n`;\n\nclass UpdateFolderGqlGatewayImpl implements GatewayAbstraction.Interface {\n constructor(\n private client: ApolloClient.Interface,\n private folderModelProvider: FolderModelProvider.Interface\n ) {}\n\n async execute(folder: FolderGatewayDto) {\n const fields = await this.folderModelProvider.getGraphQLSelection();\n\n const { id, title, slug, permissions, parentId, extensions } = folder;\n\n const { data: response } = await this.client.mutate<\n UpdateFolderResponse,\n UpdateFolderVariables\n >({\n mutation: UPDATE_FOLDER(fields),\n variables: {\n id,\n data: {\n title,\n slug,\n extensions,\n parentId: parentId === ROOT_FOLDER ? null : parentId,\n permissions: permissions.filter(p => !p.inheritedFrom)\n }\n }\n });\n\n if (!response) {\n throw new Error(\"Network error while updating folder.\");\n }\n\n const { data, error } = response.aco.updateFolder;\n\n if (!data) {\n throw new Error(error?.message || \"Could not update folder\");\n }\n\n return data;\n }\n}\n\nexport const UpdateFolderGqlGateway = GatewayAbstraction.createImplementation({\n implementation: UpdateFolderGqlGatewayImpl,\n dependencies: [ApolloClient, FolderModelProvider]\n});\n"],"names":["UPDATE_FOLDER","FOLDER_FIELDS","gql","UpdateFolderGqlGatewayImpl","client","folderModelProvider","folder","fields","id","title","slug","permissions","parentId","extensions","response","ROOT_FOLDER","p","Error","data","error","UpdateFolderGqlGateway","GatewayAbstraction","ApolloClient","FolderModelProvider"],"mappings":";;;;;AA4BO,MAAMA,gBAAgB,CAACC,gBAA0BC,WAAG,CAAC;;;;qBAIvC,EAAED,cAAc;;;;;;;;;AASrC,CAAC;AAED,MAAME;IACF,YACYC,MAA8B,EAC9BC,mBAAkD,CAC5D;aAFUD,MAAM,GAANA;aACAC,mBAAmB,GAAnBA;IACT;IAEH,MAAM,QAAQC,MAAwB,EAAE;QACpC,MAAMC,SAAS,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB;QAEjE,MAAM,EAAEC,EAAE,EAAEC,KAAK,EAAEC,IAAI,EAAEC,WAAW,EAAEC,QAAQ,EAAEC,UAAU,EAAE,GAAGP;QAE/D,MAAM,EAAE,MAAMQ,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAGjD;YACE,UAAUd,cAAcO;YACxB,WAAW;gBACPC;gBACA,MAAM;oBACFC;oBACAC;oBACAG;oBACA,UAAUD,aAAaG,cAAc,OAAOH;oBAC5C,aAAaD,YAAY,MAAM,CAACK,CAAAA,IAAK,CAACA,EAAE,aAAa;gBACzD;YACJ;QACJ;QAEA,IAAI,CAACF,UACD,MAAM,IAAIG,MAAM;QAGpB,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGL,SAAS,GAAG,CAAC,YAAY;QAEjD,IAAI,CAACI,MACD,MAAM,IAAID,MAAME,OAAO,WAAW;QAGtC,OAAOD;IACX;AACJ;AAEO,MAAME,yBAAyBC,oBAAAA,oBAAuC,CAAC;IAC1E,gBAAgBlB;IAChB,cAAc;QAACmB;QAAcC;KAAoB;AACrD"}
1
+ {"version":3,"file":"features/folders/updateFolder/UpdateFolderGqlGateway.js","sources":["../../../../src/features/folders/updateFolder/UpdateFolderGqlGateway.ts"],"sourcesContent":["import { MainGraphQLClient } from \"@webiny/app/features/mainGraphQLClient/index.js\";\nimport type { FolderDto } from \"~/domain/folder/FolderDto.js\";\nimport { FolderModelProvider } from \"~/features/folders/abstractions.js\";\nimport type { FolderGatewayDto } from \"./abstractions.js\";\nimport { UpdateFolderGateway as GatewayAbstraction } from \"./abstractions.js\";\nimport type { AcoError } from \"~/types.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\n\nexport interface UpdateFolderResponse {\n aco: {\n updateFolder: {\n data: FolderDto;\n error: AcoError | null;\n };\n };\n}\n\nexport interface UpdateFolderVariables {\n id: string;\n data: Partial<\n Omit<\n FolderDto,\n \"id\" | \"createdOn\" | \"createdBy\" | \"savedOn\" | \"savedBy\" | \"modifiedOn\" | \"modifiedBy\"\n >\n >;\n}\n\nexport const UPDATE_FOLDER = (FOLDER_FIELDS: string) => /* GraphQL */ `\n mutation UpdateFolder($id: ID!, $data: FolderUpdateInput!) {\n aco {\n updateFolder(id: $id, data: $data) {\n data ${FOLDER_FIELDS}\n error {\n code\n data\n message\n }\n }\n }\n }\n`;\n\nclass UpdateFolderGqlGatewayImpl implements GatewayAbstraction.Interface {\n constructor(\n private client: MainGraphQLClient.Interface,\n private folderModelProvider: FolderModelProvider.Interface\n ) {}\n\n async execute(folder: FolderGatewayDto) {\n const fields = await this.folderModelProvider.getGraphQLSelection();\n\n const { id, title, slug, permissions, parentId, extensions } = folder;\n\n const response = await this.client.execute<UpdateFolderResponse, UpdateFolderVariables>({\n query: UPDATE_FOLDER(fields),\n variables: {\n id,\n data: {\n title,\n slug,\n extensions,\n parentId: parentId === ROOT_FOLDER ? null : parentId,\n permissions: permissions.filter(p => !p.inheritedFrom)\n }\n }\n });\n\n if (!response) {\n throw new Error(\"Network error while updating folder.\");\n }\n\n const { data, error } = response.aco.updateFolder;\n\n if (!data) {\n throw new Error(error?.message || \"Could not update folder\");\n }\n\n return data;\n }\n}\n\nexport const UpdateFolderGqlGateway = GatewayAbstraction.createImplementation({\n implementation: UpdateFolderGqlGatewayImpl,\n dependencies: [MainGraphQLClient, FolderModelProvider]\n});\n"],"names":["UPDATE_FOLDER","FOLDER_FIELDS","UpdateFolderGqlGatewayImpl","client","folderModelProvider","folder","fields","id","title","slug","permissions","parentId","extensions","response","ROOT_FOLDER","p","Error","data","error","UpdateFolderGqlGateway","GatewayAbstraction","MainGraphQLClient","FolderModelProvider"],"mappings":";;;;AA2BO,MAAMA,gBAAgB,CAACC,gBAAwC,CAAC;;;;qBAIlD,EAAEA,cAAc;;;;;;;;;AASrC,CAAC;AAED,MAAMC;IACF,YACYC,MAAmC,EACnCC,mBAAkD,CAC5D;aAFUD,MAAM,GAANA;aACAC,mBAAmB,GAAnBA;IACT;IAEH,MAAM,QAAQC,MAAwB,EAAE;QACpC,MAAMC,SAAS,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB;QAEjE,MAAM,EAAEC,EAAE,EAAEC,KAAK,EAAEC,IAAI,EAAEC,WAAW,EAAEC,QAAQ,EAAEC,UAAU,EAAE,GAAGP;QAE/D,MAAMQ,WAAW,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAA8C;YACpF,OAAOb,cAAcM;YACrB,WAAW;gBACPC;gBACA,MAAM;oBACFC;oBACAC;oBACAG;oBACA,UAAUD,aAAaG,cAAc,OAAOH;oBAC5C,aAAaD,YAAY,MAAM,CAACK,CAAAA,IAAK,CAACA,EAAE,aAAa;gBACzD;YACJ;QACJ;QAEA,IAAI,CAACF,UACD,MAAM,IAAIG,MAAM;QAGpB,MAAM,EAAEC,IAAI,EAAEC,KAAK,EAAE,GAAGL,SAAS,GAAG,CAAC,YAAY;QAEjD,IAAI,CAACI,MACD,MAAM,IAAID,MAAME,OAAO,WAAW;QAGtC,OAAOD;IACX;AACJ;AAEO,MAAME,yBAAyBC,oBAAAA,oBAAuC,CAAC;IAC1E,gBAAgBlB;IAChB,cAAc;QAACmB;QAAmBC;KAAoB;AAC1D"}
package/hooks/index.d.ts CHANGED
@@ -1,7 +1 @@
1
- export * from "./useAcoList.js";
2
- export * from "./useAcoApp.js";
3
1
  export * from "./useFolder.js";
4
- export * from "./useFoldersType.js";
5
- export * from "./useRecords.js";
6
- export * from "./useTags.js";
7
- export * from "./useNavigateFolder.js";
package/hooks/index.js CHANGED
@@ -1,7 +1 @@
1
- export * from "./useAcoList.js";
2
- export * from "./useAcoApp.js";
3
1
  export * from "./useFolder.js";
4
- export * from "./useFoldersType.js";
5
- export * from "./useRecords.js";
6
- export * from "./useTags.js";
7
- export * from "./useNavigateFolder.js";
package/index.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- export * from "./app.js";
2
1
  export * from "./components/index.js";
3
2
  export * from "./config/index.js";
4
3
  export * from "./contexts/index.js";
5
4
  export * from "./hooks/index.js";
6
5
  export * from "./dialogs/index.js";
7
- export * from "./sorting.js";
8
6
  export type { TableRow, FolderTableRow, RecordTableRow } from "./table.types.js";
7
+ export { sortFolders } from "./components/Table/createTableData.js";
8
+ export type { FolderSortConfig } from "./components/Table/createTableData.js";
9
9
  export type { ListMeta, FolderLevelPermissionsTarget } from "./types.js";
10
10
  export { LIST_FOLDER_LEVEL_PERMISSIONS_TARGETS } from "./dialogs/DialogSetPermissions/graphql.js";
11
11
  export { UsersTeamsMultiAutocomplete } from "./dialogs/DialogSetPermissions/UsersTeamsMultiAutocomplete.js";
@@ -23,3 +23,4 @@ export * from "./features/folders/loadFolderHierarchy/useLoadFolderHierarchy.js"
23
23
  export * from "./features/folders/listFolders/useListFolders.js";
24
24
  export * from "./features/folders/listFoldersByParentIds/useListFoldersByParentIds.js";
25
25
  export * from "./presentation/folderTree/index.js";
26
+ export * from "./app.js";
package/index.js CHANGED
@@ -1,10 +1,8 @@
1
- export * from "./app.js";
2
1
  export * from "./components/index.js";
3
2
  export * from "./config/index.js";
4
3
  export * from "./contexts/index.js";
5
4
  export * from "./hooks/index.js";
6
5
  export * from "./dialogs/index.js";
7
- export * from "./sorting.js";
8
6
  export * from "./domain/folder/FolderDto.js";
9
7
  export * from "./domain/folder/FolderDtoMapper.js";
10
8
  export * from "./features/folders/createFolder/useCreateFolder.js";
@@ -19,5 +17,7 @@ export * from "./features/folders/loadFolderHierarchy/useLoadFolderHierarchy.js"
19
17
  export * from "./features/folders/listFolders/useListFolders.js";
20
18
  export * from "./features/folders/listFoldersByParentIds/useListFoldersByParentIds.js";
21
19
  export * from "./presentation/folderTree/index.js";
20
+ export * from "./app.js";
21
+ export { sortFolders } from "./components/Table/createTableData.js";
22
22
  export { LIST_FOLDER_LEVEL_PERMISSIONS_TARGETS } from "./dialogs/DialogSetPermissions/graphql.js";
23
23
  export { UsersTeamsMultiAutocomplete } from "./dialogs/DialogSetPermissions/UsersTeamsMultiAutocomplete.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/app-aco",
3
- "version": "6.4.12-beta.5",
3
+ "version": "6.5.0-beta.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -15,41 +15,34 @@
15
15
  "author": "Webiny Ltd.",
16
16
  "license": "MIT",
17
17
  "dependencies": {
18
- "@apollo/react-hooks": "3.1.5",
19
- "@webiny/admin-ui": "6.4.12-beta.5",
20
- "@webiny/app": "6.4.12-beta.5",
21
- "@webiny/app-admin": "6.4.12-beta.5",
22
- "@webiny/app-headless-cms-common": "6.4.12-beta.5",
23
- "@webiny/app-utils": "6.4.12-beta.5",
24
- "@webiny/feature": "6.4.12-beta.5",
25
- "@webiny/form": "6.4.12-beta.5",
26
- "@webiny/icons": "6.4.12-beta.5",
27
- "@webiny/plugins": "6.4.12-beta.5",
28
- "@webiny/react-properties": "6.4.12-beta.5",
29
- "@webiny/shared-aco": "6.4.12-beta.5",
30
- "@webiny/utils": "6.4.12-beta.5",
31
- "@webiny/validation": "6.4.12-beta.5",
32
- "dot-prop-immutable": "2.1.1",
33
- "graphql": "16.14.2",
34
- "graphql-tag": "2.12.7",
18
+ "@webiny/admin-ui": "6.5.0-beta.1",
19
+ "@webiny/app": "6.5.0-beta.1",
20
+ "@webiny/app-admin": "6.5.0-beta.1",
21
+ "@webiny/app-headless-cms-common": "6.5.0-beta.1",
22
+ "@webiny/app-utils": "6.5.0-beta.1",
23
+ "@webiny/feature": "6.5.0-beta.1",
24
+ "@webiny/form": "6.5.0-beta.1",
25
+ "@webiny/icons": "6.5.0-beta.1",
26
+ "@webiny/react-properties": "6.5.0-beta.1",
27
+ "@webiny/shared-aco": "6.5.0-beta.1",
28
+ "@webiny/utils": "6.5.0-beta.1",
29
+ "@webiny/validation": "6.5.0-beta.1",
35
30
  "lodash": "4.18.1",
36
- "mobx": "7.0.3",
37
- "mobx-react-lite": "5.0.3",
31
+ "mobx": "6.16.1",
32
+ "mobx-react-lite": "4.1.1",
38
33
  "react": "18.3.1",
39
34
  "react-dom": "18.3.1",
40
35
  "slugify": "1.6.9",
41
- "zod": "4.6.5"
36
+ "zod": "4.4.3"
42
37
  },
43
38
  "devDependencies": {
44
39
  "@types/react": "18.3.31",
45
- "@webiny/build-tools": "6.4.12-beta.5",
46
- "@webiny/di": "1.1.0",
47
- "@webiny/wcp": "6.4.12-beta.5",
48
- "apollo-client": "2.6.10",
49
- "apollo-link": "1.2.14",
40
+ "@webiny/build-tools": "6.5.0-beta.1",
41
+ "@webiny/di": "1.0.2",
42
+ "@webiny/wcp": "6.5.0-beta.1",
50
43
  "rimraf": "6.1.3",
51
- "typescript": "6.0.3",
52
- "vitest": "5.0.1"
44
+ "typescript": "7.0.2",
45
+ "vitest": "4.1.10"
53
46
  },
54
47
  "publishConfig": {
55
48
  "access": "public"
@@ -138,10 +138,18 @@ const FolderTree = ({ vm, actions, folderActions = [], enableCreate, enableActio
138
138
  const folder = localFolders.find((f)=>f.id === dragSourceId);
139
139
  const targetFolder = localFolders.find((f)=>f.id === dropTargetId);
140
140
  if (!folder || !targetFolder) return;
141
- showConfirmMoveFolderDialog({
142
- folder,
143
- targetFolder,
144
- onAccept: runDrop
141
+ await new Promise((resolve, reject)=>{
142
+ showConfirmMoveFolderDialog({
143
+ folder,
144
+ targetFolder,
145
+ onAccept: async ()=>{
146
+ await runDrop();
147
+ resolve();
148
+ },
149
+ onClose: ()=>{
150
+ reject(new Error("cancelled"));
151
+ }
152
+ });
145
153
  });
146
154
  } else await runDrop();
147
155
  }, [
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/folderTree/FolderTree.js","sources":["../../../src/presentation/folderTree/FolderTree.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport {\n Tree,\n Tooltip,\n Dialog,\n Text,\n OverlayLoader,\n type NodeDto,\n type TreeProps,\n type WithDefaultNodeData,\n type DropOptions\n} from \"@webiny/admin-ui\";\nimport { useFeature } from \"@webiny/app\";\nimport { observer } from \"mobx-react-lite\";\nimport { useSnackbar, FormView } from \"@webiny/app-admin\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\nimport { FolderProvider } from \"~/contexts/folder.js\";\nimport { Node } from \"~/components/FolderTree/Node/Node.js\";\nimport { Loader } from \"~/components/FolderTree/Loader/Loader.js\";\nimport { ButtonCreate } from \"~/components/FolderTree/ButtonCreate/ButtonCreate.js\";\nimport { useConfirmMoveFolderDialog } from \"~/dialogs/index.js\";\nimport { createTreeData, createInitialOpenList } from \"~/components/FolderTree/List/utils.js\";\nimport { FolderTreePresenterFeature } from \"./feature.js\";\nimport type { FolderDto } from \"~/domain/folder/FolderDto.js\";\nimport type { FolderActionConfig } from \"~/config/AcoConfig.js\";\nimport type {\n IFolderTreeCallbacks,\n IFolderTreeViewModel,\n IFolderOperationState\n} from \"./abstractions.js\";\n\nconst t = i18n.ns(\"app-aco/presentation/folder-tree\");\n\nconst FolderOperationDialog = observer(function FolderOperationDialog({\n operation,\n actions\n}: {\n operation: IFolderOperationState;\n actions: IFolderTreeCallbacks;\n}) {\n const [loading, setLoading] = useState(false);\n\n if (!operation.active) {\n return null;\n }\n\n const handleClose = () => {\n if (!loading) {\n actions.cancelOperation();\n }\n };\n\n const withLoading = async (fn: () => Promise<unknown>) => {\n setLoading(true);\n try {\n await fn();\n } finally {\n setLoading(false);\n }\n };\n\n if (operation.mode === \"delete\") {\n return (\n <Dialog\n open={true}\n onClose={handleClose}\n title={t`Delete Folder`}\n actions={\n <>\n <Dialog.CancelAction onClick={handleClose} text={t`Cancel`} />\n <Dialog.ConfirmAction\n onClick={() => {\n if (operation.folderId) {\n void withLoading(() =>\n actions.deleteFolder(operation.folderId!)\n );\n }\n }}\n text={t`Delete`}\n />\n </>\n }\n >\n {loading && <OverlayLoader text={t`Deleting folder...`} />}\n <Text size={\"md\"}>\n {t`Are you sure you want to delete this folder? This action cannot be undone.`}\n </Text>\n </Dialog>\n );\n }\n\n if ((operation.mode === \"create\" || operation.mode === \"edit\") && operation.form) {\n const title = operation.mode === \"create\" ? t`Create Folder` : t`Edit Folder`;\n const confirmLabel = operation.mode === \"create\" ? t`Create` : t`Save`;\n const loadingLabel =\n operation.mode === \"create\" ? t`Creating folder...` : t`Saving folder...`;\n\n return (\n <Dialog\n open={true}\n onClose={handleClose}\n title={title}\n actions={\n <>\n <Dialog.CancelAction onClick={handleClose} text={t`Cancel`} />\n <Dialog.ConfirmAction\n onClick={() => {\n void withLoading(() => actions.submitOperation());\n }}\n text={confirmLabel}\n />\n </>\n }\n >\n {loading && <OverlayLoader text={loadingLabel} />}\n <FormView name={\"Folder Tree\"} form={operation.form.vm} />\n </Dialog>\n );\n }\n\n return null;\n});\n\nexport interface PresenterFolderTreeProps {\n vm: IFolderTreeViewModel;\n actions: IFolderTreeCallbacks;\n folderActions?: FolderActionConfig[];\n enableCreate?: boolean;\n enableActions?: boolean;\n dropConfirmation?: boolean;\n rootFolderLabel?: string;\n hiddenFolderIds?: string[];\n}\n\nexport interface UncontrolledFolderTreeProps extends Omit<\n PresenterFolderTreeProps,\n \"vm\" | \"actions\"\n> {\n focusedFolderId?: string | null;\n onFolderClick?: (folderId: string | null) => void;\n}\n\nexport const FolderTree = ({\n vm,\n actions,\n folderActions = [],\n enableCreate,\n enableActions,\n dropConfirmation = false,\n rootFolderLabel,\n hiddenFolderIds\n}: PresenterFolderTreeProps) => {\n const { showSnackbar } = useSnackbar();\n const { showDialog: showConfirmMoveFolderDialog } = useConfirmMoveFolderDialog();\n\n const focusedFolderId = vm.currentFolderId ?? ROOT_FOLDER;\n\n const folders = vm.folders;\n\n const localFolders = useMemo(() => {\n if (!folders.length) {\n return [];\n }\n return folders.map(item =>\n item.id === ROOT_FOLDER && rootFolderLabel ? { ...item, title: rootFolderLabel } : item\n );\n }, [folders, rootFolderLabel]);\n\n const [treeData, setTreeData] = useState<NodeDto<FolderDto>[]>([]);\n const [openFolderIds, setOpenFolderIds] = useState<string[]>([ROOT_FOLDER]);\n\n useEffect(() => {\n setTreeData(createTreeData(localFolders, focusedFolderId, hiddenFolderIds));\n }, [localFolders, focusedFolderId, hiddenFolderIds]);\n\n useEffect(() => {\n setOpenFolderIds(prev => {\n const expanded = createInitialOpenList(localFolders, prev, focusedFolderId);\n return [...new Set([ROOT_FOLDER, ...expanded])];\n });\n }, [focusedFolderId, localFolders]);\n\n const handleChangeOpen: TreeProps[\"onChangeOpen\"] = async nodes => {\n const folderIds = nodes.map(node => node.id);\n const updatedOpenIds = [...new Set([ROOT_FOLDER, ...folderIds])];\n const newlyOpened = updatedOpenIds.filter(id => !openFolderIds.includes(id));\n setOpenFolderIds(updatedOpenIds);\n\n if (newlyOpened.length > 0) {\n await actions.loadChildFolders(newlyOpened);\n }\n };\n\n const handleDrop: TreeProps[\"onDrop\"] = async (_, { dragSourceId, dropTargetId }) => {\n try {\n const targetParentId = dropTargetId !== ROOT_FOLDER ? (dropTargetId as string) : null;\n await actions.moveFolder(dragSourceId as string, targetParentId);\n } catch (error) {\n showSnackbar((error as Error).message);\n }\n };\n\n const onDrop = useCallback<NonNullable<TreeProps[\"onDrop\"]>>(\n async (newTree, options: DropOptions) => {\n const runDrop = async () => handleDrop(newTree, options);\n\n if (dropConfirmation) {\n const { dragSourceId, dropTargetId } = options;\n const folder = localFolders.find(f => f.id === dragSourceId);\n const targetFolder = localFolders.find(f => f.id === dropTargetId);\n\n if (!folder || !targetFolder) {\n return;\n }\n\n showConfirmMoveFolderDialog({\n folder,\n targetFolder,\n onAccept: runDrop\n });\n } else {\n await runDrop();\n }\n },\n [localFolders, dropConfirmation, showConfirmMoveFolderDialog]\n );\n\n const sort = useMemo(\n () => (a: NodeDto<any>, b: NodeDto<any>) => {\n if (a.id === ROOT_FOLDER || b.id === ROOT_FOLDER) {\n return 1;\n }\n return a.label.localeCompare(b.label, undefined, { numeric: true });\n },\n []\n );\n\n const canDrag: TreeProps<FolderDto>[\"canDrag\"] = useCallback(\n (node: NodeDto<FolderDto>) =>\n node.id !== ROOT_FOLDER && actions.canManageStructure(node.id),\n [actions]\n );\n\n const canDrop: TreeProps<FolderDto>[\"canDrop\"] = (_, options: DropOptions<FolderDto>) => {\n const { dragSourceId, dropTargetId } = options;\n const ancestorIds = actions.getAncestorIds(dropTargetId as string);\n return !(dragSourceId && ancestorIds.includes(dragSourceId as string));\n };\n\n const nodeRenderer: TreeProps<FolderDto>[\"renderer\"] = node => {\n const folder = localFolders.find(f => f.id === node.id);\n return (\n <FolderProvider folder={folder}>\n <Node enableActions={enableActions} folderActions={folderActions} />\n </FolderProvider>\n );\n };\n\n const handleNodeClick = useCallback(\n (node: WithDefaultNodeData<FolderDto>) => {\n actions.selectFolder(node.id === ROOT_FOLDER ? null : node.id);\n },\n [actions]\n );\n\n const createButton = useMemo(() => {\n if (!enableCreate) {\n return null;\n }\n\n const canCreate = actions.canManageStructure(focusedFolderId);\n const button = (\n <ButtonCreate\n disabled={!canCreate}\n onCreateFolder={() =>\n actions.createFolder(\n focusedFolderId === ROOT_FOLDER ? undefined : focusedFolderId\n )\n }\n />\n );\n\n return canCreate ? (\n button\n ) : (\n <Tooltip\n content={`Cannot create folder because you're not an owner.`}\n trigger={button}\n />\n );\n }, [enableCreate, actions, focusedFolderId, localFolders]);\n\n if (vm.loading) {\n return <Loader />;\n }\n\n return (\n <div className=\"my-xs\">\n <Tree<FolderDto>\n nodes={treeData}\n rootId={\"0\"}\n defaultOpenNodeIds={openFolderIds}\n onChangeOpen={handleChangeOpen}\n onDrop={onDrop}\n onNodeClick={handleNodeClick}\n sort={sort}\n canDrag={canDrag}\n canDrop={canDrop}\n renderer={nodeRenderer}\n defaultLockedOpenNodeIds={[ROOT_FOLDER]}\n loadingNodeIds={vm.loadingNodeIds}\n />\n {enableCreate && (\n <div className={\"m-xs-plus mt-sm-plus mb-lg pl-sm-extra\"}>{createButton}</div>\n )}\n <FolderOperationDialog operation={vm.operation} actions={actions} />\n </div>\n );\n};\n\nexport const UncontrolledFolderTree = ({\n focusedFolderId,\n onFolderClick,\n ...props\n}: UncontrolledFolderTreeProps) => {\n const { presenter } = useFeature(FolderTreePresenterFeature);\n\n const vm = useMemo(() => {\n if (focusedFolderId === undefined) {\n return presenter.vm;\n }\n return { ...presenter.vm, currentFolderId: focusedFolderId };\n }, [presenter.vm, focusedFolderId]);\n\n const actions = useMemo(() => {\n if (!onFolderClick) {\n return presenter;\n }\n return { ...presenter, selectFolder: onFolderClick };\n }, [presenter, onFolderClick]);\n\n return <FolderTree vm={vm} actions={actions} {...props} />;\n};\n"],"names":["t","i18n","FolderOperationDialog","observer","operation","actions","loading","setLoading","useState","handleClose","withLoading","fn","Dialog","OverlayLoader","Text","title","confirmLabel","loadingLabel","FormView","FolderTree","vm","folderActions","enableCreate","enableActions","dropConfirmation","rootFolderLabel","hiddenFolderIds","showSnackbar","useSnackbar","showConfirmMoveFolderDialog","useConfirmMoveFolderDialog","focusedFolderId","ROOT_FOLDER","folders","localFolders","useMemo","item","treeData","setTreeData","openFolderIds","setOpenFolderIds","useEffect","createTreeData","prev","expanded","createInitialOpenList","Set","handleChangeOpen","nodes","folderIds","node","updatedOpenIds","newlyOpened","id","handleDrop","_","dragSourceId","dropTargetId","targetParentId","error","onDrop","useCallback","newTree","options","runDrop","folder","f","targetFolder","sort","a","b","undefined","canDrag","canDrop","ancestorIds","nodeRenderer","FolderProvider","Node","handleNodeClick","createButton","canCreate","button","ButtonCreate","Tooltip","Loader","Tree","UncontrolledFolderTree","onFolderClick","props","presenter","useFeature","FolderTreePresenterFeature"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/folderTree/FolderTree.js","sources":["../../../src/presentation/folderTree/FolderTree.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from \"react\";\nimport {\n Tree,\n Tooltip,\n Dialog,\n Text,\n OverlayLoader,\n type NodeDto,\n type TreeProps,\n type WithDefaultNodeData,\n type DropOptions\n} from \"@webiny/admin-ui\";\nimport { useFeature } from \"@webiny/app\";\nimport { observer } from \"mobx-react-lite\";\nimport { useSnackbar, FormView } from \"@webiny/app-admin\";\nimport { i18n } from \"@webiny/app/i18n/index.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\nimport { FolderProvider } from \"~/contexts/folder.js\";\nimport { Node } from \"~/components/FolderTree/Node/Node.js\";\nimport { Loader } from \"~/components/FolderTree/Loader/Loader.js\";\nimport { ButtonCreate } from \"~/components/FolderTree/ButtonCreate/ButtonCreate.js\";\nimport { useConfirmMoveFolderDialog } from \"~/dialogs/index.js\";\nimport { createTreeData, createInitialOpenList } from \"~/components/FolderTree/List/utils.js\";\nimport { FolderTreePresenterFeature } from \"./feature.js\";\nimport type { FolderDto } from \"~/domain/folder/FolderDto.js\";\nimport type { FolderActionConfig } from \"~/config/AcoConfig.js\";\nimport type {\n IFolderTreeCallbacks,\n IFolderTreeViewModel,\n IFolderOperationState\n} from \"./abstractions.js\";\n\nconst t = i18n.ns(\"app-aco/presentation/folder-tree\");\n\nconst FolderOperationDialog = observer(function FolderOperationDialog({\n operation,\n actions\n}: {\n operation: IFolderOperationState;\n actions: IFolderTreeCallbacks;\n}) {\n const [loading, setLoading] = useState(false);\n\n if (!operation.active) {\n return null;\n }\n\n const handleClose = () => {\n if (!loading) {\n actions.cancelOperation();\n }\n };\n\n const withLoading = async (fn: () => Promise<unknown>) => {\n setLoading(true);\n try {\n await fn();\n } finally {\n setLoading(false);\n }\n };\n\n if (operation.mode === \"delete\") {\n return (\n <Dialog\n open={true}\n onClose={handleClose}\n title={t`Delete Folder`}\n actions={\n <>\n <Dialog.CancelAction onClick={handleClose} text={t`Cancel`} />\n <Dialog.ConfirmAction\n onClick={() => {\n if (operation.folderId) {\n void withLoading(() =>\n actions.deleteFolder(operation.folderId!)\n );\n }\n }}\n text={t`Delete`}\n />\n </>\n }\n >\n {loading && <OverlayLoader text={t`Deleting folder...`} />}\n <Text size={\"md\"}>\n {t`Are you sure you want to delete this folder? This action cannot be undone.`}\n </Text>\n </Dialog>\n );\n }\n\n if ((operation.mode === \"create\" || operation.mode === \"edit\") && operation.form) {\n const title = operation.mode === \"create\" ? t`Create Folder` : t`Edit Folder`;\n const confirmLabel = operation.mode === \"create\" ? t`Create` : t`Save`;\n const loadingLabel =\n operation.mode === \"create\" ? t`Creating folder...` : t`Saving folder...`;\n\n return (\n <Dialog\n open={true}\n onClose={handleClose}\n title={title}\n actions={\n <>\n <Dialog.CancelAction onClick={handleClose} text={t`Cancel`} />\n <Dialog.ConfirmAction\n onClick={() => {\n void withLoading(() => actions.submitOperation());\n }}\n text={confirmLabel}\n />\n </>\n }\n >\n {loading && <OverlayLoader text={loadingLabel} />}\n <FormView name={\"Folder Tree\"} form={operation.form.vm} />\n </Dialog>\n );\n }\n\n return null;\n});\n\nexport interface PresenterFolderTreeProps {\n vm: IFolderTreeViewModel;\n actions: IFolderTreeCallbacks;\n folderActions?: FolderActionConfig[];\n enableCreate?: boolean;\n enableActions?: boolean;\n dropConfirmation?: boolean;\n rootFolderLabel?: string;\n hiddenFolderIds?: string[];\n}\n\nexport interface UncontrolledFolderTreeProps extends Omit<\n PresenterFolderTreeProps,\n \"vm\" | \"actions\"\n> {\n focusedFolderId?: string | null;\n onFolderClick?: (folderId: string | null) => void;\n}\n\nexport const FolderTree = ({\n vm,\n actions,\n folderActions = [],\n enableCreate,\n enableActions,\n dropConfirmation = false,\n rootFolderLabel,\n hiddenFolderIds\n}: PresenterFolderTreeProps) => {\n const { showSnackbar } = useSnackbar();\n const { showDialog: showConfirmMoveFolderDialog } = useConfirmMoveFolderDialog();\n\n const focusedFolderId = vm.currentFolderId ?? ROOT_FOLDER;\n\n const folders = vm.folders;\n\n const localFolders = useMemo(() => {\n if (!folders.length) {\n return [];\n }\n return folders.map(item =>\n item.id === ROOT_FOLDER && rootFolderLabel ? { ...item, title: rootFolderLabel } : item\n );\n }, [folders, rootFolderLabel]);\n\n const [treeData, setTreeData] = useState<NodeDto<FolderDto>[]>([]);\n const [openFolderIds, setOpenFolderIds] = useState<string[]>([ROOT_FOLDER]);\n\n useEffect(() => {\n setTreeData(createTreeData(localFolders, focusedFolderId, hiddenFolderIds));\n }, [localFolders, focusedFolderId, hiddenFolderIds]);\n\n useEffect(() => {\n setOpenFolderIds(prev => {\n const expanded = createInitialOpenList(localFolders, prev, focusedFolderId);\n return [...new Set([ROOT_FOLDER, ...expanded])];\n });\n }, [focusedFolderId, localFolders]);\n\n const handleChangeOpen: TreeProps[\"onChangeOpen\"] = async nodes => {\n const folderIds = nodes.map(node => node.id);\n const updatedOpenIds = [...new Set([ROOT_FOLDER, ...folderIds])];\n const newlyOpened = updatedOpenIds.filter(id => !openFolderIds.includes(id));\n setOpenFolderIds(updatedOpenIds);\n\n if (newlyOpened.length > 0) {\n await actions.loadChildFolders(newlyOpened);\n }\n };\n\n const handleDrop: TreeProps[\"onDrop\"] = async (_, { dragSourceId, dropTargetId }) => {\n try {\n const targetParentId = dropTargetId !== ROOT_FOLDER ? (dropTargetId as string) : null;\n await actions.moveFolder(dragSourceId as string, targetParentId);\n } catch (error) {\n showSnackbar((error as Error).message);\n }\n };\n\n const onDrop = useCallback<NonNullable<TreeProps[\"onDrop\"]>>(\n async (newTree, options: DropOptions) => {\n const runDrop = async () => handleDrop(newTree, options);\n\n if (dropConfirmation) {\n const { dragSourceId, dropTargetId } = options;\n const folder = localFolders.find(f => f.id === dragSourceId);\n const targetFolder = localFolders.find(f => f.id === dropTargetId);\n\n if (!folder || !targetFolder) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n showConfirmMoveFolderDialog({\n folder,\n targetFolder,\n onAccept: async () => {\n await runDrop();\n resolve();\n },\n onClose: () => {\n reject(new Error(\"cancelled\"));\n }\n });\n });\n } else {\n await runDrop();\n }\n },\n [localFolders, dropConfirmation, showConfirmMoveFolderDialog]\n );\n\n const sort = useMemo(\n () => (a: NodeDto<any>, b: NodeDto<any>) => {\n if (a.id === ROOT_FOLDER || b.id === ROOT_FOLDER) {\n return 1;\n }\n return a.label.localeCompare(b.label, undefined, { numeric: true });\n },\n []\n );\n\n const canDrag: TreeProps<FolderDto>[\"canDrag\"] = useCallback(\n (node: NodeDto<FolderDto>) =>\n node.id !== ROOT_FOLDER && actions.canManageStructure(node.id),\n [actions]\n );\n\n const canDrop: TreeProps<FolderDto>[\"canDrop\"] = (_, options: DropOptions<FolderDto>) => {\n const { dragSourceId, dropTargetId } = options;\n const ancestorIds = actions.getAncestorIds(dropTargetId as string);\n return !(dragSourceId && ancestorIds.includes(dragSourceId as string));\n };\n\n const nodeRenderer: TreeProps<FolderDto>[\"renderer\"] = node => {\n const folder = localFolders.find(f => f.id === node.id);\n return (\n <FolderProvider folder={folder}>\n <Node enableActions={enableActions} folderActions={folderActions} />\n </FolderProvider>\n );\n };\n\n const handleNodeClick = useCallback(\n (node: WithDefaultNodeData<FolderDto>) => {\n actions.selectFolder(node.id === ROOT_FOLDER ? null : node.id);\n },\n [actions]\n );\n\n const createButton = useMemo(() => {\n if (!enableCreate) {\n return null;\n }\n\n const canCreate = actions.canManageStructure(focusedFolderId);\n const button = (\n <ButtonCreate\n disabled={!canCreate}\n onCreateFolder={() =>\n actions.createFolder(\n focusedFolderId === ROOT_FOLDER ? undefined : focusedFolderId\n )\n }\n />\n );\n\n return canCreate ? (\n button\n ) : (\n <Tooltip\n content={`Cannot create folder because you're not an owner.`}\n trigger={button}\n />\n );\n }, [enableCreate, actions, focusedFolderId, localFolders]);\n\n if (vm.loading) {\n return <Loader />;\n }\n\n return (\n <div className=\"my-xs\">\n <Tree<FolderDto>\n nodes={treeData}\n rootId={\"0\"}\n defaultOpenNodeIds={openFolderIds}\n onChangeOpen={handleChangeOpen}\n onDrop={onDrop}\n onNodeClick={handleNodeClick}\n sort={sort}\n canDrag={canDrag}\n canDrop={canDrop}\n renderer={nodeRenderer}\n defaultLockedOpenNodeIds={[ROOT_FOLDER]}\n loadingNodeIds={vm.loadingNodeIds}\n />\n {enableCreate && (\n <div className={\"m-xs-plus mt-sm-plus mb-lg pl-sm-extra\"}>{createButton}</div>\n )}\n <FolderOperationDialog operation={vm.operation} actions={actions} />\n </div>\n );\n};\n\nexport const UncontrolledFolderTree = ({\n focusedFolderId,\n onFolderClick,\n ...props\n}: UncontrolledFolderTreeProps) => {\n const { presenter } = useFeature(FolderTreePresenterFeature);\n\n const vm = useMemo(() => {\n if (focusedFolderId === undefined) {\n return presenter.vm;\n }\n return { ...presenter.vm, currentFolderId: focusedFolderId };\n }, [presenter.vm, focusedFolderId]);\n\n const actions = useMemo(() => {\n if (!onFolderClick) {\n return presenter;\n }\n return { ...presenter, selectFolder: onFolderClick };\n }, [presenter, onFolderClick]);\n\n return <FolderTree vm={vm} actions={actions} {...props} />;\n};\n"],"names":["t","i18n","FolderOperationDialog","observer","operation","actions","loading","setLoading","useState","handleClose","withLoading","fn","Dialog","OverlayLoader","Text","title","confirmLabel","loadingLabel","FormView","FolderTree","vm","folderActions","enableCreate","enableActions","dropConfirmation","rootFolderLabel","hiddenFolderIds","showSnackbar","useSnackbar","showConfirmMoveFolderDialog","useConfirmMoveFolderDialog","focusedFolderId","ROOT_FOLDER","folders","localFolders","useMemo","item","treeData","setTreeData","openFolderIds","setOpenFolderIds","useEffect","createTreeData","prev","expanded","createInitialOpenList","Set","handleChangeOpen","nodes","folderIds","node","updatedOpenIds","newlyOpened","id","handleDrop","_","dragSourceId","dropTargetId","targetParentId","error","onDrop","useCallback","newTree","options","runDrop","folder","f","targetFolder","Promise","resolve","reject","Error","sort","a","b","undefined","canDrag","canDrop","ancestorIds","nodeRenderer","FolderProvider","Node","handleNodeClick","createButton","canCreate","button","ButtonCreate","Tooltip","Loader","Tree","UncontrolledFolderTree","onFolderClick","props","presenter","useFeature","FolderTreePresenterFeature"],"mappings":"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"}
@@ -26,6 +26,7 @@ declare class FolderTreePresenterImpl implements Abstraction.Interface {
26
26
  private operation;
27
27
  private callbacks;
28
28
  private disposed;
29
+ private previousFolders;
29
30
  constructor(foldersContext: FoldersContext.Interface, foldersCache: FoldersCache.Interface, listFoldersUseCase: ListFoldersUseCase.Interface, listFoldersByParentIdsUseCase: ListFoldersByParentIdsUseCase.Interface, createFolderUseCase: CreateFolderUseCase.Interface, updateFolderUseCase: UpdateFolderUseCase.Interface, deleteFolderUseCase: DeleteFolderUseCase.Interface, getFolderAncestorsUseCase: GetFolderAncestorsUseCase.Interface, getFolderLevelPermissionUseCase: GetFolderLevelPermissionUseCase.Interface, formModelFactory: FormModelFactory.Interface);
30
31
  get vm(): IFolderTreeViewModel;
31
32
  selectFolder(folderId: string | null): void;
@@ -40,6 +41,7 @@ declare class FolderTreePresenterImpl implements Abstraction.Interface {
40
41
  deleteFolder(folderId: string): Promise<void>;
41
42
  cancelOperation(): void;
42
43
  private loadFolders;
44
+ private resolveValidFolderId;
43
45
  private buildTree;
44
46
  private buildTreeFromFolders;
45
47
  private findFolder;
@@ -33,14 +33,32 @@ class FolderTreePresenterImpl {
33
33
  };
34
34
  this.callbacks = new Set();
35
35
  this.disposed = false;
36
+ this.previousFolders = [];
36
37
  makeAutoObservable(this, {
37
- callbacks: false
38
+ callbacks: false,
39
+ previousFolders: false
38
40
  }, {
39
41
  autoBind: true
40
42
  });
41
43
  reaction(()=>this.currentFolderId, (folderId)=>{
42
44
  if (!this.disposed) this.callbacks.forEach((cb)=>cb(folderId));
43
45
  });
46
+ reaction(()=>({
47
+ folders: this.foldersCache.getItems(),
48
+ currentFolderId: this.currentFolderId
49
+ }), ({ folders, currentFolderId })=>{
50
+ if (null !== currentFolderId) {
51
+ const stillExists = folders.some((f)=>f.id === currentFolderId);
52
+ const isTransientReloadClear = 0 === folders.length && this.loading;
53
+ if (!stillExists && !isTransientReloadClear) {
54
+ const resolvedId = this.resolveValidFolderId(currentFolderId, this.previousFolders);
55
+ this.selectFolder(resolvedId);
56
+ }
57
+ }
58
+ this.previousFolders = folders;
59
+ }, {
60
+ fireImmediately: true
61
+ });
44
62
  this.loadFolders();
45
63
  }
46
64
  get vm() {
@@ -66,9 +84,10 @@ class FolderTreePresenterImpl {
66
84
  };
67
85
  }
68
86
  selectFolder(folderId) {
69
- this.currentFolderId = folderId;
70
- if (folderId) this.loadChildFolders([
71
- folderId
87
+ const normalized = folderId === ROOT_FOLDER ? null : folderId;
88
+ this.currentFolderId = normalized;
89
+ if (normalized) this.loadChildFolders([
90
+ normalized
72
91
  ]);
73
92
  }
74
93
  onFolderChange(callback) {
@@ -115,8 +134,8 @@ class FolderTreePresenterImpl {
115
134
  const form = this.formModelFactory.create({
116
135
  fields: (fields)=>({
117
136
  title: fields.text().label("Title").required("Title is required"),
118
- slug: fields.text().label("Slug").required("Slug is required").computedUntilDirty((f)=>{
119
- const title = f.field("title").getValue();
137
+ slug: fields.text().label("Slug").required("Slug is required").computedUntilDirty(({ form })=>{
138
+ const title = form.field("title").getValue();
120
139
  return slugify(String(title ?? ""), {
121
140
  replacement: "-",
122
141
  lower: true,
@@ -149,8 +168,8 @@ class FolderTreePresenterImpl {
149
168
  const form = this.formModelFactory.create({
150
169
  fields: (fields)=>({
151
170
  title: fields.text().label("Name").required("Name is required"),
152
- slug: fields.text().label("Slug").required("Slug is required").computedUntilDirty((f)=>{
153
- const title = f.field("title").getValue();
171
+ slug: fields.text().label("Slug").required("Slug is required").computedUntilDirty(({ form })=>{
172
+ const title = form.field("title").getValue();
154
173
  return slugify(String(title ?? ""), {
155
174
  replacement: "-",
156
175
  lower: true,
@@ -199,7 +218,6 @@ class FolderTreePresenterImpl {
199
218
  permissions: folder?.permissions ?? []
200
219
  });
201
220
  }
202
- await this.loadFolders();
203
221
  runInAction(()=>{
204
222
  this.operation = {
205
223
  active: false,
@@ -209,22 +227,18 @@ class FolderTreePresenterImpl {
209
227
  return true;
210
228
  }
211
229
  async deleteFolder(folderId) {
212
- const folders = this.foldersCache.getItems();
213
- const folder = folders.find((f)=>f.id === folderId);
214
- const parentId = folder?.parentId ?? null;
215
230
  this.operation = {
216
231
  active: true,
217
232
  mode: "delete",
218
233
  folderId
219
234
  };
220
235
  await this.deleteFolderUseCase.execute(folderId);
221
- await this.loadFolders();
222
236
  runInAction(()=>{
237
+ this.foldersCache.removeItems((f)=>f.id === folderId);
223
238
  this.operation = {
224
239
  active: false,
225
240
  mode: null
226
241
  };
227
- this.currentFolderId = parentId;
228
242
  });
229
243
  }
230
244
  cancelOperation() {
@@ -245,6 +259,18 @@ class FolderTreePresenterImpl {
245
259
  });
246
260
  }
247
261
  }
262
+ resolveValidFolderId(folderId, previousFolders) {
263
+ let candidateId = folderId;
264
+ const visited = new Set();
265
+ while(null !== candidateId){
266
+ if (visited.has(candidateId)) break;
267
+ visited.add(candidateId);
268
+ if (this.foldersCache.getItem((f)=>f.id === candidateId)) return candidateId;
269
+ const prev = previousFolders.find((f)=>f.id === candidateId);
270
+ candidateId = prev?.parentId ?? null;
271
+ }
272
+ return null;
273
+ }
248
274
  buildTree() {
249
275
  const folders = this.foldersCache.getItems();
250
276
  return this.buildTreeFromFolders(folders);
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/folderTree/FolderTreePresenter.js","sources":["../../../src/presentation/folderTree/FolderTreePresenter.ts"],"sourcesContent":["import { makeAutoObservable, reaction, runInAction } from \"mobx\";\nimport slugify from \"slugify\";\nimport {\n FolderTreePresenter as Abstraction,\n type IFolderTreeNode,\n type IFolderTreeViewModel,\n type IFolderOperationState\n} from \"./abstractions.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\nimport { FoldersCache, FoldersContext } from \"~/features/folders/abstractions.js\";\nimport { ListFoldersUseCase } from \"~/features/folders/listFolders/abstractions.js\";\nimport { ListFoldersByParentIdsUseCase } from \"~/features/folders/listFoldersByParentIds/abstractions.js\";\nimport { CreateFolderUseCase } from \"~/features/folders/createFolder/abstractions.js\";\nimport { UpdateFolderUseCase } from \"~/features/folders/updateFolder/abstractions.js\";\nimport { DeleteFolderUseCase } from \"~/features/folders/deleteFolder/abstractions.js\";\nimport { GetFolderAncestorsUseCase } from \"~/features/folders/getFolderAncestors/abstractions.js\";\nimport { GetFolderLevelPermissionUseCase } from \"~/features/folders/getFolderLevelPermission/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { Folder } from \"~/domain/folder/Folder.js\";\nimport type { FolderDto } from \"~/domain/folder/FolderDto.js\";\nimport { FolderDtoMapper } from \"~/domain/folder/FolderDtoMapper.js\";\n\ntype FolderChangeCallback = (folderId: string | null) => void;\n\nclass FolderTreePresenterImpl implements Abstraction.Interface {\n private currentFolderId: string | null = null;\n private loading = false;\n private _loadingNodeIds: string[] = [];\n private operation: IFolderOperationState = { active: false, mode: null };\n private callbacks: Set<FolderChangeCallback> = new Set();\n private disposed = false;\n\n constructor(\n private foldersContext: FoldersContext.Interface,\n private foldersCache: FoldersCache.Interface,\n private listFoldersUseCase: ListFoldersUseCase.Interface,\n private listFoldersByParentIdsUseCase: ListFoldersByParentIdsUseCase.Interface,\n private createFolderUseCase: CreateFolderUseCase.Interface,\n private updateFolderUseCase: UpdateFolderUseCase.Interface,\n private deleteFolderUseCase: DeleteFolderUseCase.Interface,\n private getFolderAncestorsUseCase: GetFolderAncestorsUseCase.Interface,\n private getFolderLevelPermissionUseCase: GetFolderLevelPermissionUseCase.Interface,\n private formModelFactory: FormModelFactory.Interface\n ) {\n makeAutoObservable<FolderTreePresenterImpl, \"callbacks\">(\n this,\n { callbacks: false },\n { autoBind: true }\n );\n\n reaction(\n () => this.currentFolderId,\n folderId => {\n if (!this.disposed) {\n this.callbacks.forEach(cb => cb(folderId));\n }\n }\n );\n\n void this.loadFolders();\n }\n\n get vm(): IFolderTreeViewModel {\n const tree = this.buildTree();\n const allFolders = this.foldersCache.getItems();\n const currentNode = this.findNode(this.currentFolderId, tree);\n const currentFolder = this.findFolder(this.currentFolderId);\n const childNodes = currentNode\n ? currentNode.children\n : tree.filter(n => n.id !== ROOT_FOLDER);\n return {\n folders: allFolders.map(f => FolderDtoMapper.toDTO(f)),\n tree,\n currentFolderId: this.currentFolderId,\n currentFolder: currentFolder ? FolderDtoMapper.toDTO(currentFolder) : null,\n isRootFolder: this.currentFolderId === null,\n currentFolderTitle: currentNode?.name ?? \"All Files\",\n childFolders: childNodes\n .map(n => {\n const folder = allFolders.find(f => f.id === n.id);\n return folder ? FolderDtoMapper.toDTO(folder) : null;\n })\n .filter((f): f is FolderDto => f !== null),\n loading: this.loading,\n loadingNodeIds: this._loadingNodeIds,\n operation: this.operation\n };\n }\n\n selectFolder(folderId: string | null): void {\n this.currentFolderId = folderId;\n if (folderId) {\n void this.loadChildFolders([folderId]);\n }\n }\n\n onFolderChange(callback: FolderChangeCallback): () => void {\n this.callbacks.add(callback);\n return () => {\n this.callbacks.delete(callback);\n };\n }\n\n async loadChildFolders(parentIds: string[]): Promise<void> {\n const fetchableIds = parentIds.filter(id => id !== ROOT_FOLDER && id !== \"0\");\n if (fetchableIds.length === 0) {\n return;\n }\n\n runInAction(() => {\n this._loadingNodeIds = fetchableIds;\n });\n\n try {\n await this.listFoldersByParentIdsUseCase.execute(fetchableIds);\n } finally {\n runInAction(() => {\n this._loadingNodeIds = [];\n });\n }\n }\n\n async moveFolder(folderId: string, targetParentId: string | null): Promise<void> {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n if (!folder) {\n return;\n }\n\n await this.updateFolderUseCase.execute({\n id: folderId,\n title: folder.title,\n slug: folder.slug,\n type: this.foldersContext.type,\n parentId: targetParentId,\n permissions: folder.permissions\n });\n\n await this.loadFolders();\n }\n\n canManageStructure(folderId: string): boolean {\n return this.getFolderLevelPermissionUseCase.execute(folderId, \"canManageStructure\");\n }\n\n getAncestorIds(folderId: string): string[] {\n return this.getFolderAncestorsUseCase.execute(folderId).map(f => f.id);\n }\n\n createFolder(parentFolderId?: string): void {\n const form = this.formModelFactory.create({\n fields: fields => ({\n title: fields.text().label(\"Title\").required(\"Title is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(f => {\n const title = f.field(\"title\").getValue();\n return slugify(String(title ?? \"\"), {\n replacement: \"-\",\n lower: true,\n remove: /[*#\\?<>_\\{\\}\\[\\]+~.()'\"!:;@]/g,\n trim: false\n });\n }),\n parentId: fields\n .text()\n .label(\"Parent folder\")\n .renderer(\"folderTree\" as any)\n }),\n layout: layout => [layout.row(\"title\"), layout.row(\"slug\"), layout.row(\"parentId\")]\n });\n\n form.setData({ parentId: parentFolderId ?? null });\n\n this.operation = {\n active: true,\n mode: \"create\",\n parentFolderId,\n form\n };\n }\n\n editFolder(folderId: string): void {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n if (!folder) {\n return;\n }\n\n const form = this.formModelFactory.create({\n fields: fields => ({\n title: fields.text().label(\"Name\").required(\"Name is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(f => {\n const title = f.field(\"title\").getValue();\n return slugify(String(title ?? \"\"), {\n replacement: \"-\",\n lower: true,\n remove: /[*#\\?<>_\\{\\}\\[\\]+~.()'\"!:;@]/g,\n trim: false\n });\n })\n }),\n layout: layout => [layout.row(\"title\"), layout.row(\"slug\")]\n });\n\n form.setData({ title: folder.title, slug: folder.slug });\n\n this.operation = {\n active: true,\n mode: \"edit\",\n folderId,\n form\n };\n }\n\n async submitOperation(): Promise<boolean> {\n const { mode, form, parentFolderId, folderId } = this.operation;\n if (!form || !mode) {\n return false;\n }\n\n const data = await form.submit<{ title: string; slug: string; parentId?: string | null }>();\n if (!data) {\n return false;\n }\n\n if (mode === \"create\") {\n await this.createFolderUseCase.execute({\n title: data.title,\n slug: data.slug,\n type: this.foldersContext.type,\n parentId: data.parentId ?? parentFolderId ?? null,\n permissions: []\n });\n } else if (mode === \"edit\" && folderId) {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n\n await this.updateFolderUseCase.execute({\n id: folderId,\n title: data.title,\n slug: data.slug,\n type: this.foldersContext.type,\n parentId: folder?.parentId ?? null,\n permissions: folder?.permissions ?? []\n });\n }\n\n await this.loadFolders();\n\n runInAction(() => {\n this.operation = { active: false, mode: null };\n });\n\n return true;\n }\n\n async deleteFolder(folderId: string): Promise<void> {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n const parentId = folder?.parentId ?? null;\n\n this.operation = {\n active: true,\n mode: \"delete\",\n folderId\n };\n\n await this.deleteFolderUseCase.execute(folderId);\n await this.loadFolders();\n\n runInAction(() => {\n this.operation = { active: false, mode: null };\n this.currentFolderId = parentId;\n });\n }\n\n cancelOperation(): void {\n this.operation = { active: false, mode: null };\n }\n\n private async loadFolders(): Promise<void> {\n runInAction(() => {\n this.loading = true;\n });\n\n try {\n await this.listFoldersUseCase.execute();\n } finally {\n runInAction(() => {\n this.loading = false;\n });\n }\n }\n\n private buildTree(): IFolderTreeNode[] {\n const folders = this.foldersCache.getItems();\n return this.buildTreeFromFolders(folders);\n }\n\n private buildTreeFromFolders(folders: Folder[]): IFolderTreeNode[] {\n const nodeMap = new Map<string, IFolderTreeNode>();\n\n for (const folder of folders) {\n nodeMap.set(folder.id, {\n id: folder.id,\n name: folder.title,\n slug: folder.slug,\n parentId: folder.parentId,\n children: [],\n hasNonInheritedPermissions: folder.hasNonInheritedPermissions ?? false,\n canManagePermissions: folder.canManagePermissions ?? false,\n canManageStructure: folder.canManageStructure ?? true\n });\n }\n\n const roots: IFolderTreeNode[] = [];\n for (const folder of folders) {\n const node = nodeMap.get(folder.id)!;\n if (folder.parentId && nodeMap.has(folder.parentId)) {\n nodeMap.get(folder.parentId)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n\n return roots;\n }\n\n private findFolder(folderId: string | null): Folder | null {\n if (!folderId) {\n return null;\n }\n\n return this.foldersCache.getItem(f => f.id === folderId) ?? null;\n }\n\n private findNode(folderId: string | null, nodes: IFolderTreeNode[]): IFolderTreeNode | null {\n if (folderId === null) {\n return null;\n }\n\n for (const node of nodes) {\n if (node.id === folderId) {\n return node;\n }\n const found = this.findNode(folderId, node.children);\n if (found) {\n return found;\n }\n }\n\n return null;\n }\n}\n\nexport const FolderTreePresenter = Abstraction.createImplementation({\n implementation: FolderTreePresenterImpl,\n dependencies: [\n FoldersContext,\n FoldersCache,\n ListFoldersUseCase,\n ListFoldersByParentIdsUseCase,\n CreateFolderUseCase,\n UpdateFolderUseCase,\n DeleteFolderUseCase,\n GetFolderAncestorsUseCase,\n GetFolderLevelPermissionUseCase,\n FormModelFactory\n ]\n});\n"],"names":["FolderTreePresenterImpl","foldersContext","foldersCache","listFoldersUseCase","listFoldersByParentIdsUseCase","createFolderUseCase","updateFolderUseCase","deleteFolderUseCase","getFolderAncestorsUseCase","getFolderLevelPermissionUseCase","formModelFactory","Set","makeAutoObservable","reaction","folderId","cb","tree","allFolders","currentNode","currentFolder","childNodes","n","ROOT_FOLDER","f","FolderDtoMapper","folder","callback","parentIds","fetchableIds","id","runInAction","targetParentId","folders","parentFolderId","form","fields","title","slugify","String","layout","mode","data","parentId","nodeMap","Map","roots","node","nodes","found","FolderTreePresenter","Abstraction","FoldersContext","FoldersCache","ListFoldersUseCase","ListFoldersByParentIdsUseCase","CreateFolderUseCase","UpdateFolderUseCase","DeleteFolderUseCase","GetFolderAncestorsUseCase","GetFolderLevelPermissionUseCase","FormModelFactory"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/folderTree/FolderTreePresenter.js","sources":["../../../src/presentation/folderTree/FolderTreePresenter.ts"],"sourcesContent":["import { makeAutoObservable, reaction, runInAction } from \"mobx\";\nimport slugify from \"slugify\";\nimport {\n FolderTreePresenter as Abstraction,\n type IFolderTreeNode,\n type IFolderTreeViewModel,\n type IFolderOperationState\n} from \"./abstractions.js\";\nimport { ROOT_FOLDER } from \"~/constants.js\";\nimport { FoldersCache, FoldersContext } from \"~/features/folders/abstractions.js\";\nimport { ListFoldersUseCase } from \"~/features/folders/listFolders/abstractions.js\";\nimport { ListFoldersByParentIdsUseCase } from \"~/features/folders/listFoldersByParentIds/abstractions.js\";\nimport { CreateFolderUseCase } from \"~/features/folders/createFolder/abstractions.js\";\nimport { UpdateFolderUseCase } from \"~/features/folders/updateFolder/abstractions.js\";\nimport { DeleteFolderUseCase } from \"~/features/folders/deleteFolder/abstractions.js\";\nimport { GetFolderAncestorsUseCase } from \"~/features/folders/getFolderAncestors/abstractions.js\";\nimport { GetFolderLevelPermissionUseCase } from \"~/features/folders/getFolderLevelPermission/abstractions.js\";\nimport { FormModelFactory } from \"@webiny/app-admin/features/formModel/abstractions.js\";\nimport type { Folder } from \"~/domain/folder/Folder.js\";\nimport type { FolderDto } from \"~/domain/folder/FolderDto.js\";\nimport { FolderDtoMapper } from \"~/domain/folder/FolderDtoMapper.js\";\n\ntype FolderChangeCallback = (folderId: string | null) => void;\n\nclass FolderTreePresenterImpl implements Abstraction.Interface {\n private currentFolderId: string | null = null;\n private loading = false;\n private _loadingNodeIds: string[] = [];\n private operation: IFolderOperationState = { active: false, mode: null };\n private callbacks: Set<FolderChangeCallback> = new Set();\n private disposed = false;\n\n private previousFolders: Folder[] = [];\n\n constructor(\n private foldersContext: FoldersContext.Interface,\n private foldersCache: FoldersCache.Interface,\n private listFoldersUseCase: ListFoldersUseCase.Interface,\n private listFoldersByParentIdsUseCase: ListFoldersByParentIdsUseCase.Interface,\n private createFolderUseCase: CreateFolderUseCase.Interface,\n private updateFolderUseCase: UpdateFolderUseCase.Interface,\n private deleteFolderUseCase: DeleteFolderUseCase.Interface,\n private getFolderAncestorsUseCase: GetFolderAncestorsUseCase.Interface,\n private getFolderLevelPermissionUseCase: GetFolderLevelPermissionUseCase.Interface,\n private formModelFactory: FormModelFactory.Interface\n ) {\n makeAutoObservable<FolderTreePresenterImpl, \"callbacks\" | \"previousFolders\">(\n this,\n { callbacks: false, previousFolders: false },\n { autoBind: true }\n );\n\n reaction(\n () => this.currentFolderId,\n folderId => {\n if (!this.disposed) {\n this.callbacks.forEach(cb => cb(folderId));\n }\n }\n );\n\n reaction(\n () => ({\n folders: this.foldersCache.getItems(),\n currentFolderId: this.currentFolderId\n }),\n ({ folders, currentFolderId }) => {\n if (currentFolderId !== null) {\n const stillExists = folders.some(f => f.id === currentFolderId);\n // Skip when folders is empty *and* a reload is in flight — the cache is\n // cleared before being repopulated, so this is a transient state, not a\n // real \"all folders were removed\" event.\n const isTransientReloadClear = folders.length === 0 && this.loading;\n if (!stillExists && !isTransientReloadClear) {\n const resolvedId = this.resolveValidFolderId(\n currentFolderId,\n this.previousFolders\n );\n this.selectFolder(resolvedId);\n }\n }\n\n this.previousFolders = folders;\n },\n { fireImmediately: true }\n );\n\n void this.loadFolders();\n }\n\n get vm(): IFolderTreeViewModel {\n const tree = this.buildTree();\n const allFolders = this.foldersCache.getItems();\n const currentNode = this.findNode(this.currentFolderId, tree);\n const currentFolder = this.findFolder(this.currentFolderId);\n const childNodes = currentNode\n ? currentNode.children\n : tree.filter(n => n.id !== ROOT_FOLDER);\n return {\n folders: allFolders.map(f => FolderDtoMapper.toDTO(f)),\n tree,\n currentFolderId: this.currentFolderId,\n currentFolder: currentFolder ? FolderDtoMapper.toDTO(currentFolder) : null,\n isRootFolder: this.currentFolderId === null,\n currentFolderTitle: currentNode?.name ?? \"All Files\",\n childFolders: childNodes\n .map(n => {\n const folder = allFolders.find(f => f.id === n.id);\n return folder ? FolderDtoMapper.toDTO(folder) : null;\n })\n .filter((f): f is FolderDto => f !== null),\n loading: this.loading,\n loadingNodeIds: this._loadingNodeIds,\n operation: this.operation\n };\n }\n\n selectFolder(folderId: string | null): void {\n const normalized = folderId === ROOT_FOLDER ? null : folderId;\n this.currentFolderId = normalized;\n if (normalized) {\n void this.loadChildFolders([normalized]);\n }\n }\n\n onFolderChange(callback: FolderChangeCallback): () => void {\n this.callbacks.add(callback);\n return () => {\n this.callbacks.delete(callback);\n };\n }\n\n async loadChildFolders(parentIds: string[]): Promise<void> {\n const fetchableIds = parentIds.filter(id => id !== ROOT_FOLDER && id !== \"0\");\n if (fetchableIds.length === 0) {\n return;\n }\n\n runInAction(() => {\n this._loadingNodeIds = fetchableIds;\n });\n\n try {\n await this.listFoldersByParentIdsUseCase.execute(fetchableIds);\n } finally {\n runInAction(() => {\n this._loadingNodeIds = [];\n });\n }\n }\n\n async moveFolder(folderId: string, targetParentId: string | null): Promise<void> {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n if (!folder) {\n return;\n }\n\n await this.updateFolderUseCase.execute({\n id: folderId,\n title: folder.title,\n slug: folder.slug,\n type: this.foldersContext.type,\n parentId: targetParentId,\n permissions: folder.permissions\n });\n\n await this.loadFolders();\n }\n\n canManageStructure(folderId: string): boolean {\n return this.getFolderLevelPermissionUseCase.execute(folderId, \"canManageStructure\");\n }\n\n getAncestorIds(folderId: string): string[] {\n return this.getFolderAncestorsUseCase.execute(folderId).map(f => f.id);\n }\n\n createFolder(parentFolderId?: string): void {\n const form = this.formModelFactory.create({\n fields: fields => ({\n title: fields.text().label(\"Title\").required(\"Title is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(({ form }) => {\n const title = form.field(\"title\").getValue();\n return slugify(String(title ?? \"\"), {\n replacement: \"-\",\n lower: true,\n remove: /[*#\\?<>_\\{\\}\\[\\]+~.()'\"!:;@]/g,\n trim: false\n });\n }),\n parentId: fields\n .text()\n .label(\"Parent folder\")\n .renderer(\"folderTree\" as any)\n }),\n layout: layout => [layout.row(\"title\"), layout.row(\"slug\"), layout.row(\"parentId\")]\n });\n\n form.setData({ parentId: parentFolderId ?? null });\n\n this.operation = {\n active: true,\n mode: \"create\",\n parentFolderId,\n form\n };\n }\n\n editFolder(folderId: string): void {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n if (!folder) {\n return;\n }\n\n const form = this.formModelFactory.create({\n fields: fields => ({\n title: fields.text().label(\"Name\").required(\"Name is required\"),\n slug: fields\n .text()\n .label(\"Slug\")\n .required(\"Slug is required\")\n .computedUntilDirty(({ form }) => {\n const title = form.field(\"title\").getValue();\n return slugify(String(title ?? \"\"), {\n replacement: \"-\",\n lower: true,\n remove: /[*#\\?<>_\\{\\}\\[\\]+~.()'\"!:;@]/g,\n trim: false\n });\n })\n }),\n layout: layout => [layout.row(\"title\"), layout.row(\"slug\")]\n });\n\n form.setData({ title: folder.title, slug: folder.slug });\n\n this.operation = {\n active: true,\n mode: \"edit\",\n folderId,\n form\n };\n }\n\n async submitOperation(): Promise<boolean> {\n const { mode, form, parentFolderId, folderId } = this.operation;\n if (!form || !mode) {\n return false;\n }\n\n const data = await form.submit<{ title: string; slug: string; parentId?: string | null }>();\n if (!data) {\n return false;\n }\n\n if (mode === \"create\") {\n await this.createFolderUseCase.execute({\n title: data.title,\n slug: data.slug,\n type: this.foldersContext.type,\n parentId: data.parentId ?? parentFolderId ?? null,\n permissions: []\n });\n } else if (mode === \"edit\" && folderId) {\n const folders = this.foldersCache.getItems();\n const folder = folders.find(f => f.id === folderId);\n\n await this.updateFolderUseCase.execute({\n id: folderId,\n title: data.title,\n slug: data.slug,\n type: this.foldersContext.type,\n parentId: folder?.parentId ?? null,\n permissions: folder?.permissions ?? []\n });\n }\n\n runInAction(() => {\n this.operation = { active: false, mode: null };\n });\n\n return true;\n }\n\n async deleteFolder(folderId: string): Promise<void> {\n this.operation = {\n active: true,\n mode: \"delete\",\n folderId\n };\n\n await this.deleteFolderUseCase.execute(folderId);\n\n runInAction(() => {\n this.foldersCache.removeItems(f => f.id === folderId);\n this.operation = { active: false, mode: null };\n });\n }\n\n cancelOperation(): void {\n this.operation = { active: false, mode: null };\n }\n\n private async loadFolders(): Promise<void> {\n runInAction(() => {\n this.loading = true;\n });\n\n try {\n await this.listFoldersUseCase.execute();\n } finally {\n runInAction(() => {\n this.loading = false;\n });\n }\n }\n\n private resolveValidFolderId(\n folderId: string | null,\n previousFolders: Folder[]\n ): string | null {\n let candidateId = folderId;\n const visited = new Set<string>();\n\n while (candidateId !== null) {\n if (visited.has(candidateId)) {\n return null;\n }\n visited.add(candidateId);\n\n if (this.foldersCache.getItem(f => f.id === candidateId)) {\n return candidateId;\n }\n\n const prev = previousFolders.find(f => f.id === candidateId);\n candidateId = prev?.parentId ?? null;\n }\n\n return null;\n }\n\n private buildTree(): IFolderTreeNode[] {\n const folders = this.foldersCache.getItems();\n return this.buildTreeFromFolders(folders);\n }\n\n private buildTreeFromFolders(folders: Folder[]): IFolderTreeNode[] {\n const nodeMap = new Map<string, IFolderTreeNode>();\n\n for (const folder of folders) {\n nodeMap.set(folder.id, {\n id: folder.id,\n name: folder.title,\n slug: folder.slug,\n parentId: folder.parentId,\n children: [],\n hasNonInheritedPermissions: folder.hasNonInheritedPermissions ?? false,\n canManagePermissions: folder.canManagePermissions ?? false,\n canManageStructure: folder.canManageStructure ?? true\n });\n }\n\n const roots: IFolderTreeNode[] = [];\n for (const folder of folders) {\n const node = nodeMap.get(folder.id)!;\n if (folder.parentId && nodeMap.has(folder.parentId)) {\n nodeMap.get(folder.parentId)!.children.push(node);\n } else {\n roots.push(node);\n }\n }\n\n return roots;\n }\n\n private findFolder(folderId: string | null): Folder | null {\n if (!folderId) {\n return null;\n }\n\n return this.foldersCache.getItem(f => f.id === folderId) ?? null;\n }\n\n private findNode(folderId: string | null, nodes: IFolderTreeNode[]): IFolderTreeNode | null {\n if (folderId === null) {\n return null;\n }\n\n for (const node of nodes) {\n if (node.id === folderId) {\n return node;\n }\n const found = this.findNode(folderId, node.children);\n if (found) {\n return found;\n }\n }\n\n return null;\n }\n}\n\nexport const FolderTreePresenter = Abstraction.createImplementation({\n implementation: FolderTreePresenterImpl,\n dependencies: [\n FoldersContext,\n FoldersCache,\n ListFoldersUseCase,\n ListFoldersByParentIdsUseCase,\n CreateFolderUseCase,\n UpdateFolderUseCase,\n DeleteFolderUseCase,\n GetFolderAncestorsUseCase,\n GetFolderLevelPermissionUseCase,\n FormModelFactory\n ]\n});\n"],"names":["FolderTreePresenterImpl","foldersContext","foldersCache","listFoldersUseCase","listFoldersByParentIdsUseCase","createFolderUseCase","updateFolderUseCase","deleteFolderUseCase","getFolderAncestorsUseCase","getFolderLevelPermissionUseCase","formModelFactory","Set","makeAutoObservable","reaction","folderId","cb","folders","currentFolderId","stillExists","f","isTransientReloadClear","resolvedId","tree","allFolders","currentNode","currentFolder","childNodes","n","ROOT_FOLDER","FolderDtoMapper","folder","normalized","callback","parentIds","fetchableIds","id","runInAction","targetParentId","parentFolderId","form","fields","title","slugify","String","layout","mode","data","previousFolders","candidateId","visited","prev","nodeMap","Map","roots","node","nodes","found","FolderTreePresenter","Abstraction","FoldersContext","FoldersCache","ListFoldersUseCase","ListFoldersByParentIdsUseCase","CreateFolderUseCase","UpdateFolderUseCase","DeleteFolderUseCase","GetFolderAncestorsUseCase","GetFolderLevelPermissionUseCase","FormModelFactory"],"mappings":"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"}