@webiny/app-file-manager 6.4.11 → 6.6.0-alpha.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 (235) hide show
  1. package/app.js +21 -2
  2. package/app.js.map +1 -1
  3. package/domain/tagsHelpers.d.ts +2 -2
  4. package/domain/types.d.ts +0 -8
  5. package/features/permissions/abstractions.d.ts +2 -2
  6. package/features/permissions/feature.d.ts +3 -3
  7. package/features/shared/FILE_FIELDS.js +4 -0
  8. package/features/shared/FILE_FIELDS.js.map +1 -1
  9. package/features/shared/FileFieldsProviderWithWcp.d.ts +5 -5
  10. package/features/shared/FileFieldsProviderWithWcp.js +7 -7
  11. package/features/shared/FileFieldsProviderWithWcp.js.map +1 -1
  12. package/modules/AiEnrichment/AiImageEnrichmentEventHandler.d.ts +18 -0
  13. package/modules/AiEnrichment/AiImageEnrichmentEventHandler.js +33 -0
  14. package/modules/AiEnrichment/AiImageEnrichmentEventHandler.js.map +1 -0
  15. package/modules/AiEnrichment/ReenrichFileGateway.d.ts +12 -0
  16. package/modules/AiEnrichment/ReenrichFileGateway.js +23 -0
  17. package/modules/AiEnrichment/ReenrichFileGateway.js.map +1 -0
  18. package/modules/AiEnrichment/ReenrichWithAi.d.ts +11 -0
  19. package/modules/AiEnrichment/ReenrichWithAi.js +57 -0
  20. package/modules/AiEnrichment/ReenrichWithAi.js.map +1 -0
  21. package/modules/AiEnrichment/ReenrichWithAiPresenter.d.ts +50 -0
  22. package/modules/AiEnrichment/ReenrichWithAiPresenter.js +114 -0
  23. package/modules/AiEnrichment/ReenrichWithAiPresenter.js.map +1 -0
  24. package/modules/AiEnrichment/StreamingPlaceholder.d.ts +15 -0
  25. package/modules/AiEnrichment/StreamingPlaceholder.js +32 -0
  26. package/modules/AiEnrichment/StreamingPlaceholder.js.map +1 -0
  27. package/modules/AiEnrichment/abstractions.d.ts +70 -0
  28. package/modules/AiEnrichment/abstractions.js +6 -0
  29. package/modules/AiEnrichment/abstractions.js.map +1 -0
  30. package/modules/AiEnrichment/feature.d.ts +3 -0
  31. package/modules/AiEnrichment/feature.js +21 -0
  32. package/modules/AiEnrichment/feature.js.map +1 -0
  33. package/modules/AiEnrichment/index.d.ts +2 -0
  34. package/modules/AiEnrichment/index.js +9 -0
  35. package/modules/AiEnrichment/index.js.map +1 -0
  36. package/modules/Enterprise/index.js +3 -3
  37. package/modules/Enterprise/index.js.map +1 -1
  38. package/modules/HeadlessCms/fieldType/AssetFieldSettingsModifier.d.ts +26 -0
  39. package/modules/HeadlessCms/fieldType/AssetFieldSettingsModifier.js +39 -0
  40. package/modules/HeadlessCms/fieldType/AssetFieldSettingsModifier.js.map +1 -0
  41. package/modules/HeadlessCms/fieldType/AssetFieldType.d.ts +34 -0
  42. package/modules/HeadlessCms/fieldType/AssetFieldType.js +42 -0
  43. package/modules/HeadlessCms/fieldType/AssetFieldType.js.map +1 -0
  44. package/modules/HeadlessCms/fieldType/AssetFormFieldType.d.ts +21 -0
  45. package/modules/HeadlessCms/fieldType/AssetFormFieldType.js +42 -0
  46. package/modules/HeadlessCms/fieldType/AssetFormFieldType.js.map +1 -0
  47. package/modules/HeadlessCms/fieldType/AssetInputRenderer.d.ts +15 -0
  48. package/modules/HeadlessCms/fieldType/AssetInputRenderer.js +20 -0
  49. package/modules/HeadlessCms/fieldType/AssetInputRenderer.js.map +1 -0
  50. package/modules/HeadlessCms/fieldType/AssetInputsRenderer.d.ts +15 -0
  51. package/modules/HeadlessCms/fieldType/AssetInputsRenderer.js +20 -0
  52. package/modules/HeadlessCms/fieldType/AssetInputsRenderer.js.map +1 -0
  53. package/modules/HeadlessCms/fieldType/FileFieldSettingsModifier.d.ts +16 -0
  54. package/modules/HeadlessCms/fieldType/FileFieldSettingsModifier.js +33 -0
  55. package/modules/HeadlessCms/fieldType/FileFieldSettingsModifier.js.map +1 -0
  56. package/modules/HeadlessCms/fieldType/FileFieldType.d.ts +25 -0
  57. package/modules/HeadlessCms/fieldType/FileFieldType.js +38 -0
  58. package/modules/HeadlessCms/fieldType/FileFieldType.js.map +1 -0
  59. package/modules/HeadlessCms/fieldType/FileInputRenderer.d.ts +15 -0
  60. package/modules/HeadlessCms/fieldType/FileInputRenderer.js +19 -0
  61. package/modules/HeadlessCms/fieldType/FileInputRenderer.js.map +1 -0
  62. package/modules/HeadlessCms/fieldType/FileInputsRenderer.d.ts +15 -0
  63. package/modules/HeadlessCms/fieldType/FileInputsRenderer.js +19 -0
  64. package/modules/HeadlessCms/fieldType/FileInputsRenderer.js.map +1 -0
  65. package/modules/HeadlessCms/fieldType/feature.d.ts +1 -0
  66. package/modules/HeadlessCms/fieldType/feature.js +27 -0
  67. package/modules/HeadlessCms/fieldType/feature.js.map +1 -0
  68. package/modules/HeadlessCms/fieldType/isAssetField.d.ts +2 -0
  69. package/modules/HeadlessCms/fieldType/isAssetField.js +4 -0
  70. package/modules/HeadlessCms/fieldType/isAssetField.js.map +1 -0
  71. package/package.json +24 -34
  72. package/presentation/FileActions/FileDetails/EditImage.d.ts +2 -0
  73. package/presentation/FileActions/FileDetails/EditImage.js +39 -0
  74. package/presentation/FileActions/FileDetails/EditImage.js.map +1 -0
  75. package/presentation/FileActions/index.js +8 -0
  76. package/presentation/FileActions/index.js.map +1 -1
  77. package/presentation/FileDetails/FileDetailsPresenter.d.ts +5 -4
  78. package/presentation/FileDetails/FileDetailsPresenter.js +40 -46
  79. package/presentation/FileDetails/FileDetailsPresenter.js.map +1 -1
  80. package/presentation/FileDetails/FileDetailsPresenter.test.js +39 -56
  81. package/presentation/FileDetails/FileDetailsPresenter.test.js.map +1 -1
  82. package/presentation/FileDetails/abstractions.d.ts +2 -0
  83. package/presentation/FileDetails/abstractions.js.map +1 -1
  84. package/presentation/FileDetails/components/Content.d.ts +6 -4
  85. package/presentation/FileDetails/components/Content.js +2 -2
  86. package/presentation/FileDetails/components/Content.js.map +1 -1
  87. package/presentation/FileDetails/components/FileDetailsDrawer.d.ts +2 -2
  88. package/presentation/FileDetails/components/FileDetailsDrawer.js +11 -5
  89. package/presentation/FileDetails/components/FileDetailsDrawer.js.map +1 -1
  90. package/presentation/FileList/FileListDataSource.d.ts +8 -12
  91. package/presentation/FileList/FileListDataSource.js +47 -87
  92. package/presentation/FileList/FileListDataSource.js.map +1 -1
  93. package/presentation/FileList/FileListPresenter.test.js +9 -3
  94. package/presentation/FileList/FileListPresenter.test.js.map +1 -1
  95. package/presentation/FileList/FileManagerPresenter.d.ts +1 -0
  96. package/presentation/FileList/FileManagerPresenter.js +15 -5
  97. package/presentation/FileList/FileManagerPresenter.js.map +1 -1
  98. package/presentation/FileList/abstractions.d.ts +3 -0
  99. package/presentation/FileList/abstractions.js.map +1 -1
  100. package/presentation/FileList/components/BulkActions/BulkActionBar.d.ts +2 -2
  101. package/presentation/FileList/components/BulkActions/BulkActionDelete.d.ts +2 -2
  102. package/presentation/FileList/components/BulkActions/BulkActionMove.d.ts +2 -2
  103. package/presentation/FileList/components/BulkActions/index.d.ts +0 -1
  104. package/presentation/FileList/components/BulkActions/index.js +0 -1
  105. package/presentation/FileList/components/BulkActions/useBulkActionWorker.d.ts +9 -8
  106. package/presentation/FileList/components/BulkActions/useBulkActionWorker.js +3 -9
  107. package/presentation/FileList/components/BulkActions/useBulkActionWorker.js.map +1 -1
  108. package/presentation/FileList/components/Filters/SubFoldersToggle.d.ts +2 -2
  109. package/presentation/FileList/components/Filters/TagsFilter.d.ts +2 -2
  110. package/presentation/FileList/components/Filters/TypeFilter.d.ts +2 -2
  111. package/presentation/FileList/components/Grid/FileGrid.d.ts +2 -2
  112. package/presentation/FileList/components/Grid/FileGrid.js +1 -1
  113. package/presentation/FileList/components/Grid/FileGrid.js.map +1 -1
  114. package/presentation/FileList/components/Grid/FileGrid.test.js +18 -7
  115. package/presentation/FileList/components/Grid/FileGrid.test.js.map +1 -1
  116. package/presentation/FileList/components/Header/FileManagerHeader.d.ts +2 -2
  117. package/presentation/FileList/components/Search/SearchBar.d.ts +2 -2
  118. package/presentation/FileList/components/Table/FileTable.d.ts +2 -2
  119. package/presentation/FileList/components/Table/FileTable.js +1 -1
  120. package/presentation/FileList/components/Table/FileTable.js.map +1 -1
  121. package/presentation/FileList/components/Table/FileTable.test.js +9 -4
  122. package/presentation/FileList/components/Table/FileTable.test.js.map +1 -1
  123. package/presentation/FileList/components/Upload/UploadProgress.d.ts +2 -2
  124. package/presentation/FileManager/FileManagerBreadcrumbs.d.ts +12 -0
  125. package/presentation/FileManager/FileManagerBreadcrumbs.js +37 -0
  126. package/presentation/FileManager/FileManagerBreadcrumbs.js.map +1 -0
  127. package/presentation/FileManager/FileManagerView.js +36 -2
  128. package/presentation/FileManager/FileManagerView.js.map +1 -1
  129. package/presentation/FileManager/RouteParamsSync.d.ts +2 -0
  130. package/presentation/FileManager/RouteParamsSync.js +30 -0
  131. package/presentation/FileManager/RouteParamsSync.js.map +1 -0
  132. package/presentation/Settings/components/SettingsView.d.ts +2 -2
  133. package/presentation/config/DefaultFileManagerConfig.js +13 -11
  134. package/presentation/config/DefaultFileManagerConfig.js.map +1 -1
  135. package/presentation/config/FileManagerViewConfig.d.ts +19 -25
  136. package/presentation/config/configComponents/Browser/BulkAction.d.ts +10 -8
  137. package/presentation/config/configComponents/Browser/BulkAction.js +3 -9
  138. package/presentation/config/configComponents/Browser/BulkAction.js.map +1 -1
  139. package/presentation/config/configComponents/Browser/FileAction.d.ts +2 -1
  140. package/presentation/config/configComponents/Browser/FolderAction.d.ts +2 -1
  141. package/presentation/config/configComponents/Browser/Table/Column.d.ts +9 -8
  142. package/presentation/config/configComponents/Browser/Table/index.d.ts +9 -9
  143. package/presentation/config/configComponents/Browser/index.d.ts +20 -20
  144. package/presentation/config/configComponents/Browser/index.js +0 -8
  145. package/presentation/config/configComponents/Browser/index.js.map +1 -1
  146. package/presentation/config/configComponents/FileDetails/index.d.ts +4 -2
  147. package/presentation/config/thumbnailRenderers/CroppedFileImage.d.ts +18 -0
  148. package/presentation/config/thumbnailRenderers/CroppedFileImage.js +66 -0
  149. package/presentation/config/thumbnailRenderers/CroppedFileImage.js.map +1 -0
  150. package/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js +6 -9
  151. package/presentation/config/thumbnailRenderers/FilePreviewImageRenderer.js.map +1 -1
  152. package/presentation/config/thumbnailRenderers/GridItemImageRenderer.js +6 -9
  153. package/presentation/config/thumbnailRenderers/GridItemImageRenderer.js.map +1 -1
  154. package/presentation/config/thumbnailRenderers/TableItemImageRenderer.js +6 -9
  155. package/presentation/config/thumbnailRenderers/TableItemImageRenderer.js.map +1 -1
  156. package/presentation/fieldRenderers/CmsAssetPickerRenderer.d.ts +22 -0
  157. package/presentation/fieldRenderers/CmsAssetPickerRenderer.js +56 -0
  158. package/presentation/fieldRenderers/CmsAssetPickerRenderer.js.map +1 -0
  159. package/presentation/fieldRenderers/CmsFilePickerRenderer.d.ts +13 -0
  160. package/presentation/fieldRenderers/CmsFilePickerRenderer.js +36 -0
  161. package/presentation/fieldRenderers/CmsFilePickerRenderer.js.map +1 -0
  162. package/presentation/fieldRenderers/CmsImageEditorDialog.d.ts +7 -0
  163. package/presentation/fieldRenderers/CmsImageEditorDialog.js +32 -0
  164. package/presentation/fieldRenderers/CmsImageEditorDialog.js.map +1 -0
  165. package/presentation/fieldRenderers/CmsMultiAssetPickerRenderer.d.ts +18 -0
  166. package/presentation/fieldRenderers/CmsMultiAssetPickerRenderer.js +88 -0
  167. package/presentation/fieldRenderers/CmsMultiAssetPickerRenderer.js.map +1 -0
  168. package/presentation/fieldRenderers/CmsMultiFilePickerRenderer.d.ts +13 -0
  169. package/presentation/fieldRenderers/CmsMultiFilePickerRenderer.js +60 -0
  170. package/presentation/fieldRenderers/CmsMultiFilePickerRenderer.js.map +1 -0
  171. package/presentation/fieldRenderers/CroppedAssetThumb.d.ts +15 -0
  172. package/presentation/fieldRenderers/CroppedAssetThumb.js +25 -0
  173. package/presentation/fieldRenderers/CroppedAssetThumb.js.map +1 -0
  174. package/presentation/fieldRenderers/assetValue.d.ts +10 -0
  175. package/presentation/fieldRenderers/assetValue.js +88 -0
  176. package/presentation/fieldRenderers/assetValue.js.map +1 -0
  177. package/presentation/hooks/useCmsImageEditor.d.ts +10 -0
  178. package/presentation/hooks/useCmsImageEditor.js +76 -0
  179. package/presentation/hooks/useCmsImageEditor.js.map +1 -0
  180. package/presentation/hooks/useEditImage.d.ts +14 -0
  181. package/presentation/hooks/useEditImage.js +67 -0
  182. package/presentation/hooks/useEditImage.js.map +1 -0
  183. package/routes.d.ts +1 -0
  184. package/routes.js +2 -1
  185. package/routes.js.map +1 -1
  186. package/modules/HeadlessCms/fileField.d.ts +0 -2
  187. package/modules/HeadlessCms/fileField.js +0 -44
  188. package/modules/HeadlessCms/fileField.js.map +0 -1
  189. package/modules/HeadlessCms/fileRenderer/fileField.d.ts +0 -2
  190. package/modules/HeadlessCms/fileRenderer/fileField.js +0 -53
  191. package/modules/HeadlessCms/fileRenderer/fileField.js.map +0 -1
  192. package/modules/HeadlessCms/fileRenderer/fileFields.d.ts +0 -2
  193. package/modules/HeadlessCms/fileRenderer/fileFields.js +0 -73
  194. package/modules/HeadlessCms/fileRenderer/fileFields.js.map +0 -1
  195. package/modules/HeadlessCms/fileRenderer/utils.d.ts +0 -2
  196. package/modules/HeadlessCms/fileRenderer/utils.js +0 -15
  197. package/modules/HeadlessCms/fileRenderer/utils.js.map +0 -1
  198. package/modules/HeadlessCms/index.d.ts +0 -1
  199. package/modules/HeadlessCms/index.js +0 -14
  200. package/modules/HeadlessCms/index.js.map +0 -1
  201. package/modules/Settings/graphql.d.ts +0 -12
  202. package/modules/Settings/graphql.js +0 -36
  203. package/modules/Settings/graphql.js.map +0 -1
  204. package/modules/Settings/views/FileManagerSettings.d.ts +0 -2
  205. package/modules/Settings/views/FileManagerSettings.js +0 -134
  206. package/modules/Settings/views/FileManagerSettings.js.map +0 -1
  207. package/presentation/FileList/components/BulkActions/BatchEditorDialog/AddOperation.d.ts +0 -7
  208. package/presentation/FileList/components/BulkActions/BatchEditorDialog/AddOperation.js +0 -15
  209. package/presentation/FileList/components/BulkActions/BatchEditorDialog/AddOperation.js.map +0 -1
  210. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditor.d.ts +0 -15
  211. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditor.js +0 -44
  212. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditor.js.map +0 -1
  213. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialog.d.ts +0 -15
  214. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialog.js +0 -52
  215. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialog.js.map +0 -1
  216. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialogPresenter.d.ts +0 -61
  217. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialogPresenter.js +0 -111
  218. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialogPresenter.js.map +0 -1
  219. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialogPresenter.test.d.ts +0 -1
  220. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialogPresenter.test.js +0 -372
  221. package/presentation/FileList/components/BulkActions/BatchEditorDialog/BatchEditorDialogPresenter.test.js.map +0 -1
  222. package/presentation/FileList/components/BulkActions/BatchEditorDialog/FieldRenderer.d.ts +0 -8
  223. package/presentation/FileList/components/BulkActions/BatchEditorDialog/FieldRenderer.js +0 -31
  224. package/presentation/FileList/components/BulkActions/BatchEditorDialog/FieldRenderer.js.map +0 -1
  225. package/presentation/FileList/components/BulkActions/BatchEditorDialog/Operation.d.ts +0 -11
  226. package/presentation/FileList/components/BulkActions/BatchEditorDialog/Operation.js +0 -33
  227. package/presentation/FileList/components/BulkActions/BatchEditorDialog/Operation.js.map +0 -1
  228. package/presentation/FileList/components/BulkActions/BatchEditorDialog/index.d.ts +0 -1
  229. package/presentation/FileList/components/BulkActions/BatchEditorDialog/index.js +0 -1
  230. package/presentation/FileList/components/BulkActions/BulkActionEdit.d.ts +0 -4
  231. package/presentation/FileList/components/BulkActions/BulkActionEdit.js +0 -105
  232. package/presentation/FileList/components/BulkActions/BulkActionEdit.js.map +0 -1
  233. package/presentation/config/configComponents/Browser/FolderFieldDecorator.d.ts +0 -7
  234. package/presentation/config/configComponents/Browser/FolderFieldDecorator.js +0 -11
  235. package/presentation/config/configComponents/Browser/FolderFieldDecorator.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/FileList/FileListDataSource.js","sources":["../../../src/presentation/FileList/FileListDataSource.ts"],"sourcesContent":["import { makeAutoObservable, runInAction, computed } from \"mobx\";\nimport type {\n IDataSource,\n IDataSourceQuery,\n IDataSourceMeta\n} from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { IListFilesUseCase } from \"../../features/listFiles/abstractions.js\";\nimport type { IGetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport type { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\nimport { DEFAULT_SCOPE } from \"~/domain/constants.js\";\n\nexport class FileListDataSource implements IDataSource<FmFile> {\n private _meta: IDataSourceMeta = { cursor: null, hasMoreItems: false, totalCount: 0 };\n private _loading = false;\n\n constructor(\n private listFilesUseCase: IListFilesUseCase,\n private cache: IListCache<FmFile>,\n private getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase,\n private scope?: string\n ) {\n makeAutoObservable<FileListDataSource, \"listFilesUseCase\" | \"getDescendantFoldersUseCase\">(\n this,\n {\n listFilesUseCase: false,\n getDescendantFoldersUseCase: false,\n rows: computed\n }\n );\n }\n\n get rows(): FmFile[] {\n return this.cache.getItems();\n }\n\n get meta(): IDataSourceMeta {\n return this._meta;\n }\n\n get loading(): boolean {\n return this._loading;\n }\n\n async query(params: IDataSourceQuery): Promise<void> {\n this._loading = true;\n this.cache.clear();\n\n const where = this.buildWhere(params);\n const sort = params.sort ? [`${params.sort.field}_${params.sort.direction}`] : undefined;\n\n const result = await this.listFilesUseCase.execute({\n search: params.search,\n where,\n sort,\n limit: params.limit,\n after: params.cursor\n });\n\n runInAction(() => {\n this.cache.addItems(result.data);\n this._meta = {\n cursor: result.meta.cursor,\n hasMoreItems: result.meta.hasMoreItems,\n totalCount: result.meta.totalCount\n };\n this._loading = false;\n });\n }\n\n async loadMore(params: IDataSourceQuery): Promise<void> {\n if (!this._meta.hasMoreItems || this._loading) {\n return;\n }\n this._loading = true;\n\n const where = this.buildWhere(params);\n const sort = params.sort ? [`${params.sort.field}_${params.sort.direction}`] : undefined;\n\n const result = await this.listFilesUseCase.execute({\n search: params.search,\n where,\n sort,\n limit: params.limit,\n after: params.cursor\n });\n\n runInAction(() => {\n this.cache.addItems(result.data);\n this._meta = {\n cursor: result.meta.cursor,\n hasMoreItems: result.meta.hasMoreItems,\n totalCount: result.meta.totalCount\n };\n this._loading = false;\n });\n }\n\n private buildWhere(params: IDataSourceQuery): Record<string, unknown> {\n const where: Record<string, unknown> = { ...params.filters };\n\n const includeSubFolders = where[\"includeSubFolders\"] === true;\n delete where[\"includeSubFolders\"];\n\n const tags = where[\"tags\"] as string[] | undefined;\n const tagsRule = (where[\"tags_rule\"] as string) || \"OR\";\n delete where[\"tags\"];\n delete where[\"tags_rule\"];\n\n if (this.scope) {\n where[\"tags_startsWith\"] = this.scope;\n } else {\n where[\"tags_not_startsWith\"] = DEFAULT_SCOPE;\n }\n\n if (tags && tags.length > 0) {\n const andConditions: Record<string, unknown>[] = [];\n if (tagsRule === \"OR\") {\n andConditions.push({ tags_in: tags });\n } else {\n andConditions.push(...tags.map(tag => ({ tags_in: [tag] })));\n }\n where[\"AND\"] = andConditions;\n }\n\n if (where[\"folderId\"]) {\n const currentFolderId = where[\"folderId\"] as string;\n const isRoot = currentFolderId === \"root\";\n\n if (params.search && isRoot) {\n // Search from root: no location filter — search all folders.\n } else if ((params.search || includeSubFolders) && this.getDescendantFoldersUseCase) {\n const descendants = this.getDescendantFoldersUseCase.execute(currentFolderId);\n const folderIds = descendants.map(f => f.id);\n where[\"location\"] = { folderId_in: folderIds };\n } else {\n where[\"location\"] = { folderId: currentFolderId };\n }\n\n delete where[\"folderId\"];\n }\n\n return where;\n }\n}\n"],"names":["FileListDataSource","listFilesUseCase","cache","getDescendantFoldersUseCase","scope","makeAutoObservable","computed","params","where","sort","undefined","result","runInAction","includeSubFolders","tags","tagsRule","DEFAULT_SCOPE","andConditions","tag","currentFolderId","isRoot","descendants","folderIds","f"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/FileList/FileListDataSource.js","sources":["../../../src/presentation/FileList/FileListDataSource.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 { IListCache } from \"@webiny/app-admin/features/listCache/index.js\";\nimport { DEFAULT_SCOPE } from \"~/domain/constants.js\";\nimport type { IListFilesUseCase } from \"~/features/listFiles/index.js\";\nimport type { FmFile } from \"~/features/shared/types.js\";\n\nexport class FileListDataSource extends FolderAwareDataSource<FmFile> {\n constructor(\n private listFilesUseCase: IListFilesUseCase,\n private cache: IListCache<FmFile>,\n getDescendantFoldersUseCase?: IGetDescendantFoldersUseCase,\n private scope?: string\n ) {\n super({\n keyField: \"id\",\n getDescendantFolders: getDescendantFoldersUseCase,\n localFilters: {\n accept: (item, value) => {\n const mimeTypes = value as string[];\n if (!mimeTypes || mimeTypes.length === 0) {\n return true;\n }\n return mimeTypes.some(pattern => {\n if (pattern.endsWith(\"/*\")) {\n return item.type.startsWith(pattern.slice(0, -1));\n }\n return item.type === pattern;\n });\n }\n }\n });\n }\n\n get rows(): FmFile[] {\n return this.queryMatcher.filter(this.cache.getItems());\n }\n\n async fetch(params: FetchParams): Promise<FetchResult<FmFile>> {\n return this.listFilesUseCase.execute({\n search: params.search,\n where: params.where,\n sort: params.sort,\n limit: params.limit,\n after: params.after\n });\n }\n\n protected override shouldExpandFolders(filters: Record<string, unknown>): boolean {\n return filters[\"includeSubFolders\"] === true;\n }\n\n protected override customizeWhere(\n where: Record<string, unknown>,\n filters: Record<string, unknown>\n ): void {\n delete where[\"includeSubFolders\"];\n\n const accept = where[\"accept\"] as string[] | undefined;\n delete where[\"accept\"];\n\n const tags = where[\"tags\"] as string[] | undefined;\n const tagsRule = (where[\"tags_rule\"] as string) || \"OR\";\n delete where[\"tags\"];\n delete where[\"tags_rule\"];\n\n if (this.scope) {\n where[\"tags_startsWith\"] = this.scope;\n } else {\n where[\"tags_not_startsWith\"] = DEFAULT_SCOPE;\n }\n\n if (tags && tags.length > 0) {\n const andConditions: Record<string, unknown>[] = [];\n if (tagsRule === \"OR\") {\n andConditions.push({ tags_in: tags });\n } else {\n andConditions.push(...tags.map(tag => ({ tags_in: [tag] })));\n }\n where[\"AND\"] = andConditions;\n }\n\n if (accept && accept.length > 0) {\n const exact: string[] = [];\n const prefixes: string[] = [];\n for (const mime of accept) {\n if (mime.endsWith(\"/*\")) {\n prefixes.push(mime.slice(0, -1));\n } else {\n exact.push(mime);\n }\n }\n\n if (prefixes.length === 0) {\n where[\"type_in\"] = exact;\n } else if (exact.length === 0 && prefixes.length === 1) {\n where[\"type_startsWith\"] = prefixes[0];\n } else {\n const orConditions: Record<string, unknown>[] = [];\n if (exact.length > 0) {\n orConditions.push({ type_in: exact });\n }\n for (const prefix of prefixes) {\n orConditions.push({ type_startsWith: prefix });\n }\n where[\"OR\"] = [\n ...((where[\"OR\"] as Record<string, unknown>[]) ?? []),\n ...orConditions\n ];\n }\n }\n }\n}\n"],"names":["FileListDataSource","FolderAwareDataSource","listFilesUseCase","cache","getDescendantFoldersUseCase","scope","item","value","mimeTypes","pattern","params","filters","where","accept","tags","tagsRule","DEFAULT_SCOPE","andConditions","tag","exact","prefixes","mime","orConditions","prefix"],"mappings":"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"}
@@ -33,8 +33,10 @@ function createMockListPresenter() {
33
33
  selection: {
34
34
  selectedIds: new Set(),
35
35
  selectedCount: 0,
36
- allSelected: false
36
+ allSelected: false,
37
+ label: ""
37
38
  },
39
+ showingFilters: false,
38
40
  empty: true,
39
41
  emptyWithFilters: false,
40
42
  error: null
@@ -55,7 +57,9 @@ function createMockListPresenter() {
55
57
  filter: {
56
58
  set: vi.fn(),
57
59
  clear: vi.fn(),
58
- clearAll: vi.fn()
60
+ clearAll: vi.fn(),
61
+ show: vi.fn(),
62
+ hide: vi.fn()
59
63
  },
60
64
  selection: {
61
65
  toggle: vi.fn(),
@@ -194,6 +198,7 @@ function createMockFileDetailsPresenter() {
194
198
  form: {
195
199
  layout: [],
196
200
  errors: [],
201
+ hasErrors: false,
197
202
  isDirty: false,
198
203
  isValid: null,
199
204
  submitCount: 0,
@@ -208,7 +213,8 @@ function createMockFileDetailsPresenter() {
208
213
  }
209
214
  },
210
215
  loadFile: vi.fn().mockResolvedValue(void 0),
211
- saveFile: vi.fn().mockResolvedValue(void 0)
216
+ saveFile: vi.fn().mockResolvedValue(void 0),
217
+ setFile: vi.fn()
212
218
  };
213
219
  }
214
220
  function createMocks() {
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/FileList/FileListPresenter.test.js","sources":["../../../src/presentation/FileList/FileListPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { observable, runInAction } 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/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { FileManagerPermissions } from \"../../features/permissions/abstractions.js\";\nimport { GetSettingsRepository } from \"../../features/settings/abstractions.js\";\nimport { ListTagsRepository } from \"../../features/tags/abstractions.js\";\nimport { FileUploader } from \"../../features/fileUploader/abstractions.js\";\nimport { LocalStorage } from \"@webiny/app/features/localStorage\";\nimport { ListFilesUseCase } from \"../../features/listFiles/abstractions.js\";\nimport { FilesListCache } from \"../../features/shared/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { FileModelProvider } from \"../../features/fileModel/abstractions.js\";\nimport { FileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport { FileManagerPresenter as Abstraction, type IFileManagerPresenter } from \"./abstractions.js\";\nimport { FileManagerPresenter } from \"./FileManagerPresenter.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createMockListPresenter(): ListPresenter.Interface<FmFile> {\n const vmState = observable({\n rows: [] as FmFile[],\n sort: null as { field: string; direction: \"ASC\" | \"DESC\" } | null,\n filters: {} as Record<string, unknown>,\n search: \"\",\n appliedQuery: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IDataSourceQuery\n | null,\n pagination: {\n hasMore: false,\n loading: false,\n loadingMore: false,\n totalCount: 0,\n currentCount: 0\n },\n selection: {\n selectedIds: new Set<string>(),\n selectedCount: 0,\n allSelected: false\n },\n empty: true,\n emptyWithFilters: false,\n error: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IListError\n | null\n });\n\n return {\n get vm() {\n return vmState;\n },\n actions: {\n search: { set: vi.fn(), clear: vi.fn() },\n sort: { set: vi.fn(), toggle: vi.fn() },\n filter: { set: vi.fn(), clear: vi.fn(), clearAll: vi.fn() },\n selection: {\n toggle: vi.fn(),\n selectRangeTo: vi.fn(),\n selectAll: vi.fn(),\n deselectAll: vi.fn(),\n selectRows: vi.fn(),\n isSelected: vi.fn().mockReturnValue(false)\n },\n loadMore: vi.fn().mockResolvedValue(undefined),\n refresh: vi.fn().mockResolvedValue(undefined)\n },\n init: vi.fn()\n };\n}\n\nfunction createMockFolderTreePresenter(): FolderTreePresenter.Interface {\n const state = 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 Files\",\n childFolders: [],\n loadingNodeIds: []\n });\n\n return {\n get vm() {\n return state;\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\nfunction createMockPermissions(): FileManagerPermissions.Interface {\n return {\n canAccess: vi.fn().mockReturnValue(true),\n canRead: vi.fn().mockReturnValue(true),\n canCreate: vi.fn().mockReturnValue(true),\n canEdit: vi.fn().mockReturnValue(false),\n canDelete: vi.fn().mockReturnValue(false),\n canAction: vi.fn().mockReturnValue(true)\n } as unknown as FileManagerPermissions.Interface;\n}\n\nfunction createMockSettingsRepository(): GetSettingsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }),\n save: vi.fn().mockImplementation(async (data: Record<string, unknown>) => data),\n settings: null\n };\n}\n\nfunction createMockTagsRepository(): ListTagsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue([]),\n tags: [{ tag: \"photo\", count: 5 }]\n };\n}\n\nfunction createMockFileUploader(): FileUploader.Interface {\n return {\n vm: {\n jobs: [],\n overallProgress: { sent: 0, total: 0, percentage: 0 },\n isUploading: false,\n completedCount: 0,\n failedCount: 0\n },\n upload: vi.fn().mockResolvedValue(undefined),\n uploadMany: vi.fn().mockResolvedValue(undefined),\n abort: vi.fn(),\n clear: vi.fn()\n };\n}\n\nfunction createMockLocalStorage(): LocalStorage.Interface {\n const store = new Map<string, unknown>();\n return {\n get: vi.fn((key: string) => store.get(key)) as LocalStorage.Interface[\"get\"],\n set: vi.fn(<T>(key: string, value: T): void => {\n store.set(key, value);\n }),\n remove: vi.fn((key: string) => {\n store.delete(key);\n }),\n clear: vi.fn(() => store.clear()),\n keys: vi.fn(() => Array.from(store.keys()))\n };\n}\n\nfunction createMockListFilesUseCase(): ListFilesUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n })\n };\n}\n\nfunction createMockGetDescendantFoldersUseCase(): GetDescendantFoldersUseCase.Interface {\n return {\n execute: vi.fn().mockReturnValue([])\n };\n}\n\nfunction createMockFileDetailsPresenter(): IFileDetailsPresenter {\n return {\n vm: {\n file: null,\n loading: null,\n form: {\n layout: [],\n errors: [],\n isDirty: false,\n isValid: null,\n submitCount: 0,\n focusField: vi.fn(),\n getData: vi.fn(() => ({})),\n setData: vi.fn()\n },\n previewUrl: null,\n permissions: { canEdit: true, canDelete: true }\n },\n loadFile: vi.fn().mockResolvedValue(undefined),\n saveFile: vi.fn().mockResolvedValue(undefined)\n };\n}\n\n// ---------------------------------------------------------------------------\n// Container setup\n// ---------------------------------------------------------------------------\n\ninterface Mocks {\n listPresenter: ListPresenter.Interface<FmFile>;\n folderTreePresenter: FolderTreePresenter.Interface;\n fileDetailsPresenter: IFileDetailsPresenter;\n permissions: FileManagerPermissions.Interface;\n settingsRepository: GetSettingsRepository.Interface;\n tagsRepository: ListTagsRepository.Interface;\n fileUploader: FileUploader.Interface;\n localStorage: LocalStorage.Interface;\n listFilesUseCase: ListFilesUseCase.Interface;\n cache: ListCache<FmFile>;\n getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface;\n fileModelProvider: FileModelProvider.Interface;\n}\n\nfunction createMocks(): Mocks {\n return {\n listPresenter: createMockListPresenter(),\n folderTreePresenter: createMockFolderTreePresenter(),\n fileDetailsPresenter: createMockFileDetailsPresenter(),\n permissions: createMockPermissions(),\n settingsRepository: createMockSettingsRepository(),\n tagsRepository: createMockTagsRepository(),\n fileUploader: createMockFileUploader(),\n localStorage: createMockLocalStorage(),\n listFilesUseCase: createMockListFilesUseCase(),\n cache: new ListCache<FmFile>(),\n getDescendantFoldersUseCase: createMockGetDescendantFoldersUseCase(),\n fileModelProvider: {\n getModel: vi.fn().mockResolvedValue({ fields: [] })\n }\n };\n}\n\nfunction createContainer(mocks: Mocks) {\n const container = new Container();\n\n container.registerInstance(ListPresenter, mocks.listPresenter);\n container.registerInstance(FolderTreePresenter, mocks.folderTreePresenter);\n container.registerInstance(FileDetailsPresenter, mocks.fileDetailsPresenter);\n container.registerInstance(FileManagerPermissions, mocks.permissions);\n container.registerInstance(GetSettingsRepository, mocks.settingsRepository);\n container.registerInstance(ListTagsRepository, mocks.tagsRepository);\n container.registerInstance(FileUploader, mocks.fileUploader);\n container.registerInstance(LocalStorage, mocks.localStorage);\n container.registerInstance(ListFilesUseCase, mocks.listFilesUseCase);\n container.registerInstance(FilesListCache, mocks.cache);\n container.registerInstance(GetDescendantFoldersUseCase, mocks.getDescendantFoldersUseCase);\n container.registerInstance(FileModelProvider, mocks.fileModelProvider);\n\n // Register the real FileListPresenter implementation.\n container.register(FileManagerPresenter).inSingletonScope();\n\n return container;\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FileListPresenter\", () => {\n let mocks: Mocks;\n let presenter: IFileManagerPresenter;\n\n beforeEach(() => {\n mocks = createMocks();\n const container = createContainer(mocks);\n presenter = container.resolve(Abstraction);\n });\n\n // -----------------------------------------------------------------------\n // Composition: ListPresenter and FolderTreePresenter initialized.\n // -----------------------------------------------------------------------\n\n it(\"should call listPresenter.init with a DataSource and initialSort on init()\", () => {\n presenter.init();\n\n expect(mocks.listPresenter.init).toHaveBeenCalledTimes(1);\n const config = (mocks.listPresenter.init as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(config.dataSource).toBeDefined();\n expect(config.initialSort).toEqual({ field: \"createdOn\", direction: \"DESC\" });\n });\n\n it(\"should forward ListPresenter.vm data as vm.list\", () => {\n presenter.init();\n expect(presenter.vm.list.rows).toEqual(mocks.listPresenter.vm.rows);\n expect(presenter.vm.list.sort).toEqual(mocks.listPresenter.vm.sort);\n expect(presenter.vm.list.search).toBe(mocks.listPresenter.vm.search);\n expect(presenter.vm.list.empty).toBe(mocks.listPresenter.vm.empty);\n });\n\n it(\"should forward FolderTreePresenter.vm as vm.folders\", () => {\n presenter.init();\n expect(presenter.vm.folders).toBe(mocks.folderTreePresenter.vm);\n });\n\n // -----------------------------------------------------------------------\n // Folder change wiring.\n // -----------------------------------------------------------------------\n\n it(\"should set folderId filter when folder changes\", async () => {\n presenter.init();\n\n // Simulate folder selection via MobX observable change.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-abc\";\n });\n\n // MobX reaction fires synchronously in the same tick after runInAction.\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\n \"folderId\",\n \"folder-abc\"\n );\n });\n\n it(\"should set folderId to root when folder is set to null\", () => {\n presenter.init();\n\n // First set a folder.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-1\";\n });\n\n // Then clear it.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = null;\n });\n\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\"folderId\", \"root\");\n });\n\n // -----------------------------------------------------------------------\n // Permission flags forwarded to vm.\n // -----------------------------------------------------------------------\n\n it(\"should expose permission flags in vm.permissions\", () => {\n presenter.init();\n\n expect(presenter.vm.permissions.canRead).toBe(true);\n expect(presenter.vm.permissions.canCreate).toBe(true);\n expect(presenter.vm.permissions.canEdit).toBe(false);\n expect(presenter.vm.permissions.canDelete).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // View mode persistence via LocalStorage.\n // -----------------------------------------------------------------------\n\n it(\"should default viewMode to 'grid'\", () => {\n expect(presenter.vm.viewMode).toBe(\"grid\");\n });\n\n it(\"should update viewMode and persist to localStorage\", () => {\n presenter.actions.setViewMode(\"grid\");\n\n expect(presenter.vm.viewMode).toBe(\"grid\");\n expect(mocks.localStorage.set).toHaveBeenCalledWith(\"fm:viewMode\", \"grid\");\n });\n\n it(\"should restore viewMode from localStorage on construction\", () => {\n // Pre-seed localStorage with \"grid\" before creating the presenter.\n const seededMocks = createMocks();\n (seededMocks.localStorage.get as ReturnType<typeof vi.fn>).mockReturnValue(\"grid\");\n\n const container = createContainer(seededMocks);\n const seededPresenter: IFileManagerPresenter = container.resolve(Abstraction);\n\n expect(seededPresenter.vm.viewMode).toBe(\"grid\");\n });\n\n // -----------------------------------------------------------------------\n // Upload action.\n // -----------------------------------------------------------------------\n\n it(\"should call fileUploader.uploadMany when actions.upload is called\", async () => {\n presenter.init();\n\n const file1 = {\n id: \"f1\",\n name: \"test.txt\",\n type: \"text/plain\",\n size: 7,\n src: { file: new File([\"content\"], \"test.txt\", { type: \"text/plain\" }), base64: null }\n };\n const file2 = {\n id: \"f2\",\n name: \"photo.png\",\n type: \"image/png\",\n size: 3,\n src: { file: new File([\"img\"], \"photo.png\", { type: \"image/png\" }), base64: null }\n };\n\n await presenter.actions.upload([file1, file2]);\n\n expect(mocks.fileUploader.uploadMany).toHaveBeenCalledTimes(1);\n const args = (mocks.fileUploader.uploadMany as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(args).toHaveLength(2);\n expect(args[0].data.name).toBe(\"test.txt\");\n expect(args[0].data.type).toBe(\"text/plain\");\n expect(args[1].data.name).toBe(\"photo.png\");\n expect(args[1].data.type).toBe(\"image/png\");\n });\n\n // -----------------------------------------------------------------------\n // loading: true only during initial load (no rows yet).\n // -----------------------------------------------------------------------\n\n it(\"should be loading when pagination is loading and no rows exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(true);\n });\n\n it(\"should not be loading when rows already exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n it(\"should not be loading when pagination is not loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // empty: accounts for both files and child folders.\n // -----------------------------------------------------------------------\n\n it(\"should be empty when no files and no child folders\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n it(\"should not be empty when there are files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty when there are child folders but no files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty while loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should be empty when child folders exist but folders are hidden (search active)\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n // -----------------------------------------------------------------------\n // showFolders computed from appliedQuery.\n // -----------------------------------------------------------------------\n\n it(\"should show folders when appliedQuery is null\", () => {\n presenter.init();\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should show folders when appliedQuery has no search and only folderId filter\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should hide folders when appliedQuery has a search\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should hide folders when appliedQuery has non-folderId filters\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", tags: [\"photo\"] }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should show folders again when appliedQuery filters are cleared\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", type: \"image\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n});\n"],"names":["createMockListPresenter","vmState","observable","Set","vi","undefined","createMockFolderTreePresenter","state","createMockPermissions","createMockSettingsRepository","data","createMockTagsRepository","createMockFileUploader","createMockLocalStorage","store","Map","key","value","Array","createMockListFilesUseCase","createMockGetDescendantFoldersUseCase","createMockFileDetailsPresenter","createMocks","ListCache","createContainer","mocks","container","Container","ListPresenter","FolderTreePresenter","FileDetailsPresenter","FileManagerPermissions","GetSettingsRepository","ListTagsRepository","FileUploader","LocalStorage","ListFilesUseCase","FilesListCache","GetDescendantFoldersUseCase","FileModelProvider","FileManagerPresenter","describe","presenter","beforeEach","Abstraction","it","expect","config","runInAction","seededMocks","seededPresenter","file1","File","file2","args"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/FileList/FileListPresenter.test.js","sources":["../../../src/presentation/FileList/FileListPresenter.test.ts"],"sourcesContent":["// @vitest-environment jsdom\nimport { describe, it, expect, vi, beforeEach } from \"vitest\";\nimport { observable, runInAction } 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/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { FileManagerPermissions } from \"../../features/permissions/abstractions.js\";\nimport { GetSettingsRepository } from \"../../features/settings/abstractions.js\";\nimport { ListTagsRepository } from \"../../features/tags/abstractions.js\";\nimport { FileUploader } from \"../../features/fileUploader/abstractions.js\";\nimport { LocalStorage } from \"@webiny/app/features/localStorage\";\nimport { ListFilesUseCase } from \"../../features/listFiles/abstractions.js\";\nimport { FilesListCache } from \"../../features/shared/abstractions.js\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport { FileModelProvider } from \"../../features/fileModel/abstractions.js\";\nimport { FileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport { FileManagerPresenter as Abstraction, type IFileManagerPresenter } from \"./abstractions.js\";\nimport { FileManagerPresenter } from \"./FileManagerPresenter.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction createMockListPresenter(): ListPresenter.Interface<FmFile> {\n const vmState = observable({\n rows: [] as FmFile[],\n sort: null as { field: string; direction: \"ASC\" | \"DESC\" } | null,\n filters: {} as Record<string, unknown>,\n search: \"\",\n appliedQuery: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IDataSourceQuery\n | null,\n pagination: {\n hasMore: false,\n loading: false,\n loadingMore: false,\n totalCount: 0,\n currentCount: 0\n },\n selection: {\n selectedIds: new Set<string>(),\n selectedCount: 0,\n allSelected: false,\n label: \"\"\n },\n showingFilters: false,\n empty: true,\n emptyWithFilters: false,\n error: null as\n | import(\"@webiny/app-admin/presentation/listPresenter/abstractions.js\").IListError\n | null\n });\n\n return {\n get vm() {\n return vmState;\n },\n actions: {\n search: { set: vi.fn(), clear: vi.fn() },\n sort: { set: vi.fn(), toggle: vi.fn() },\n filter: {\n set: vi.fn(),\n clear: vi.fn(),\n clearAll: vi.fn(),\n show: vi.fn(),\n hide: vi.fn()\n },\n selection: {\n toggle: vi.fn(),\n selectRangeTo: vi.fn(),\n selectAll: vi.fn(),\n deselectAll: vi.fn(),\n selectRows: vi.fn(),\n isSelected: vi.fn().mockReturnValue(false)\n },\n loadMore: vi.fn().mockResolvedValue(undefined),\n refresh: vi.fn().mockResolvedValue(undefined)\n },\n init: vi.fn()\n };\n}\n\nfunction createMockFolderTreePresenter(): FolderTreePresenter.Interface {\n const state = 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 Files\",\n childFolders: [],\n loadingNodeIds: []\n });\n\n return {\n get vm() {\n return state;\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\nfunction createMockPermissions(): FileManagerPermissions.Interface {\n return {\n canAccess: vi.fn().mockReturnValue(true),\n canRead: vi.fn().mockReturnValue(true),\n canCreate: vi.fn().mockReturnValue(true),\n canEdit: vi.fn().mockReturnValue(false),\n canDelete: vi.fn().mockReturnValue(false),\n canAction: vi.fn().mockReturnValue(true)\n } as unknown as FileManagerPermissions.Interface;\n}\n\nfunction createMockSettingsRepository(): GetSettingsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n uploadMinFileSize: \"0\",\n uploadMaxFileSize: \"10485760\",\n srcPrefix: \"https://cdn.example.com/\"\n }),\n save: vi.fn().mockImplementation(async (data: Record<string, unknown>) => data),\n settings: null\n };\n}\n\nfunction createMockTagsRepository(): ListTagsRepository.Interface {\n return {\n execute: vi.fn().mockResolvedValue([]),\n tags: [{ tag: \"photo\", count: 5 }]\n };\n}\n\nfunction createMockFileUploader(): FileUploader.Interface {\n return {\n vm: {\n jobs: [],\n overallProgress: { sent: 0, total: 0, percentage: 0 },\n isUploading: false,\n completedCount: 0,\n failedCount: 0\n },\n upload: vi.fn().mockResolvedValue(undefined),\n uploadMany: vi.fn().mockResolvedValue(undefined),\n abort: vi.fn(),\n clear: vi.fn()\n };\n}\n\nfunction createMockLocalStorage(): LocalStorage.Interface {\n const store = new Map<string, unknown>();\n return {\n get: vi.fn((key: string) => store.get(key)) as LocalStorage.Interface[\"get\"],\n set: vi.fn(<T>(key: string, value: T): void => {\n store.set(key, value);\n }),\n remove: vi.fn((key: string) => {\n store.delete(key);\n }),\n clear: vi.fn(() => store.clear()),\n keys: vi.fn(() => Array.from(store.keys()))\n };\n}\n\nfunction createMockListFilesUseCase(): ListFilesUseCase.Interface {\n return {\n execute: vi.fn().mockResolvedValue({\n data: [],\n meta: { cursor: null, hasMoreItems: false, totalCount: 0 }\n })\n };\n}\n\nfunction createMockGetDescendantFoldersUseCase(): GetDescendantFoldersUseCase.Interface {\n return {\n execute: vi.fn().mockReturnValue([])\n };\n}\n\nfunction createMockFileDetailsPresenter(): IFileDetailsPresenter {\n return {\n vm: {\n file: null,\n loading: null,\n form: {\n layout: [],\n errors: [],\n hasErrors: false,\n isDirty: false,\n isValid: null,\n submitCount: 0,\n focusField: vi.fn(),\n getData: vi.fn(() => ({})),\n setData: vi.fn()\n },\n previewUrl: null,\n permissions: { canEdit: true, canDelete: true }\n },\n loadFile: vi.fn().mockResolvedValue(undefined),\n saveFile: vi.fn().mockResolvedValue(undefined),\n setFile: vi.fn()\n };\n}\n\n// ---------------------------------------------------------------------------\n// Container setup\n// ---------------------------------------------------------------------------\n\ninterface Mocks {\n listPresenter: ListPresenter.Interface<FmFile>;\n folderTreePresenter: FolderTreePresenter.Interface;\n fileDetailsPresenter: IFileDetailsPresenter;\n permissions: FileManagerPermissions.Interface;\n settingsRepository: GetSettingsRepository.Interface;\n tagsRepository: ListTagsRepository.Interface;\n fileUploader: FileUploader.Interface;\n localStorage: LocalStorage.Interface;\n listFilesUseCase: ListFilesUseCase.Interface;\n cache: ListCache<FmFile>;\n getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface;\n fileModelProvider: FileModelProvider.Interface;\n}\n\nfunction createMocks(): Mocks {\n return {\n listPresenter: createMockListPresenter(),\n folderTreePresenter: createMockFolderTreePresenter(),\n fileDetailsPresenter: createMockFileDetailsPresenter(),\n permissions: createMockPermissions(),\n settingsRepository: createMockSettingsRepository(),\n tagsRepository: createMockTagsRepository(),\n fileUploader: createMockFileUploader(),\n localStorage: createMockLocalStorage(),\n listFilesUseCase: createMockListFilesUseCase(),\n cache: new ListCache<FmFile>(),\n getDescendantFoldersUseCase: createMockGetDescendantFoldersUseCase(),\n fileModelProvider: {\n getModel: vi.fn().mockResolvedValue({ fields: [] })\n }\n };\n}\n\nfunction createContainer(mocks: Mocks) {\n const container = new Container();\n\n container.registerInstance(ListPresenter, mocks.listPresenter);\n container.registerInstance(FolderTreePresenter, mocks.folderTreePresenter);\n container.registerInstance(FileDetailsPresenter, mocks.fileDetailsPresenter);\n container.registerInstance(FileManagerPermissions, mocks.permissions);\n container.registerInstance(GetSettingsRepository, mocks.settingsRepository);\n container.registerInstance(ListTagsRepository, mocks.tagsRepository);\n container.registerInstance(FileUploader, mocks.fileUploader);\n container.registerInstance(LocalStorage, mocks.localStorage);\n container.registerInstance(ListFilesUseCase, mocks.listFilesUseCase);\n container.registerInstance(FilesListCache, mocks.cache);\n container.registerInstance(GetDescendantFoldersUseCase, mocks.getDescendantFoldersUseCase);\n container.registerInstance(FileModelProvider, mocks.fileModelProvider);\n\n // Register the real FileListPresenter implementation.\n container.register(FileManagerPresenter).inSingletonScope();\n\n return container;\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FileListPresenter\", () => {\n let mocks: Mocks;\n let presenter: IFileManagerPresenter;\n\n beforeEach(() => {\n mocks = createMocks();\n const container = createContainer(mocks);\n presenter = container.resolve(Abstraction);\n });\n\n // -----------------------------------------------------------------------\n // Composition: ListPresenter and FolderTreePresenter initialized.\n // -----------------------------------------------------------------------\n\n it(\"should call listPresenter.init with a DataSource and initialSort on init()\", () => {\n presenter.init();\n\n expect(mocks.listPresenter.init).toHaveBeenCalledTimes(1);\n const config = (mocks.listPresenter.init as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(config.dataSource).toBeDefined();\n expect(config.initialSort).toEqual({ field: \"createdOn\", direction: \"DESC\" });\n });\n\n it(\"should forward ListPresenter.vm data as vm.list\", () => {\n presenter.init();\n expect(presenter.vm.list.rows).toEqual(mocks.listPresenter.vm.rows);\n expect(presenter.vm.list.sort).toEqual(mocks.listPresenter.vm.sort);\n expect(presenter.vm.list.search).toBe(mocks.listPresenter.vm.search);\n expect(presenter.vm.list.empty).toBe(mocks.listPresenter.vm.empty);\n });\n\n it(\"should forward FolderTreePresenter.vm as vm.folders\", () => {\n presenter.init();\n expect(presenter.vm.folders).toBe(mocks.folderTreePresenter.vm);\n });\n\n // -----------------------------------------------------------------------\n // Folder change wiring.\n // -----------------------------------------------------------------------\n\n it(\"should set folderId filter when folder changes\", async () => {\n presenter.init();\n\n // Simulate folder selection via MobX observable change.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-abc\";\n });\n\n // MobX reaction fires synchronously in the same tick after runInAction.\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\n \"folderId\",\n \"folder-abc\"\n );\n });\n\n it(\"should set folderId to root when folder is set to null\", () => {\n presenter.init();\n\n // First set a folder.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = \"folder-1\";\n });\n\n // Then clear it.\n runInAction(() => {\n (mocks.folderTreePresenter.vm as any).currentFolderId = null;\n });\n\n expect(mocks.listPresenter.actions.filter.set).toHaveBeenCalledWith(\"folderId\", \"root\");\n });\n\n // -----------------------------------------------------------------------\n // Permission flags forwarded to vm.\n // -----------------------------------------------------------------------\n\n it(\"should expose permission flags in vm.permissions\", () => {\n presenter.init();\n\n expect(presenter.vm.permissions.canRead).toBe(true);\n expect(presenter.vm.permissions.canCreate).toBe(true);\n expect(presenter.vm.permissions.canEdit).toBe(false);\n expect(presenter.vm.permissions.canDelete).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // View mode persistence via LocalStorage.\n // -----------------------------------------------------------------------\n\n it(\"should default viewMode to 'grid'\", () => {\n expect(presenter.vm.viewMode).toBe(\"grid\");\n });\n\n it(\"should update viewMode and persist to localStorage\", () => {\n presenter.actions.setViewMode(\"grid\");\n\n expect(presenter.vm.viewMode).toBe(\"grid\");\n expect(mocks.localStorage.set).toHaveBeenCalledWith(\"fm:viewMode\", \"grid\");\n });\n\n it(\"should restore viewMode from localStorage on construction\", () => {\n // Pre-seed localStorage with \"grid\" before creating the presenter.\n const seededMocks = createMocks();\n (seededMocks.localStorage.get as ReturnType<typeof vi.fn>).mockReturnValue(\"grid\");\n\n const container = createContainer(seededMocks);\n const seededPresenter: IFileManagerPresenter = container.resolve(Abstraction);\n\n expect(seededPresenter.vm.viewMode).toBe(\"grid\");\n });\n\n // -----------------------------------------------------------------------\n // Upload action.\n // -----------------------------------------------------------------------\n\n it(\"should call fileUploader.uploadMany when actions.upload is called\", async () => {\n presenter.init();\n\n const file1 = {\n id: \"f1\",\n name: \"test.txt\",\n type: \"text/plain\",\n size: 7,\n src: { file: new File([\"content\"], \"test.txt\", { type: \"text/plain\" }), base64: null }\n };\n const file2 = {\n id: \"f2\",\n name: \"photo.png\",\n type: \"image/png\",\n size: 3,\n src: { file: new File([\"img\"], \"photo.png\", { type: \"image/png\" }), base64: null }\n };\n\n await presenter.actions.upload([file1, file2]);\n\n expect(mocks.fileUploader.uploadMany).toHaveBeenCalledTimes(1);\n const args = (mocks.fileUploader.uploadMany as ReturnType<typeof vi.fn>).mock.calls[0][0];\n expect(args).toHaveLength(2);\n expect(args[0].data.name).toBe(\"test.txt\");\n expect(args[0].data.type).toBe(\"text/plain\");\n expect(args[1].data.name).toBe(\"photo.png\");\n expect(args[1].data.type).toBe(\"image/png\");\n });\n\n // -----------------------------------------------------------------------\n // loading: true only during initial load (no rows yet).\n // -----------------------------------------------------------------------\n\n it(\"should be loading when pagination is loading and no rows exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(true);\n });\n\n it(\"should not be loading when rows already exist\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n it(\"should not be loading when pagination is not loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.loading).toBe(false);\n });\n\n // -----------------------------------------------------------------------\n // empty: accounts for both files and child folders.\n // -----------------------------------------------------------------------\n\n it(\"should be empty when no files and no child folders\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n it(\"should not be empty when there are files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [{ id: \"file-1\" }];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty when there are child folders but no files\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should not be empty while loading\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = true;\n });\n expect(presenter.vm.empty).toBe(false);\n });\n\n it(\"should be empty when child folders exist but folders are hidden (search active)\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).rows = [];\n (mocks.listPresenter.vm as any).pagination.loading = false;\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n (mocks.folderTreePresenter.vm as any).childFolders = [{ id: \"folder-1\" }];\n });\n expect(presenter.vm.empty).toBe(true);\n });\n\n // -----------------------------------------------------------------------\n // showFolders computed from appliedQuery.\n // -----------------------------------------------------------------------\n\n it(\"should show folders when appliedQuery is null\", () => {\n presenter.init();\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should show folders when appliedQuery has no search and only folderId filter\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n\n it(\"should hide folders when appliedQuery has a search\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n search: \"photo\",\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should hide folders when appliedQuery has non-folderId filters\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", tags: [\"photo\"] }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n });\n\n it(\"should show folders again when appliedQuery filters are cleared\", () => {\n presenter.init();\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\", type: \"image\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(false);\n\n runInAction(() => {\n (mocks.listPresenter.vm as any).appliedQuery = {\n filters: { folderId: \"root\" }\n };\n });\n expect(presenter.vm.showFolders).toBe(true);\n });\n});\n"],"names":["createMockListPresenter","vmState","observable","Set","vi","undefined","createMockFolderTreePresenter","state","createMockPermissions","createMockSettingsRepository","data","createMockTagsRepository","createMockFileUploader","createMockLocalStorage","store","Map","key","value","Array","createMockListFilesUseCase","createMockGetDescendantFoldersUseCase","createMockFileDetailsPresenter","createMocks","ListCache","createContainer","mocks","container","Container","ListPresenter","FolderTreePresenter","FileDetailsPresenter","FileManagerPermissions","GetSettingsRepository","ListTagsRepository","FileUploader","LocalStorage","ListFilesUseCase","FilesListCache","GetDescendantFoldersUseCase","FileModelProvider","FileManagerPresenter","describe","presenter","beforeEach","Abstraction","it","expect","config","runInAction","seededMocks","seededPresenter","file1","File","file2","args"],"mappings":"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"}
@@ -37,6 +37,7 @@ declare class FileManagerPresenterImpl implements IFileManagerPresenter {
37
37
  dispose(): void;
38
38
  private isLoading;
39
39
  private isEmpty;
40
+ private getSortedChildFolders;
40
41
  private shouldShowFolders;
41
42
  }
42
43
  export declare const FileManagerPresenter: typeof FileManagerPresenterImpl & {
@@ -1,6 +1,7 @@
1
1
  import { computed, makeAutoObservable, reaction, runInAction } from "mobx";
2
2
  import { ListPresenter } from "@webiny/app-admin/presentation/listPresenter/abstractions.js";
3
3
  import { FolderTreePresenter } from "@webiny/app-aco/presentation/folderTree/abstractions.js";
4
+ import { sortFolders } from "@webiny/app-aco";
4
5
  import { LocalStorage } from "@webiny/app/features/localStorage";
5
6
  import { GetDescendantFoldersUseCase } from "@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js";
6
7
  import { FileManagerPresenter } from "./abstractions.js";
@@ -46,7 +47,9 @@ class FileManagerPresenterImpl {
46
47
  filter: {
47
48
  set: (key, value)=>this.listPresenter.actions.filter.set(key, value),
48
49
  clear: (key)=>this.listPresenter.actions.filter.clear(key),
49
- clearAll: ()=>this.listPresenter.actions.filter.clearAll()
50
+ clearAll: ()=>this.listPresenter.actions.filter.clearAll(),
51
+ show: ()=>this.listPresenter.actions.filter.show(),
52
+ hide: ()=>this.listPresenter.actions.filter.hide()
50
53
  },
51
54
  selection: {
52
55
  toggle: (id)=>this.listPresenter.actions.selection.toggle(id),
@@ -146,6 +149,7 @@ class FileManagerPresenterImpl {
146
149
  loading: this.isLoading(),
147
150
  empty: this.isEmpty(),
148
151
  showFolders: this.shouldShowFolders(),
152
+ childFolders: this.getSortedChildFolders(),
149
153
  viewMode: this._viewMode,
150
154
  dragging: this._dragging,
151
155
  showingFilters: this._showingFilters
@@ -155,15 +159,17 @@ class FileManagerPresenterImpl {
155
159
  const initialFolderId = config?.initialFolderId ?? this.localStorage.get(LAST_FOLDER_KEY) ?? "root";
156
160
  this._persistFolder = !config?.initialFolderId;
157
161
  const dataSource = new FileListDataSource(this.listFilesUseCase, this.filesListCache, this.getDescendantFoldersUseCase, config?.scope);
162
+ const initialFilters = {
163
+ folderId: initialFolderId
164
+ };
165
+ if (config?.accept && config.accept.length > 0) initialFilters["accept"] = config.accept;
158
166
  this.listPresenter.init({
159
167
  dataSource,
160
168
  initialSort: {
161
169
  field: "createdOn",
162
170
  direction: "DESC"
163
171
  },
164
- initialFilters: {
165
- folderId: initialFolderId
166
- },
172
+ initialFilters,
167
173
  limit: 50
168
174
  });
169
175
  if ("root" !== initialFolderId) this.folderTreePresenter.selectFolder(initialFolderId);
@@ -194,11 +200,15 @@ class FileManagerPresenterImpl {
194
200
  if (this.shouldShowFolders() && this.folderTreePresenter.vm.childFolders.length > 0) return false;
195
201
  return true;
196
202
  }
203
+ getSortedChildFolders() {
204
+ if (!this.shouldShowFolders()) return [];
205
+ return sortFolders(this.folderTreePresenter.vm.childFolders ?? [], this.listPresenter.vm.appliedQuery?.sort);
206
+ }
197
207
  shouldShowFolders() {
198
208
  const { appliedQuery } = this.listPresenter.vm;
199
209
  if (!appliedQuery) return true;
200
210
  if (appliedQuery.search) return false;
201
- const filterKeys = Object.keys(appliedQuery.filters ?? {}).filter((k)=>"folderId" !== k);
211
+ const filterKeys = Object.keys(appliedQuery.filters ?? {}).filter((k)=>"folderId" !== k && "accept" !== k);
202
212
  if (filterKeys.length > 0) return false;
203
213
  return true;
204
214
  }
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/FileList/FileManagerPresenter.js","sources":["../../../src/presentation/FileList/FileManagerPresenter.ts"],"sourcesContent":["import { makeAutoObservable, reaction, runInAction, computed } from \"mobx\";\nimport type { FmFile } from \"@webiny/sdk\";\nimport type { CmsModel } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { LocalStorage } from \"@webiny/app/features/localStorage\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport {\n FileManagerPresenter as Abstraction,\n type IFileManagerPresenter,\n type IFileManagerViewModel,\n type IFileManagerActions,\n type IFileManagerInitConfig\n} from \"./abstractions.js\";\nimport { FileListDataSource } from \"./FileListDataSource.js\";\nimport { FileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport { FileManagerPermissions } from \"~/features/permissions/abstractions.js\";\nimport { ListTagsRepository } from \"~/features/tags/index.js\";\nimport { FileUploader } from \"~/features/fileUploader/index.js\";\nimport { ListFilesUseCase } from \"~/features/listFiles/index.js\";\nimport { FilesListCache } from \"~/features/shared/index.js\";\nimport { FileModelProvider } from \"~/features/fileModel/index.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { SelectedFile } from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\n\nconst VIEW_MODE_KEY = \"fm:viewMode\";\nconst LAST_FOLDER_KEY = \"fm:lastFolder\";\n\nclass FileManagerPresenterImpl implements IFileManagerPresenter {\n private _viewMode: \"table\" | \"grid\" = \"grid\";\n private _dragging = false;\n private _disposeReaction: (() => void) | null = null;\n private _fileDetails: IFileDetailsPresenter | null = null;\n private _showingFilters = false;\n private _fileModel: CmsModel | null = null;\n private _persistFolder = true;\n\n constructor(\n private listPresenter: ListPresenter.Interface<FmFile>,\n private folderTreePresenter: FolderTreePresenter.Interface,\n private fileDetailsPresenter: FileDetailsPresenter.Interface,\n private permissions: FileManagerPermissions.Interface,\n private tagsRepository: ListTagsRepository.Interface,\n private fileUploader: FileUploader.Interface,\n private localStorage: LocalStorage.Interface,\n private listFilesUseCase: ListFilesUseCase.Interface,\n private filesListCache: FilesListCache.Interface,\n private getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface\n ) {\n makeAutoObservable<\n FileManagerPresenterImpl,\n \"_disposeReaction\" | \"fileDetailsPresenter\" | \"_persistFolder\"\n >(this, {\n _disposeReaction: false,\n fileDetailsPresenter: false,\n _persistFolder: false,\n vm: computed\n });\n\n const stored = this.localStorage.get<\"table\" | \"grid\">(VIEW_MODE_KEY);\n if (stored === \"table\" || stored === \"grid\") {\n this._viewMode = stored;\n }\n }\n\n get vm(): IFileManagerViewModel {\n return {\n fileModel: this._fileModel,\n list: this.listPresenter.vm,\n folders: this.folderTreePresenter.vm,\n fileDetails: this._fileDetails,\n // Flat booleans for UI visibility (e.g., show/hide buttons).\n // Per-file methods for ownership-aware checks (e.g., \"own\" scope).\n permissions: {\n canRead: this.permissions.canRead(\"file\"),\n canCreate: this.permissions.canCreate(\"file\"),\n canEdit: this.permissions.canEdit(\"file\"),\n canDelete: this.permissions.canDelete(\"file\"),\n canEditFile: (file: FmFile) => this.permissions.canEdit(\"file\", file),\n canDeleteFile: (file: FmFile) => this.permissions.canDelete(\"file\", file)\n },\n upload: {\n jobs: this.fileUploader.vm.jobs,\n overallProgress: {\n percentage: this.fileUploader.vm.overallProgress.percentage,\n bytesSent: this.fileUploader.vm.overallProgress.sent,\n totalBytes: this.fileUploader.vm.overallProgress.total\n },\n isUploading: this.fileUploader.vm.isUploading\n },\n tags: this.tagsRepository.tags,\n loading: this.isLoading(),\n empty: this.isEmpty(),\n showFolders: this.shouldShowFolders(),\n viewMode: this._viewMode,\n dragging: this._dragging,\n showingFilters: this._showingFilters\n };\n }\n\n actions: IFileManagerActions = {\n search: {\n set: (query: string) => this.listPresenter.actions.search.set(query),\n clear: () => this.listPresenter.actions.search.clear()\n },\n sort: {\n set: (field: string, direction: \"ASC\" | \"DESC\") =>\n this.listPresenter.actions.sort.set(field, direction),\n toggle: (field: string) => this.listPresenter.actions.sort.toggle(field)\n },\n filter: {\n set: (key: string, value: unknown) => this.listPresenter.actions.filter.set(key, value),\n clear: (key: string) => this.listPresenter.actions.filter.clear(key),\n clearAll: () => this.listPresenter.actions.filter.clearAll()\n },\n selection: {\n toggle: (id: string) => this.listPresenter.actions.selection.toggle(id),\n selectRangeTo: (id: string) => this.listPresenter.actions.selection.selectRangeTo(id),\n selectAll: () => this.listPresenter.actions.selection.selectAll(),\n deselectAll: () => this.listPresenter.actions.selection.deselectAll(),\n selectRows: (ids: string[]) => this.listPresenter.actions.selection.selectRows(ids),\n isSelected: (id: string) => this.listPresenter.actions.selection.isSelected(id)\n },\n loadMore: () => this.listPresenter.actions.loadMore(),\n refresh: () => this.listPresenter.actions.refresh(),\n upload: async (files: SelectedFile[]) => {\n const folderId = this.folderTreePresenter.vm.currentFolderId ?? \"root\";\n await this.fileUploader.uploadMany(\n files.map(file => ({\n file: file.src.file,\n data: {\n name: file.name,\n type: file.type,\n location: { folderId }\n }\n }))\n );\n this.fileUploader.clear();\n },\n setViewMode: (mode: \"table\" | \"grid\") => {\n this._viewMode = mode;\n this.localStorage.set(VIEW_MODE_KEY, mode);\n },\n setDragging: (dragging: boolean) => {\n this._dragging = dragging;\n },\n showFilters: () => {\n this._showingFilters = true;\n },\n hideFilters: () => {\n this._showingFilters = false;\n },\n showFileDetails: (id: string) => {\n this._fileDetails = this.fileDetailsPresenter;\n void this.fileDetailsPresenter.loadFile(id);\n },\n hideFileDetails: () => {\n this._fileDetails = null;\n },\n folders: {\n // Clear search when navigating to a folder — gives the user a clean slate.\n selectFolder: (folderId: string | null) => {\n this.listPresenter.actions.search.clear();\n this.folderTreePresenter.selectFolder(folderId);\n },\n createFolder: (parentFolderId?: string) =>\n this.folderTreePresenter.createFolder(parentFolderId),\n editFolder: (folderId: string) => this.folderTreePresenter.editFolder(folderId),\n deleteFolder: (folderId: string) => this.folderTreePresenter.deleteFolder(folderId),\n moveFolder: (folderId: string, targetParentId: string | null) =>\n this.folderTreePresenter.moveFolder(folderId, targetParentId),\n loadChildFolders: (parentIds: string[]) =>\n this.folderTreePresenter.loadChildFolders(parentIds),\n canManageStructure: (folderId: string) =>\n this.folderTreePresenter.canManageStructure(folderId),\n getAncestorIds: (folderId: string) => this.folderTreePresenter.getAncestorIds(folderId),\n submitOperation: () => this.folderTreePresenter.submitOperation(),\n cancelOperation: () => {\n this.folderTreePresenter.cancelOperation();\n }\n }\n };\n\n init(config?: IFileManagerInitConfig): void {\n const initialFolderId =\n config?.initialFolderId ?? this.localStorage.get<string>(LAST_FOLDER_KEY) ?? \"root\";\n\n // Don't persist folder navigation when an explicit initial folder is provided (e.g., overlay).\n this._persistFolder = !config?.initialFolderId;\n\n const dataSource = new FileListDataSource(\n this.listFilesUseCase,\n this.filesListCache,\n this.getDescendantFoldersUseCase,\n config?.scope\n );\n\n this.listPresenter.init({\n dataSource,\n initialSort: { field: \"createdOn\", direction: \"DESC\" },\n initialFilters: { folderId: initialFolderId },\n limit: 50\n });\n\n if (initialFolderId !== \"root\") {\n this.folderTreePresenter.selectFolder(initialFolderId);\n }\n\n // Sync folder navigation → file list: when the user selects a folder in the tree,\n // update the folderId filter so the file list re-queries for that folder's contents.\n this._disposeReaction = reaction(\n () => this.folderTreePresenter.vm.currentFolderId,\n folderId => {\n const effectiveFolderId = folderId ?? \"root\";\n this.listPresenter.actions.filter.set(\"folderId\", effectiveFolderId);\n\n if (this._persistFolder) {\n this.localStorage.set(LAST_FOLDER_KEY, effectiveFolderId);\n }\n }\n );\n\n void this.tagsRepository.execute({});\n\n // Load the CMS model in the background. The FileModelModule already kicks off\n // loading at app startup, so this usually resolves from cache instantly.\n // The view shows a loading overlay until `_fileModel` is set.\n void this.fileModelProvider.getModel().then(model => {\n runInAction(() => {\n this._fileModel = model;\n });\n });\n }\n\n dispose(): void {\n if (this._disposeReaction) {\n this._disposeReaction();\n this._disposeReaction = null;\n }\n }\n\n private isLoading(): boolean {\n return this.listPresenter.vm.pagination.loading && this.listPresenter.vm.rows.length === 0;\n }\n\n private isEmpty(): boolean {\n if (this.listPresenter.vm.pagination.loading) {\n return false;\n }\n\n if (this.listPresenter.vm.rows.length > 0) {\n return false;\n }\n\n if (this.shouldShowFolders() && this.folderTreePresenter.vm.childFolders.length > 0) {\n return false;\n }\n\n return true;\n }\n\n // Hide folders when the user is actively filtering or searching.\n // Uses `appliedQuery` (not `vm.search`) so folders stay visible while typing\n // and only disappear once the debounced query has actually executed.\n private shouldShowFolders(): boolean {\n const { appliedQuery } = this.listPresenter.vm;\n if (!appliedQuery) {\n return true;\n }\n\n if (appliedQuery.search) {\n return false;\n }\n\n // `folderId` is always present as a default filter; ignore it.\n const filterKeys = Object.keys(appliedQuery.filters ?? {}).filter(k => k !== \"folderId\");\n if (filterKeys.length > 0) {\n return false;\n }\n\n return true;\n }\n}\n\nexport const FileManagerPresenter = Abstraction.createImplementation({\n implementation: FileManagerPresenterImpl,\n dependencies: [\n ListPresenter,\n FolderTreePresenter,\n FileDetailsPresenter,\n FileManagerPermissions,\n ListTagsRepository,\n FileUploader,\n LocalStorage,\n ListFilesUseCase,\n FilesListCache,\n GetDescendantFoldersUseCase,\n FileModelProvider\n ]\n});\n"],"names":["VIEW_MODE_KEY","LAST_FOLDER_KEY","FileManagerPresenterImpl","listPresenter","folderTreePresenter","fileDetailsPresenter","permissions","tagsRepository","fileUploader","localStorage","listFilesUseCase","filesListCache","getDescendantFoldersUseCase","fileModelProvider","query","field","direction","key","value","id","ids","files","folderId","file","mode","dragging","parentFolderId","targetParentId","parentIds","makeAutoObservable","computed","stored","config","initialFolderId","dataSource","FileListDataSource","reaction","effectiveFolderId","model","runInAction","appliedQuery","filterKeys","Object","k","FileManagerPresenter","Abstraction","ListPresenter","FolderTreePresenter","FileDetailsPresenter","FileManagerPermissions","ListTagsRepository","FileUploader","LocalStorage","ListFilesUseCase","FilesListCache","GetDescendantFoldersUseCase","FileModelProvider"],"mappings":"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"}
1
+ {"version":3,"file":"presentation/FileList/FileManagerPresenter.js","sources":["../../../src/presentation/FileList/FileManagerPresenter.ts"],"sourcesContent":["import { makeAutoObservable, reaction, runInAction, computed } from \"mobx\";\nimport type { FmFile } from \"@webiny/sdk\";\nimport type { CmsModel } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport { ListPresenter } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport { FolderTreePresenter } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport { sortFolders } from \"@webiny/app-aco\";\nimport { LocalStorage } from \"@webiny/app/features/localStorage\";\nimport { GetDescendantFoldersUseCase } from \"@webiny/app-aco/features/folders/getDescendantFolders/abstractions.js\";\nimport {\n FileManagerPresenter as Abstraction,\n type IFileManagerPresenter,\n type IFileManagerViewModel,\n type IFileManagerActions,\n type IFileManagerInitConfig\n} from \"./abstractions.js\";\nimport { FileListDataSource } from \"./FileListDataSource.js\";\nimport { FileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport { FileManagerPermissions } from \"~/features/permissions/abstractions.js\";\nimport { ListTagsRepository } from \"~/features/tags/index.js\";\nimport { FileUploader } from \"~/features/fileUploader/index.js\";\nimport { ListFilesUseCase } from \"~/features/listFiles/index.js\";\nimport { FilesListCache } from \"~/features/shared/index.js\";\nimport { FileModelProvider } from \"~/features/fileModel/index.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { SelectedFile } from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\n\nconst VIEW_MODE_KEY = \"fm:viewMode\";\nconst LAST_FOLDER_KEY = \"fm:lastFolder\";\n\nclass FileManagerPresenterImpl implements IFileManagerPresenter {\n private _viewMode: \"table\" | \"grid\" = \"grid\";\n private _dragging = false;\n private _disposeReaction: (() => void) | null = null;\n private _fileDetails: IFileDetailsPresenter | null = null;\n private _showingFilters = false;\n private _fileModel: CmsModel | null = null;\n private _persistFolder = true;\n\n constructor(\n private listPresenter: ListPresenter.Interface<FmFile>,\n private folderTreePresenter: FolderTreePresenter.Interface,\n private fileDetailsPresenter: FileDetailsPresenter.Interface,\n private permissions: FileManagerPermissions.Interface,\n private tagsRepository: ListTagsRepository.Interface,\n private fileUploader: FileUploader.Interface,\n private localStorage: LocalStorage.Interface,\n private listFilesUseCase: ListFilesUseCase.Interface,\n private filesListCache: FilesListCache.Interface,\n private getDescendantFoldersUseCase: GetDescendantFoldersUseCase.Interface,\n private fileModelProvider: FileModelProvider.Interface\n ) {\n makeAutoObservable<\n FileManagerPresenterImpl,\n \"_disposeReaction\" | \"fileDetailsPresenter\" | \"_persistFolder\"\n >(this, {\n _disposeReaction: false,\n fileDetailsPresenter: false,\n _persistFolder: false,\n vm: computed\n });\n\n const stored = this.localStorage.get<\"table\" | \"grid\">(VIEW_MODE_KEY);\n if (stored === \"table\" || stored === \"grid\") {\n this._viewMode = stored;\n }\n }\n\n get vm(): IFileManagerViewModel {\n return {\n fileModel: this._fileModel,\n list: this.listPresenter.vm,\n folders: this.folderTreePresenter.vm,\n fileDetails: this._fileDetails,\n // Flat booleans for UI visibility (e.g., show/hide buttons).\n // Per-file methods for ownership-aware checks (e.g., \"own\" scope).\n permissions: {\n canRead: this.permissions.canRead(\"file\"),\n canCreate: this.permissions.canCreate(\"file\"),\n canEdit: this.permissions.canEdit(\"file\"),\n canDelete: this.permissions.canDelete(\"file\"),\n canEditFile: (file: FmFile) => this.permissions.canEdit(\"file\", file),\n canDeleteFile: (file: FmFile) => this.permissions.canDelete(\"file\", file)\n },\n upload: {\n jobs: this.fileUploader.vm.jobs,\n overallProgress: {\n percentage: this.fileUploader.vm.overallProgress.percentage,\n bytesSent: this.fileUploader.vm.overallProgress.sent,\n totalBytes: this.fileUploader.vm.overallProgress.total\n },\n isUploading: this.fileUploader.vm.isUploading\n },\n tags: this.tagsRepository.tags,\n loading: this.isLoading(),\n empty: this.isEmpty(),\n showFolders: this.shouldShowFolders(),\n childFolders: this.getSortedChildFolders(),\n viewMode: this._viewMode,\n dragging: this._dragging,\n showingFilters: this._showingFilters\n };\n }\n\n actions: IFileManagerActions = {\n search: {\n set: (query: string) => this.listPresenter.actions.search.set(query),\n clear: () => this.listPresenter.actions.search.clear()\n },\n sort: {\n set: (field: string, direction: \"ASC\" | \"DESC\") =>\n this.listPresenter.actions.sort.set(field, direction),\n toggle: (field: string) => this.listPresenter.actions.sort.toggle(field)\n },\n filter: {\n set: (key: string, value: unknown) => this.listPresenter.actions.filter.set(key, value),\n clear: (key: string) => this.listPresenter.actions.filter.clear(key),\n clearAll: () => this.listPresenter.actions.filter.clearAll(),\n show: () => this.listPresenter.actions.filter.show(),\n hide: () => this.listPresenter.actions.filter.hide()\n },\n selection: {\n toggle: (id: string) => this.listPresenter.actions.selection.toggle(id),\n selectRangeTo: (id: string) => this.listPresenter.actions.selection.selectRangeTo(id),\n selectAll: () => this.listPresenter.actions.selection.selectAll(),\n deselectAll: () => this.listPresenter.actions.selection.deselectAll(),\n selectRows: (ids: string[]) => this.listPresenter.actions.selection.selectRows(ids),\n isSelected: (id: string) => this.listPresenter.actions.selection.isSelected(id)\n },\n loadMore: () => this.listPresenter.actions.loadMore(),\n refresh: () => this.listPresenter.actions.refresh(),\n upload: async (files: SelectedFile[]) => {\n const folderId = this.folderTreePresenter.vm.currentFolderId ?? \"root\";\n await this.fileUploader.uploadMany(\n files.map(file => ({\n file: file.src.file,\n data: {\n name: file.name,\n type: file.type,\n location: { folderId }\n }\n }))\n );\n this.fileUploader.clear();\n },\n setViewMode: (mode: \"table\" | \"grid\") => {\n this._viewMode = mode;\n this.localStorage.set(VIEW_MODE_KEY, mode);\n },\n setDragging: (dragging: boolean) => {\n this._dragging = dragging;\n },\n showFilters: () => {\n this._showingFilters = true;\n },\n hideFilters: () => {\n this._showingFilters = false;\n },\n showFileDetails: (id: string) => {\n this._fileDetails = this.fileDetailsPresenter;\n void this.fileDetailsPresenter.loadFile(id);\n },\n hideFileDetails: () => {\n this._fileDetails = null;\n },\n folders: {\n // Clear search when navigating to a folder — gives the user a clean slate.\n selectFolder: (folderId: string | null) => {\n this.listPresenter.actions.search.clear();\n this.folderTreePresenter.selectFolder(folderId);\n },\n createFolder: (parentFolderId?: string) =>\n this.folderTreePresenter.createFolder(parentFolderId),\n editFolder: (folderId: string) => this.folderTreePresenter.editFolder(folderId),\n deleteFolder: (folderId: string) => this.folderTreePresenter.deleteFolder(folderId),\n moveFolder: (folderId: string, targetParentId: string | null) =>\n this.folderTreePresenter.moveFolder(folderId, targetParentId),\n loadChildFolders: (parentIds: string[]) =>\n this.folderTreePresenter.loadChildFolders(parentIds),\n canManageStructure: (folderId: string) =>\n this.folderTreePresenter.canManageStructure(folderId),\n getAncestorIds: (folderId: string) => this.folderTreePresenter.getAncestorIds(folderId),\n submitOperation: () => this.folderTreePresenter.submitOperation(),\n cancelOperation: () => {\n this.folderTreePresenter.cancelOperation();\n }\n }\n };\n\n init(config?: IFileManagerInitConfig): void {\n const initialFolderId =\n config?.initialFolderId ?? this.localStorage.get<string>(LAST_FOLDER_KEY) ?? \"root\";\n\n // Don't persist folder navigation when an explicit initial folder is provided (e.g., overlay).\n this._persistFolder = !config?.initialFolderId;\n\n const dataSource = new FileListDataSource(\n this.listFilesUseCase,\n this.filesListCache,\n this.getDescendantFoldersUseCase,\n config?.scope\n );\n\n const initialFilters: Record<string, unknown> = { folderId: initialFolderId };\n if (config?.accept && config.accept.length > 0) {\n initialFilters[\"accept\"] = config.accept;\n }\n\n this.listPresenter.init({\n dataSource,\n initialSort: { field: \"createdOn\", direction: \"DESC\" },\n initialFilters,\n limit: 50\n });\n\n if (initialFolderId !== \"root\") {\n this.folderTreePresenter.selectFolder(initialFolderId);\n }\n\n // Sync folder navigation → file list: when the user selects a folder in the tree,\n // update the folderId filter so the file list re-queries for that folder's contents.\n this._disposeReaction = reaction(\n () => this.folderTreePresenter.vm.currentFolderId,\n folderId => {\n const effectiveFolderId = folderId ?? \"root\";\n this.listPresenter.actions.filter.set(\"folderId\", effectiveFolderId);\n\n if (this._persistFolder) {\n this.localStorage.set(LAST_FOLDER_KEY, effectiveFolderId);\n }\n }\n );\n\n void this.tagsRepository.execute({});\n\n // Load the CMS model in the background. The FileModelModule already kicks off\n // loading at app startup, so this usually resolves from cache instantly.\n // The view shows a loading overlay until `_fileModel` is set.\n void this.fileModelProvider.getModel().then(model => {\n runInAction(() => {\n this._fileModel = model;\n });\n });\n }\n\n dispose(): void {\n if (this._disposeReaction) {\n this._disposeReaction();\n this._disposeReaction = null;\n }\n }\n\n private isLoading(): boolean {\n return this.listPresenter.vm.pagination.loading && this.listPresenter.vm.rows.length === 0;\n }\n\n private isEmpty(): boolean {\n if (this.listPresenter.vm.pagination.loading) {\n return false;\n }\n\n if (this.listPresenter.vm.rows.length > 0) {\n return false;\n }\n\n if (this.shouldShowFolders() && this.folderTreePresenter.vm.childFolders.length > 0) {\n return false;\n }\n\n return true;\n }\n\n private getSortedChildFolders() {\n if (!this.shouldShowFolders()) {\n return [];\n }\n return sortFolders(\n this.folderTreePresenter.vm.childFolders ?? [],\n this.listPresenter.vm.appliedQuery?.sort\n );\n }\n\n // Hide folders when the user is actively filtering or searching.\n // Uses `appliedQuery` (not `vm.search`) so folders stay visible while typing\n // and only disappear once the debounced query has actually executed.\n private shouldShowFolders(): boolean {\n const { appliedQuery } = this.listPresenter.vm;\n if (!appliedQuery) {\n return true;\n }\n\n if (appliedQuery.search) {\n return false;\n }\n\n // `folderId` is always present as a default filter; ignore it.\n const filterKeys = Object.keys(appliedQuery.filters ?? {}).filter(\n k => k !== \"folderId\" && k !== \"accept\"\n );\n if (filterKeys.length > 0) {\n return false;\n }\n\n return true;\n }\n}\n\nexport const FileManagerPresenter = Abstraction.createImplementation({\n implementation: FileManagerPresenterImpl,\n dependencies: [\n ListPresenter,\n FolderTreePresenter,\n FileDetailsPresenter,\n FileManagerPermissions,\n ListTagsRepository,\n FileUploader,\n LocalStorage,\n ListFilesUseCase,\n FilesListCache,\n GetDescendantFoldersUseCase,\n FileModelProvider\n ]\n});\n"],"names":["VIEW_MODE_KEY","LAST_FOLDER_KEY","FileManagerPresenterImpl","listPresenter","folderTreePresenter","fileDetailsPresenter","permissions","tagsRepository","fileUploader","localStorage","listFilesUseCase","filesListCache","getDescendantFoldersUseCase","fileModelProvider","query","field","direction","key","value","id","ids","files","folderId","file","mode","dragging","parentFolderId","targetParentId","parentIds","makeAutoObservable","computed","stored","config","initialFolderId","dataSource","FileListDataSource","initialFilters","reaction","effectiveFolderId","model","runInAction","sortFolders","appliedQuery","filterKeys","Object","k","FileManagerPresenter","Abstraction","ListPresenter","FolderTreePresenter","FileDetailsPresenter","FileManagerPermissions","ListTagsRepository","FileUploader","LocalStorage","ListFilesUseCase","FilesListCache","GetDescendantFoldersUseCase","FileModelProvider"],"mappings":"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"}
@@ -3,6 +3,7 @@ import type { CmsModel } from "@webiny/app-headless-cms-common/types/index.js";
3
3
  import type { IListViewModel } from "@webiny/app-admin/presentation/listPresenter/abstractions.js";
4
4
  import type { IListActions } from "@webiny/app-admin/presentation/listPresenter/abstractions.js";
5
5
  import type { IFolderTreeViewModel } from "@webiny/app-aco/presentation/folderTree/abstractions.js";
6
+ import type { FolderDto } from "@webiny/app-aco";
6
7
  import type { IFileDetailsPresenter } from "../FileDetails/abstractions.js";
7
8
  import type { FmFile } from "../../features/shared/types.js";
8
9
  import type { FmTag } from "../../features/shared/types.js";
@@ -10,6 +11,7 @@ import type { UploadJob } from "../../features/fileUploader/abstractions.js";
10
11
  export interface IFileManagerInitConfig {
11
12
  initialFolderId?: string;
12
13
  scope?: string;
14
+ accept?: string[];
13
15
  }
14
16
  export interface IFileManagerViewModel {
15
17
  fileModel: CmsModel | null;
@@ -29,6 +31,7 @@ export interface IFileManagerViewModel {
29
31
  loading: boolean;
30
32
  empty: boolean;
31
33
  showFolders: boolean;
34
+ childFolders: FolderDto[];
32
35
  viewMode: "table" | "grid";
33
36
  dragging: boolean;
34
37
  showingFilters: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"presentation/FileList/abstractions.js","sources":["../../../src/presentation/FileList/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { SelectedFile } from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\nimport type { CmsModel } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport type { IListViewModel } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { IListActions } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { IFolderTreeViewModel } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\nimport type { FmTag } from \"../../features/shared/types.js\";\nimport type { UploadJob } from \"../../features/fileUploader/abstractions.js\";\n\n// ---------------------------------------------------------------------------\n// Init config passed to presenter.init().\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerInitConfig {\n initialFolderId?: string;\n scope?: string;\n}\n\n// ---------------------------------------------------------------------------\n// FileManagerViewModel\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerViewModel {\n fileModel: CmsModel | null;\n list: IListViewModel<FmFile>;\n folders: IFolderTreeViewModel;\n fileDetails: IFileDetailsPresenter | null;\n tags: FmTag[];\n upload: {\n jobs: UploadJob[];\n overallProgress: { percentage: number; bytesSent: number; totalBytes: number };\n isUploading: boolean;\n };\n loading: boolean;\n empty: boolean;\n showFolders: boolean;\n viewMode: \"table\" | \"grid\";\n dragging: boolean;\n showingFilters: boolean;\n permissions: {\n canRead: boolean;\n canCreate: boolean;\n canEdit: boolean;\n canDelete: boolean;\n canEditFile: (file: FmFile) => boolean;\n canDeleteFile: (file: FmFile) => boolean;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Folder actions exposed by the FileManagerPresenter.\n// ---------------------------------------------------------------------------\n\nexport interface IFolderActions {\n selectFolder(folderId: string | null): void;\n createFolder(parentFolderId?: string): void;\n editFolder(folderId: string): void;\n deleteFolder(folderId: string): Promise<void>;\n moveFolder(folderId: string, targetParentId: string | null): Promise<void>;\n loadChildFolders(parentIds: string[]): Promise<void>;\n canManageStructure(folderId: string): boolean;\n getAncestorIds(folderId: string): string[];\n submitOperation(): Promise<boolean>;\n cancelOperation(): void;\n}\n\n// ---------------------------------------------------------------------------\n// FileManagerPresenter actions (extends ListActions with domain-specific actions).\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerActions extends IListActions {\n showFileDetails(id: string): void;\n hideFileDetails(): void;\n upload(files: SelectedFile[]): Promise<void>;\n setViewMode(mode: \"table\" | \"grid\"): void;\n setDragging(dragging: boolean): void;\n showFilters(): void;\n hideFilters(): void;\n folders: IFolderActions;\n}\n\n// ---------------------------------------------------------------------------\n// IFileManagerPresenter\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerPresenter {\n vm: IFileManagerViewModel;\n actions: IFileManagerActions;\n init(config?: IFileManagerInitConfig): void;\n dispose(): void;\n}\n\nexport const FileManagerPresenter =\n createAbstraction<IFileManagerPresenter>(\"FileManagerPresenter\");\n\nexport namespace FileManagerPresenter {\n export type Interface = IFileManagerPresenter;\n export type ViewModel = IFileManagerViewModel;\n export type Actions = IFileManagerActions;\n export type InitConfig = IFileManagerInitConfig;\n}\n"],"names":["FileManagerPresenter","createAbstraction"],"mappings":";AA8FO,MAAMA,uBACTC,kBAAyC"}
1
+ {"version":3,"file":"presentation/FileList/abstractions.js","sources":["../../../src/presentation/FileList/abstractions.ts"],"sourcesContent":["import { createAbstraction } from \"@webiny/feature/admin\";\nimport type { SelectedFile } from \"@webiny/app-admin/presentation/browserFilePicker/index.js\";\nimport type { CmsModel } from \"@webiny/app-headless-cms-common/types/index.js\";\nimport type { IListViewModel } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { IListActions } from \"@webiny/app-admin/presentation/listPresenter/abstractions.js\";\nimport type { IFolderTreeViewModel } from \"@webiny/app-aco/presentation/folderTree/abstractions.js\";\nimport type { FolderDto } from \"@webiny/app-aco\";\nimport type { IFileDetailsPresenter } from \"../FileDetails/abstractions.js\";\nimport type { FmFile } from \"../../features/shared/types.js\";\nimport type { FmTag } from \"../../features/shared/types.js\";\nimport type { UploadJob } from \"../../features/fileUploader/abstractions.js\";\n\n// ---------------------------------------------------------------------------\n// Init config passed to presenter.init().\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerInitConfig {\n initialFolderId?: string;\n scope?: string;\n accept?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// FileManagerViewModel\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerViewModel {\n fileModel: CmsModel | null;\n list: IListViewModel<FmFile>;\n folders: IFolderTreeViewModel;\n fileDetails: IFileDetailsPresenter | null;\n tags: FmTag[];\n upload: {\n jobs: UploadJob[];\n overallProgress: { percentage: number; bytesSent: number; totalBytes: number };\n isUploading: boolean;\n };\n loading: boolean;\n empty: boolean;\n showFolders: boolean;\n childFolders: FolderDto[];\n viewMode: \"table\" | \"grid\";\n dragging: boolean;\n showingFilters: boolean;\n permissions: {\n canRead: boolean;\n canCreate: boolean;\n canEdit: boolean;\n canDelete: boolean;\n canEditFile: (file: FmFile) => boolean;\n canDeleteFile: (file: FmFile) => boolean;\n };\n}\n\n// ---------------------------------------------------------------------------\n// Folder actions exposed by the FileManagerPresenter.\n// ---------------------------------------------------------------------------\n\nexport interface IFolderActions {\n selectFolder(folderId: string | null): void;\n createFolder(parentFolderId?: string): void;\n editFolder(folderId: string): void;\n deleteFolder(folderId: string): Promise<void>;\n moveFolder(folderId: string, targetParentId: string | null): Promise<void>;\n loadChildFolders(parentIds: string[]): Promise<void>;\n canManageStructure(folderId: string): boolean;\n getAncestorIds(folderId: string): string[];\n submitOperation(): Promise<boolean>;\n cancelOperation(): void;\n}\n\n// ---------------------------------------------------------------------------\n// FileManagerPresenter actions (extends ListActions with domain-specific actions).\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerActions extends IListActions {\n showFileDetails(id: string): void;\n hideFileDetails(): void;\n upload(files: SelectedFile[]): Promise<void>;\n setViewMode(mode: \"table\" | \"grid\"): void;\n setDragging(dragging: boolean): void;\n showFilters(): void;\n hideFilters(): void;\n folders: IFolderActions;\n}\n\n// ---------------------------------------------------------------------------\n// IFileManagerPresenter\n// ---------------------------------------------------------------------------\n\nexport interface IFileManagerPresenter {\n vm: IFileManagerViewModel;\n actions: IFileManagerActions;\n init(config?: IFileManagerInitConfig): void;\n dispose(): void;\n}\n\nexport const FileManagerPresenter =\n createAbstraction<IFileManagerPresenter>(\"FileManagerPresenter\");\n\nexport namespace FileManagerPresenter {\n export type Interface = IFileManagerPresenter;\n export type ViewModel = IFileManagerViewModel;\n export type Actions = IFileManagerActions;\n export type InitConfig = IFileManagerInitConfig;\n}\n"],"names":["FileManagerPresenter","createAbstraction"],"mappings":";AAiGO,MAAMA,uBACTC,kBAAyC"}
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
2
  export declare const getFilesLabel: (count?: number) => string;
3
- export declare const BulkActionBar: (() => React.JSX.Element | null) & {
4
- displayName: string;
3
+ export declare const BulkActionBar: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
4
+ readonly type: () => React.JSX.Element | null;
5
5
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionDelete: (() => React.JSX.Element | null) & {
3
- displayName: string;
2
+ export declare const BulkActionDelete: (() => React.JSX.Element | null) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element | null;
4
4
  };
@@ -1,4 +1,4 @@
1
1
  import React from "react";
2
- export declare const BulkActionMove: (() => React.JSX.Element) & {
3
- displayName: string;
2
+ export declare const BulkActionMove: (() => React.JSX.Element) & React.NamedExoticComponent<unknown> & {
3
+ readonly type: () => React.JSX.Element;
4
4
  };
@@ -1,5 +1,4 @@
1
1
  export { BulkActionBar, getFilesLabel } from "./BulkActionBar.js";
2
2
  export { BulkActionDelete } from "./BulkActionDelete.js";
3
3
  export { BulkActionMove } from "./BulkActionMove.js";
4
- export { BulkActionEdit } from "./BulkActionEdit.js";
5
4
  export { BulkAction } from "./useBulkActionWorker.js";
@@ -1,5 +1,4 @@
1
1
  export { BulkActionBar, getFilesLabel } from "./BulkActionBar.js";
2
2
  export { BulkActionDelete } from "./BulkActionDelete.js";
3
3
  export { BulkActionMove } from "./BulkActionMove.js";
4
- export { BulkActionEdit } from "./BulkActionEdit.js";
5
4
  export { BulkAction } from "./useBulkActionWorker.js";
@@ -1,16 +1,17 @@
1
1
  import type { CallbackParams } from "@webiny/app-admin";
2
2
  import type { FmFile } from "../../../../features/shared/types.js";
3
3
  import { getFilesLabel } from "./BulkActionBar.js";
4
+ declare const useWorker: () => {
5
+ items: FmFile[];
6
+ process: (callback: (items: FmFile[]) => void) => void;
7
+ processInSeries: (callback: ({ item, allItems, report }: CallbackParams<FmFile>) => Promise<void>, chunkSize?: number) => Promise<void>;
8
+ resetItems: () => void;
9
+ results: import("@webiny/app-admin").Result[];
10
+ resetResults: () => Promise<void>;
11
+ };
4
12
  export declare const BulkAction: {
5
13
  useButtons: () => import("@webiny/app-admin/components/Buttons/useButtons.js").ButtonsProviderContext;
6
- useWorker: () => {
7
- items: FmFile[];
8
- process: (callback: (items: FmFile[]) => void) => void;
9
- processInSeries: (callback: ({ item, allItems, report }: CallbackParams<FmFile>) => Promise<void>, chunkSize?: number) => Promise<void>;
10
- resetItems: () => void;
11
- results: import("@webiny/app-admin").Result[];
12
- resetResults: () => Promise<void>;
13
- };
14
+ useWorker: typeof useWorker;
14
15
  useDialog: () => import("@webiny/app-admin").UseDialogWithReportResponse;
15
16
  };
16
17
  export { getFilesLabel };
@@ -1,4 +1,4 @@
1
- import { useCallback, useEffect, useMemo, useRef } from "react";
1
+ import { useCallback, useMemo, useRef } from "react";
2
2
  import { Worker, useButtons, useDialogWithReport } from "@webiny/app-admin";
3
3
  import { useFileManagerPresenter } from "../../FileManagerPresenterProvider.js";
4
4
  const useWorker = ()=>{
@@ -11,13 +11,7 @@ const useWorker = ()=>{
11
11
  vm.list.selection.selectedIds,
12
12
  vm.list.rows
13
13
  ]);
14
- useEffect(()=>{
15
- worker.items = selectedFiles;
16
- }, [
17
- selectedFiles.length
18
- ]);
19
14
  const resetItems = useCallback(()=>{
20
- worker.items = [];
21
15
  actions.selection.deselectAll();
22
16
  }, []);
23
17
  const resetResults = useCallback(async ()=>{
@@ -25,8 +19,8 @@ const useWorker = ()=>{
25
19
  }, []);
26
20
  return {
27
21
  items: selectedFiles,
28
- process: (callback)=>worker.process(callback),
29
- processInSeries: async (callback, chunkSize)=>worker.processInSeries(callback, chunkSize),
22
+ process: (callback)=>worker.process(selectedFiles, callback),
23
+ processInSeries: async (callback, chunkSize)=>worker.processInSeries(selectedFiles, callback, chunkSize),
30
24
  resetItems,
31
25
  results: worker.results,
32
26
  resetResults