@acorex-platform/module-document-management-client 0.0.53 → 0.0.56

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 (88) hide show
  1. package/fesm2022/{acorex-platform-module-document-management-client-acorex-platform-module-document-management-client--0oIEHPI.mjs → acorex-platform-module-document-management-client-acorex-platform-module-document-management-client-qhcOFKFu.mjs} +1068 -436
  2. package/fesm2022/acorex-platform-module-document-management-client-acorex-platform-module-document-management-client-qhcOFKFu.mjs.map +1 -0
  3. package/fesm2022/{acorex-platform-module-document-management-client-attachment-view-skeleton.component-CP6yjHx7.mjs → acorex-platform-module-document-management-client-attachment-view-skeleton.component-BeQSbax5.mjs} +2 -2
  4. package/fesm2022/{acorex-platform-module-document-management-client-attachment-view-skeleton.component-CP6yjHx7.mjs.map → acorex-platform-module-document-management-client-attachment-view-skeleton.component-BeQSbax5.mjs.map} +1 -1
  5. package/fesm2022/acorex-platform-module-document-management-client-attachment-widget.component-CsrcMMC9.mjs +37 -0
  6. package/fesm2022/acorex-platform-module-document-management-client-attachment-widget.component-CsrcMMC9.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-module-document-management-client-contracts-entities-document-type.mjs +1 -0
  8. package/fesm2022/acorex-platform-module-document-management-client-contracts-entities-document-type.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-module-document-management-client-contracts-entities-document.mjs +15 -0
  10. package/fesm2022/acorex-platform-module-document-management-client-contracts-entities-document.mjs.map +1 -1
  11. package/fesm2022/acorex-platform-module-document-management-client-contracts-entities-folder.mjs +27 -0
  12. package/fesm2022/acorex-platform-module-document-management-client-contracts-entities-folder.mjs.map +1 -1
  13. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-acorex-platform-module-document-management-client-contracts-entity-catalog-BxwUMlCE.mjs → acorex-platform-module-document-management-client-contracts-entity-catalog-acorex-platform-module-document-management-client-contracts-entity-catalog-qzPWMiWF.mjs} +6 -6
  14. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-acorex-platform-module-document-management-client-contracts-entity-catalog-BxwUMlCE.mjs.map → acorex-platform-module-document-management-client-contracts-entity-catalog-acorex-platform-module-document-management-client-contracts-entity-catalog-qzPWMiWF.mjs.map} +1 -1
  15. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-document-shortcut.entity-D-hEBLFT.mjs → acorex-platform-module-document-management-client-contracts-entity-catalog-document-shortcut.entity-BELnXED1.mjs} +2 -2
  16. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-document-shortcut.entity-D-hEBLFT.mjs.map → acorex-platform-module-document-management-client-contracts-entity-catalog-document-shortcut.entity-BELnXED1.mjs.map} +1 -1
  17. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-document-type.entity-CBMUwrc-.mjs → acorex-platform-module-document-management-client-contracts-entity-catalog-document-type.entity-BSphQjSb.mjs} +3 -2
  18. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog-document-type.entity-BSphQjSb.mjs.map +1 -0
  19. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-document-version.entity-hATC_iAQ.mjs → acorex-platform-module-document-management-client-contracts-entity-catalog-document-version.entity-B9vWDzsE.mjs} +2 -2
  20. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-document-version.entity-hATC_iAQ.mjs.map → acorex-platform-module-document-management-client-contracts-entity-catalog-document-version.entity-B9vWDzsE.mjs.map} +1 -1
  21. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-document.entity-DOvhTOtO.mjs → acorex-platform-module-document-management-client-contracts-entity-catalog-document.entity-oFmhqAWA.mjs} +17 -2
  22. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog-document.entity-oFmhqAWA.mjs.map +1 -0
  23. package/fesm2022/{acorex-platform-module-document-management-client-contracts-entity-catalog-folder.entity-cNSFyJoY.mjs → acorex-platform-module-document-management-client-contracts-entity-catalog-folder.entity-BqKpRAiP.mjs} +29 -2
  24. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog-folder.entity-BqKpRAiP.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog.mjs +1 -1
  26. package/fesm2022/acorex-platform-module-document-management-client-contracts.mjs +2 -0
  27. package/fesm2022/acorex-platform-module-document-management-client-contracts.mjs.map +1 -1
  28. package/fesm2022/acorex-platform-module-document-management-client-details-view-skeleton.component-BnRZrzCX.mjs +19 -0
  29. package/fesm2022/acorex-platform-module-document-management-client-details-view-skeleton.component-BnRZrzCX.mjs.map +1 -0
  30. package/fesm2022/acorex-platform-module-document-management-client-details-view.component-DkCD8RSd.mjs +472 -0
  31. package/fesm2022/acorex-platform-module-document-management-client-details-view.component-DkCD8RSd.mjs.map +1 -0
  32. package/fesm2022/{acorex-platform-module-document-management-client-distribute-document.command-CCLwJcFb.mjs → acorex-platform-module-document-management-client-distribute-document.command-BaCdm2YF.mjs} +2 -2
  33. package/fesm2022/{acorex-platform-module-document-management-client-distribute-document.command-CCLwJcFb.mjs.map → acorex-platform-module-document-management-client-distribute-document.command-BaCdm2YF.mjs.map} +1 -1
  34. package/fesm2022/{acorex-platform-module-document-management-client-drive-choose.component-Bq4semJF.mjs → acorex-platform-module-document-management-client-drive-choose.component-up9sAsei.mjs} +2 -2
  35. package/fesm2022/{acorex-platform-module-document-management-client-drive-choose.component-Bq4semJF.mjs.map → acorex-platform-module-document-management-client-drive-choose.component-up9sAsei.mjs.map} +1 -1
  36. package/fesm2022/{acorex-platform-module-document-management-client-large-icons-view-skeleton.component-CXDBviff.mjs → acorex-platform-module-document-management-client-large-icons-view-skeleton.component-C_VbFRKl.mjs} +2 -2
  37. package/fesm2022/{acorex-platform-module-document-management-client-large-icons-view-skeleton.component-CXDBviff.mjs.map → acorex-platform-module-document-management-client-large-icons-view-skeleton.component-C_VbFRKl.mjs.map} +1 -1
  38. package/fesm2022/acorex-platform-module-document-management-client-large-icons-view.component-Cece4n22.mjs +31 -0
  39. package/fesm2022/{acorex-platform-module-document-management-client-large-icons-view.component-COT_8z2S.mjs.map → acorex-platform-module-document-management-client-large-icons-view.component-Cece4n22.mjs.map} +1 -1
  40. package/fesm2022/acorex-platform-module-document-management-client-large-tiles-view.component-DzWIUZtv.mjs +36 -0
  41. package/fesm2022/{acorex-platform-module-document-management-client-large-tiles-view.component-Dm-MSIUn.mjs.map → acorex-platform-module-document-management-client-large-tiles-view.component-DzWIUZtv.mjs.map} +1 -1
  42. package/fesm2022/acorex-platform-module-document-management-client-link-dialog.component-EYoimqRD.mjs +119 -0
  43. package/fesm2022/acorex-platform-module-document-management-client-link-dialog.component-EYoimqRD.mjs.map +1 -0
  44. package/fesm2022/{acorex-platform-module-document-management-client-list-view-skeleton.component-D-QA5J07.mjs → acorex-platform-module-document-management-client-list-view-skeleton.component-Dgx8lVyN.mjs} +2 -2
  45. package/fesm2022/{acorex-platform-module-document-management-client-list-view-skeleton.component-D-QA5J07.mjs.map → acorex-platform-module-document-management-client-list-view-skeleton.component-Dgx8lVyN.mjs.map} +1 -1
  46. package/fesm2022/acorex-platform-module-document-management-client-list-view.component-DVUfHWHB.mjs +31 -0
  47. package/fesm2022/{acorex-platform-module-document-management-client-list-view.component-CDldLoV-.mjs.map → acorex-platform-module-document-management-client-list-view.component-DVUfHWHB.mjs.map} +1 -1
  48. package/fesm2022/{acorex-platform-module-document-management-client-open-document.command--tM4SRV7.mjs → acorex-platform-module-document-management-client-open-document.command-Bimm2bzt.mjs} +3 -2
  49. package/fesm2022/acorex-platform-module-document-management-client-open-document.command-Bimm2bzt.mjs.map +1 -0
  50. package/fesm2022/acorex-platform-module-document-management-client-share-dialog.component-CFI4hK3T.mjs +89 -0
  51. package/fesm2022/acorex-platform-module-document-management-client-share-dialog.component-CFI4hK3T.mjs.map +1 -0
  52. package/fesm2022/acorex-platform-module-document-management-client-share-email-dialog.component-CUvlAcp6.mjs +84 -0
  53. package/fesm2022/acorex-platform-module-document-management-client-share-email-dialog.component-CUvlAcp6.mjs.map +1 -0
  54. package/fesm2022/{acorex-platform-module-document-management-client-small-icons-view-skeleton.component-Cmgqsr4e.mjs → acorex-platform-module-document-management-client-small-icons-view-skeleton.component-CU2MiVUi.mjs} +2 -2
  55. package/fesm2022/{acorex-platform-module-document-management-client-small-icons-view-skeleton.component-Cmgqsr4e.mjs.map → acorex-platform-module-document-management-client-small-icons-view-skeleton.component-CU2MiVUi.mjs.map} +1 -1
  56. package/fesm2022/acorex-platform-module-document-management-client-small-icons-view.component-CL5cNRtI.mjs +31 -0
  57. package/fesm2022/{acorex-platform-module-document-management-client-small-icons-view.component-IC5bdYey.mjs.map → acorex-platform-module-document-management-client-small-icons-view.component-CL5cNRtI.mjs.map} +1 -1
  58. package/fesm2022/{acorex-platform-module-document-management-client-small-tiles-view-skeleton.component-DzDonT_e.mjs → acorex-platform-module-document-management-client-small-tiles-view-skeleton.component-DBJldDaS.mjs} +2 -2
  59. package/fesm2022/{acorex-platform-module-document-management-client-small-tiles-view-skeleton.component-DzDonT_e.mjs.map → acorex-platform-module-document-management-client-small-tiles-view-skeleton.component-DBJldDaS.mjs.map} +1 -1
  60. package/fesm2022/acorex-platform-module-document-management-client-small-tiles-view.component-DtsBSVCq.mjs +36 -0
  61. package/fesm2022/{acorex-platform-module-document-management-client-small-tiles-view.component-NUNfAl3M.mjs.map → acorex-platform-module-document-management-client-small-tiles-view.component-DtsBSVCq.mjs.map} +1 -1
  62. package/fesm2022/{acorex-platform-module-document-management-client-upload-document.command-CCRAgI9w.mjs → acorex-platform-module-document-management-client-upload-document.command-D3L6x6CQ.mjs} +3 -3
  63. package/fesm2022/{acorex-platform-module-document-management-client-upload-document.command-CCRAgI9w.mjs.map → acorex-platform-module-document-management-client-upload-document.command-D3L6x6CQ.mjs.map} +1 -1
  64. package/fesm2022/acorex-platform-module-document-management-client.mjs +1 -1
  65. package/i18n/en-AU/document-management.json +664 -0
  66. package/i18n/en-US/document-management.json +664 -0
  67. package/i18n/fa-IR/document-management.json +664 -0
  68. package/package.json +2 -2
  69. package/types/acorex-platform-module-document-management-client-contracts.d.ts +59 -3
  70. package/types/acorex-platform-module-document-management-client.d.ts +92 -7
  71. package/fesm2022/acorex-platform-module-document-management-client-acorex-platform-module-document-management-client--0oIEHPI.mjs.map +0 -1
  72. package/fesm2022/acorex-platform-module-document-management-client-attachment-widget.component-DmgzUrWY.mjs +0 -37
  73. package/fesm2022/acorex-platform-module-document-management-client-attachment-widget.component-DmgzUrWY.mjs.map +0 -1
  74. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog-document-type.entity-CBMUwrc-.mjs.map +0 -1
  75. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog-document.entity-DOvhTOtO.mjs.map +0 -1
  76. package/fesm2022/acorex-platform-module-document-management-client-contracts-entity-catalog-folder.entity-cNSFyJoY.mjs.map +0 -1
  77. package/fesm2022/acorex-platform-module-document-management-client-large-icons-view.component-COT_8z2S.mjs +0 -31
  78. package/fesm2022/acorex-platform-module-document-management-client-large-tiles-view.component-Dm-MSIUn.mjs +0 -36
  79. package/fesm2022/acorex-platform-module-document-management-client-link-dialog.component-CUFgI0_q.mjs +0 -77
  80. package/fesm2022/acorex-platform-module-document-management-client-link-dialog.component-CUFgI0_q.mjs.map +0 -1
  81. package/fesm2022/acorex-platform-module-document-management-client-list-view.component-CDldLoV-.mjs +0 -31
  82. package/fesm2022/acorex-platform-module-document-management-client-open-document.command--tM4SRV7.mjs.map +0 -1
  83. package/fesm2022/acorex-platform-module-document-management-client-share-dialog.component-CyO_2Ppm.mjs +0 -148
  84. package/fesm2022/acorex-platform-module-document-management-client-share-dialog.component-CyO_2Ppm.mjs.map +0 -1
  85. package/fesm2022/acorex-platform-module-document-management-client-share-email-dialog.component-6B0KXT1Z.mjs +0 -58
  86. package/fesm2022/acorex-platform-module-document-management-client-share-email-dialog.component-6B0KXT1Z.mjs.map +0 -1
  87. package/fesm2022/acorex-platform-module-document-management-client-small-icons-view.component-IC5bdYey.mjs +0 -31
  88. package/fesm2022/acorex-platform-module-document-management-client-small-tiles-view.component-NUNfAl3M.mjs +0 -36
@@ -1,12 +1,12 @@
1
1
  import { AXPTaskBadgeProvider, resolveFileChooserExtension, AXPFileChooserService, AXPFileViewerService, AXPFileViewerFallbackContentComponent, AXP_FILE_CHOOSER_PROVIDERS, AXP_FILE_UPLOADER_PROVIDERS, isUnrestrictedFileAccept, fileNameMatchesAccept, AXPStateMessageComponent, AXPLayoutSideDetailPanelComponent, AXPLayoutSideDetailPanelSectionDirective, AXP_PAGE_COMPONENT_PROVIDER, AXP_TASK_BADGE_PROVIDERS, provideFileViewer, AXPThemeLayoutBlockComponent, AXPQueryFiltersComponent } from '@acorex-platform/framework-client/layout/components';
2
2
  import { AXPEntityService, resolveEntityPluginDetailPageOrder, ensureListActions, AXPEntityDefinitionRegistryService, AXPMiddlewareAbortError, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_STORAGE_MIDDLEWARE } from '@acorex-platform/framework-client/layout/entity';
3
3
  import { AXPEntityBroadcastService, AXPHookService, AXPDataGenerator as AXPDataGenerator$1, AXPDeviceService, AXPExpressionEvaluatorService, AXPDebugService, AXP_FEATURE_DEFINITION_PROVIDER, AXP_HOOK_PROVIDER } from '@acorex-platform/framework-client/core';
4
- import { AXPSearchCommandProvider, createEntitySearchCommand, AXPFileTypeProviderService, AXP_FILE_TYPE_INFO_PROVIDER, extractRequestErrorInfo, platformErrorI18nKey, AXPFileStorageService, resolveExplorerFileDisplayName, tryOpenFileByCatalogType, createFileTypeOpenContext, FILE_VIEWER_PREVIEW_EXTENSIONS, isFileNameShownInViewer, normalizeDocumentToFileListItem, UploadFromComputerActionProvider, AXP_FILE_ACTION_PROVIDER, hasFileTypeOpenHandler, resolveFileTypeDisplay, AXPSettingsService, AXPLockService, AXP_PROTECTED_ROUTE_GUARDS, AXP_STATUS_PROVIDERS, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/common';
4
+ import { AXPSearchCommandProvider, createEntitySearchCommand, AXPFileTypeProviderService, AXP_FILE_TYPE_INFO_PROVIDER, AXPFileStorageService, extractRequestErrorInfo, platformErrorI18nKey, resolveExplorerFileDisplayName, tryOpenFileByCatalogType, createFileTypeOpenContext, FILE_VIEWER_PREVIEW_EXTENSIONS, isFileNameShownInViewer, normalizeDocumentToFileListItem, UploadFromComputerActionProvider, AXP_FILE_ACTION_PROVIDER, hasFileTypeOpenHandler, resolveFileTypeDisplay, AXPSettingsService, AXPLockService, AXP_PROTECTED_ROUTE_GUARDS, AXP_STATUS_PROVIDERS, AXP_MENU_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTING_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/common';
5
5
  import { AXPSessionService, AXP_PERMISSION_DEFINITION_PROVIDER } from '@acorex-platform/framework-client/auth';
6
6
  import * as i0 from '@angular/core';
7
7
  import { Injectable, inject, DestroyRef, signal, ChangeDetectionStrategy, Component, NgModule, viewChild, computed, Injector, PLATFORM_ID, input, effect, ViewEncapsulation, untracked, HostListener } from '@angular/core';
8
8
  import { AXPDocumentManagementFeatureKeys, AXPContentDocumentsPermissionKeys, RootConfig, AXPDocumentManagementMenuKeys, AXPDocumentManagementSettings, AXMDocumentManagementCommandKeys } from '@acorex-platform/module-document-management-client/contracts';
9
- import { AXPCommonPermissionGroupKeys, AXPCommonMenuKeys, AXP_VERSIONING_ERROR_I18N, AXPVersioningField, AXPVersioningStatus, AXPCommonCommandKeys } from '@acorex-platform/module-common-client/contracts';
9
+ import { AXPCommonPermissionGroupKeys, AXPCommonMenuKeys, AXP_VERSIONING_ERROR_I18N, AXPVersioningField, AXPVersioningStatus, AXPCommonCommandKeys, isMaintainVersioningPermissionGranted } from '@acorex-platform/module-common-client/contracts';
10
10
  import { firstValueFrom, combineLatest } from 'rxjs';
11
11
  import { AXPCommandEventsService, AXPCommandService, AXPQueryService, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
12
12
  import { AXPWidgetsList, AXPSystemStatusType, AXPStatusProvider, systemStatusToDefinition, AXPPlatformScope, AXPDataGenerator, AXP_QUERY_QUICK_SEARCH_FIELD, runtimeCommandPayloadData, runtimeQueryPayloadData, runtimeQueryCollectionData, AXPRegionalSetting, getSmart, AXP_PLATFORM_ERROR_CODES, resolvePlatformScopeKey, collectQueryFilterLeaves, isQueryFilterAllNode, resolvePlatformScopeName } from '@acorex-platform/framework-shared/core';
@@ -39,9 +39,10 @@ import { CommonModule, AsyncPipe } from '@angular/common';
39
39
  import { RouterModule, ActivatedRoute, ROUTES } from '@angular/router';
40
40
  import { AXDialogService } from '@acorex/components/dialog';
41
41
  import { AXPopupService } from '@acorex/components/popup';
42
- import { AXPLayoutBuilderService } from '@acorex-platform/framework-client/layout/builder';
42
+ import { AXPLayoutBuilderService, resolveLayoutBuilderDialogResult } from '@acorex-platform/framework-client/layout/builder';
43
43
  import { unset, castArray, isArray, defaultTo, isEmpty as isEmpty$1, set, get as get$1, isString as isString$1 } from 'lodash';
44
44
  import { toDocumentExpirationDate, AXM_DOCUMENT_EXPIRATION_NEAR_DAYS, getDocumentExpirationRemainingDays, extractDocumentTypeFileKindNames, AXMDocumentManagementQueryKeys } from '@acorex-platform/module-document-management-client/contracts';
45
+ import { mergeMetaDataLists, filterMetaDataListByAppliesTo, hasMetaDataListFields } from '@acorex-platform/module-data-management-client/contracts';
45
46
  import { AXToastService } from '@acorex/components/toast';
46
47
  import { AXPPageLayoutBaseComponent, AXPPageLayoutBase, AXPPageLayoutComponent } from '@acorex-platform/framework-client/layout/views';
47
48
  import * as i1$4 from '@acorex/components/badge';
@@ -926,7 +927,7 @@ var fileTypeExtensionView_component = /*#__PURE__*/Object.freeze({
926
927
 
927
928
  const AXmFileTypeExtensionWidget = {
928
929
  name: 'file-type-extension',
929
- title: 'File Type Extension',
930
+ title: '@document-management:widgets.file-type-extension.title',
930
931
  description: 'Uploads and manages files',
931
932
  icon: 'fa-light fa-files',
932
933
  categories: AXP_WIDGETS_ADVANCE_CATEGORY,
@@ -987,8 +988,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
987
988
 
988
989
  const AXmDocumentFileTypeFilterWidget = {
989
990
  name: 'document-file-type-filter',
990
- title: 'File Type Filter',
991
+ title: '@document-management:widgets.file-type-filter.title',
991
992
  type: 'filter',
993
+ defaultFilterOperator: 'equal',
992
994
  icon: 'fa-light fa-file',
993
995
  properties: [AXP_NAME_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DISABLED_PROPERTY],
994
996
  components: {
@@ -1239,6 +1241,28 @@ function resolveFolderExpirationCountBadges(source) {
1239
1241
  }
1240
1242
  //#endregion
1241
1243
 
1244
+ /** Storage id from a document `fileInfo` object or `file:` reference. */
1245
+ function resolveDocumentStorageFileId(fileInfo) {
1246
+ if (!fileInfo) {
1247
+ return undefined;
1248
+ }
1249
+ if (typeof fileInfo === 'string') {
1250
+ return fileInfo.startsWith('file:') ? fileInfo.slice(5) : fileInfo;
1251
+ }
1252
+ const item = fileInfo;
1253
+ if (item.source?.kind === 'fileId' && typeof item.source.value === 'string') {
1254
+ const storedId = item.source.value.replace(/^file:/, '').trim();
1255
+ return storedId || undefined;
1256
+ }
1257
+ // Chooser items use a client UUID on `id` with `source.kind === 'blob'` — that is not storage.
1258
+ if (item.source?.kind === 'blob') {
1259
+ return undefined;
1260
+ }
1261
+ if (typeof item.id === 'string' && item.id.trim() !== '') {
1262
+ return item.id.replace(/^file:/, '');
1263
+ }
1264
+ return undefined;
1265
+ }
1242
1266
  /**
1243
1267
  * Resolves demo / seeded asset URLs to the current app origin.
1244
1268
  * Handles relative `/assets/...` paths and legacy absolute URLs baked in at seed time (e.g. localhost:4200).
@@ -1325,6 +1349,53 @@ function folderColorToRgbChannels(color) {
1325
1349
  }
1326
1350
  //#endregion
1327
1351
 
1352
+ //#region ----- Imports -----
1353
+ //#endregion
1354
+ //#region ----- Schema helpers -----
1355
+ function toEditableMetaDataList(list) {
1356
+ return {
1357
+ groups: (list?.groups ?? []).map((group) => ({
1358
+ ...group,
1359
+ fields: (group.fields ?? []).map((field) => ({
1360
+ ...field,
1361
+ mode: 'edit',
1362
+ })),
1363
+ })),
1364
+ };
1365
+ }
1366
+ function toViewMetaDataList(list) {
1367
+ return {
1368
+ groups: (list?.groups ?? []).map((group) => ({
1369
+ ...group,
1370
+ fields: (group.fields ?? []).map((field) => ({
1371
+ ...field,
1372
+ mode: 'view',
1373
+ })),
1374
+ })),
1375
+ };
1376
+ }
1377
+ function collectFolderScopedMetaDataList(documentTypes) {
1378
+ return mergeMetaDataLists(documentTypes.map((documentType) => filterMetaDataListByAppliesTo(documentType?.metaDataList, 'folder')));
1379
+ }
1380
+ function collectDocumentScopedMetaDataList(list) {
1381
+ return filterMetaDataListByAppliesTo(list, 'document');
1382
+ }
1383
+ function documentTypeHasFolderMetadata(documentTypes) {
1384
+ return hasMetaDataListFields(collectFolderScopedMetaDataList(documentTypes));
1385
+ }
1386
+ function pickMetaDataFormValues(form, schema) {
1387
+ const names = new Set((schema?.groups ?? []).flatMap((group) => (group.fields ?? []).map((field) => String(field?.name ?? '').trim()).filter(Boolean)));
1388
+ const source = form ?? {};
1389
+ const picked = {};
1390
+ for (const name of names) {
1391
+ if (name in source) {
1392
+ picked[name] = source[name];
1393
+ }
1394
+ }
1395
+ return picked;
1396
+ }
1397
+ //#endregion
1398
+
1328
1399
  //#region ---- Document type accept helpers ----
1329
1400
  /**
1330
1401
  * Extracts logical file type names from a document type's `type` field.
@@ -1362,6 +1433,52 @@ function buildAcceptFromDocumentType(documentType) {
1362
1433
  }
1363
1434
  //#endregion
1364
1435
 
1436
+ //#region ----- Document user-field helpers -----
1437
+ function attachedFileDefaultTitle(file) {
1438
+ const title = typeof file?.title === 'string' ? file.title.trim() : '';
1439
+ if (title) {
1440
+ return title;
1441
+ }
1442
+ const name = typeof file?.name === 'string' ? file.name.trim() : '';
1443
+ if (!name) {
1444
+ return '';
1445
+ }
1446
+ const lastDot = name.lastIndexOf('.');
1447
+ return lastDot > 0 ? name.slice(0, lastDot) : name;
1448
+ }
1449
+ function asOptionalTrimmedString(value) {
1450
+ if (typeof value !== 'string') {
1451
+ return undefined;
1452
+ }
1453
+ const trimmed = value.trim();
1454
+ return trimmed || undefined;
1455
+ }
1456
+ /** Builds a stored file name from a document title, keeping the original extension. */
1457
+ function fileNameFromTitle(title, originalFileName) {
1458
+ const trimmed = title.trim();
1459
+ if (!trimmed) {
1460
+ return originalFileName?.trim() || '';
1461
+ }
1462
+ const lastDot = originalFileName?.lastIndexOf('.') ?? -1;
1463
+ const extension = originalFileName && lastDot > 0 ? originalFileName.slice(lastDot) : '';
1464
+ if (!extension) {
1465
+ return trimmed;
1466
+ }
1467
+ if (trimmed.toLowerCase().endsWith(extension.toLowerCase())) {
1468
+ return trimmed;
1469
+ }
1470
+ return `${trimmed}${extension}`;
1471
+ }
1472
+ /** Copies document title onto the related file name, keeping the original extension. */
1473
+ function fileInfoWithTitle(file, title) {
1474
+ const name = fileNameFromTitle(title, file?.name);
1475
+ if (!file) {
1476
+ return { name };
1477
+ }
1478
+ return { name, file: { ...file, name, title } };
1479
+ }
1480
+ //#endregion
1481
+
1365
1482
  //#region ----- Helpers -----
1366
1483
  function isTruthyFlag(value) {
1367
1484
  return value === true || value === 'true' || value === 1 || value === '1';
@@ -1395,6 +1512,7 @@ class AXMDocumentDialogService {
1395
1512
  this.toastService = inject(AXToastService);
1396
1513
  this.entityService = inject(AXPEntityService);
1397
1514
  this.fileService = inject(AXFileService);
1515
+ this.fileStorageService = inject(AXPFileStorageService);
1398
1516
  this.documentData = this.entityService
1399
1517
  .withEntity(RootConfig.module.name, RootConfig.entities.document.name)
1400
1518
  .data();
@@ -1406,34 +1524,34 @@ class AXMDocumentDialogService {
1406
1524
  //#endregion
1407
1525
  //#region ---- Public API ----
1408
1526
  async openAttachmentDialog(title, data) {
1409
- const { documentType, files, parentId, metaData, documentId, versionDraftId, version, showMeta = true } = data ?? {};
1527
+ const { documentType, files, parentId, metaData, documentId, versionDraftId, showMeta = true, existingTitle, existingDescription, existingExpirationDate, replaceFile = false, skipMetadataAiFill = false, } = data ?? {};
1410
1528
  const { accept } = await buildFileChooserOptionsFromDocumentType(documentType, this.fileService);
1411
1529
  const fileList = Array.isArray(files) ? files : [];
1412
1530
  const enableExpiration = !!documentType?.enableExpiration;
1413
- const editableMetaDataList = documentType?.metaDataList && documentType.metaDataList.groups
1414
- ? {
1415
- ...documentType.metaDataList,
1416
- groups: (documentType.metaDataList.groups ?? []).map((group) => ({
1417
- ...group,
1418
- fields: (group.fields ?? []).map((field) => ({
1419
- ...field,
1420
- mode: 'edit',
1421
- })),
1422
- })),
1423
- }
1424
- : { groups: [] };
1531
+ const editableMetaDataList = toEditableMetaDataList(collectDocumentScopedMetaDataList(documentType?.metaDataList));
1425
1532
  const hasMetaFields = (editableMetaDataList.groups ?? []).some((g) => (g.fields?.length ?? 0) > 0);
1426
- // Build initial context for all files
1427
1533
  const initialContext = {};
1428
- if (showMeta) {
1429
- initialContext['file-0'] = {
1430
- metaDataForm: metaData,
1431
- ...(enableExpiration && metaData && metaData.expirationDate != null
1432
- ? { expirationDate: metaData.expirationDate }
1534
+ fileList.forEach((item, index) => {
1535
+ const fileMeta = showMeta ? metaData : undefined;
1536
+ initialContext[`file-${index}`] = {
1537
+ title: asOptionalTrimmedString(existingTitle) ?? attachedFileDefaultTitle(item),
1538
+ description: asOptionalTrimmedString(existingDescription) ?? '',
1539
+ ...(showMeta ? { metaDataForm: fileMeta } : {}),
1540
+ ...(enableExpiration
1541
+ ? {
1542
+ expirationDate: existingExpirationDate ??
1543
+ fileMeta?.expirationDate,
1544
+ }
1433
1545
  : {}),
1434
1546
  };
1547
+ });
1548
+ if (fileList.length === 0) {
1549
+ initialContext['file-0'] = {
1550
+ title: asOptionalTrimmedString(existingTitle) ?? '',
1551
+ description: asOptionalTrimmedString(existingDescription) ?? '',
1552
+ ...(showMeta ? { metaDataForm: metaData } : {}),
1553
+ };
1435
1554
  }
1436
- // Initialize files array context with default values
1437
1555
  initialContext['files'] = fileList.map((item) => ({ file: [item] }));
1438
1556
  const result = await this.layoutBuilder
1439
1557
  .create()
@@ -1447,28 +1565,33 @@ class AXMDocumentDialogService {
1447
1565
  hasMetaFields,
1448
1566
  parentId: parentId ?? '',
1449
1567
  documentType,
1568
+ skipMetadataAiFill: skipMetadataAiFill === true,
1450
1569
  },
1451
1570
  })
1452
1571
  .setContext(initialContext)
1453
1572
  .content((flex) => {
1454
1573
  flex.setDirection('column');
1455
- // Add fields for each file dynamically
1456
1574
  for (let index = 0; index < fileList.length; index++) {
1457
1575
  const item = fileList[index];
1458
- if (showMeta) {
1459
- if (hasMetaFields) {
1460
- // Bind meta-data-form-editor to file-${index}.metaDataForm (no form-field wrapper).
1461
- flex.customWidget('meta-data-form-editor', (widget) => {
1462
- widget.path(`file-${index}.metaDataForm`);
1463
- widget.options(editableMetaDataList);
1464
- });
1465
- }
1466
- if (enableExpiration) {
1467
- flex.formField('@document-management:terms.document.expire-date', (field) => {
1468
- field.path(`file-${index}.expirationDate`);
1469
- field.dateTimeBox({});
1470
- });
1471
- }
1576
+ flex.formField('@general:terms.common.title', (field) => {
1577
+ field.path(`file-${index}.title`);
1578
+ field.textBox({ validations: [{ rule: 'required' }] });
1579
+ });
1580
+ flex.formField('@general:terms.common.description', (field) => {
1581
+ field.path(`file-${index}.description`);
1582
+ field.textBox({});
1583
+ });
1584
+ if (enableExpiration) {
1585
+ flex.formField('@document-management:terms.document.expire-date', (field) => {
1586
+ field.path(`file-${index}.expirationDate`);
1587
+ field.dateTimeBox({});
1588
+ });
1589
+ }
1590
+ if (showMeta && hasMetaFields) {
1591
+ flex.customWidget('meta-data-form-editor', (widget) => {
1592
+ widget.path(`file-${index}.metaDataForm`);
1593
+ widget.options(editableMetaDataList);
1594
+ });
1472
1595
  }
1473
1596
  flex.formField('@document-management:terms.common.file', (field) => {
1474
1597
  field.path(`files[${index}].file`);
@@ -1492,36 +1615,43 @@ class AXMDocumentDialogService {
1492
1615
  return { data: { cancel: true } };
1493
1616
  }
1494
1617
  const ctx = dialogRef.context();
1495
- const metaDataFormWithExpiration = (context, fileIndex) => {
1496
- const meta = context?.[`file-${fileIndex}`]?.['metaDataForm'];
1497
- const exp = context?.[`file-${fileIndex}`]?.['expirationDate'];
1498
- return { ...(meta || {}), ...(exp != null ? { expirationDate: exp } : {}) };
1499
- };
1500
1618
  if (documentId) {
1501
1619
  dialogRef.setLoading(true);
1502
1620
  try {
1503
- const meta = showMeta ? metaDataFormWithExpiration(ctx, 0) : undefined;
1504
- if (versionDraftId) {
1505
- const draftPayload = {};
1506
- if (meta) {
1507
- draftPayload.metaDataForm = meta;
1508
- if (meta.expirationDate != null) {
1509
- draftPayload.expirationDate = meta.expirationDate;
1621
+ const userFields = this.readUserDocumentFields(ctx, 0, {
1622
+ showMeta,
1623
+ enableExpiration,
1624
+ });
1625
+ const sourceFile = fileList[0];
1626
+ const synced = fileInfoWithTitle(sourceFile, userFields.title);
1627
+ await this.syncStoredFileName(sourceFile, synced.name);
1628
+ const identity = {
1629
+ title: userFields.title,
1630
+ name: synced.name,
1631
+ ...(!replaceFile && synced.file ? { fileInfo: synced.file } : {}),
1632
+ };
1633
+ const content = {
1634
+ description: userFields.description,
1635
+ ...(userFields.metaDataForm ? { metaDataForm: userFields.metaDataForm } : {}),
1636
+ ...(enableExpiration
1637
+ ? {
1638
+ expirationDate: (userFields.expirationDate ??
1639
+ null),
1510
1640
  }
1511
- }
1512
- await this.documentVersionData.update(String(versionDraftId), draftPayload);
1641
+ : {}),
1642
+ ...(replaceFile && synced.file
1643
+ ? { fileInfo: synced.file, name: synced.name }
1644
+ : {}),
1645
+ };
1646
+ if (versionDraftId) {
1647
+ await this.documentVersionData.update(String(versionDraftId), {
1648
+ ...identity,
1649
+ ...content,
1650
+ });
1651
+ await this.documentData.update(documentId, identity);
1513
1652
  }
1514
1653
  else {
1515
- const hostPayload = {
1516
- version: (version ?? 0) + 1,
1517
- };
1518
- if (meta) {
1519
- hostPayload.metaDataForm = meta;
1520
- if (meta.expirationDate != null) {
1521
- hostPayload.expirationDate = meta.expirationDate;
1522
- }
1523
- }
1524
- await this.documentData.update(documentId, hostPayload);
1654
+ await this.documentData.update(documentId, { ...identity, ...content });
1525
1655
  }
1526
1656
  return {
1527
1657
  data: {
@@ -1532,7 +1662,6 @@ class AXMDocumentDialogService {
1532
1662
  }
1533
1663
  catch (error) {
1534
1664
  await this.notifyAttachFailed(error);
1535
- // Dialog renderer keeps the dialog open when onAction throws.
1536
1665
  throw error;
1537
1666
  }
1538
1667
  finally {
@@ -1543,20 +1672,26 @@ class AXMDocumentDialogService {
1543
1672
  try {
1544
1673
  const promises = (ctx?.['files']).map(async (_item, index) => {
1545
1674
  const f = fileList[index];
1546
- const meta = metaDataFormWithExpiration(ctx, index);
1675
+ const userFields = this.readUserDocumentFields(ctx, index, {
1676
+ showMeta,
1677
+ enableExpiration,
1678
+ });
1679
+ const synced = fileInfoWithTitle(f, userFields.title);
1680
+ await this.syncStoredFileName(f, synced.name);
1547
1681
  const newId = await this.documentData.create({
1548
- fileInfo: f,
1549
- name: f?.name,
1550
- title: f?.title ?? f?.name,
1551
- description: f?.description,
1682
+ fileInfo: synced.file ?? f,
1683
+ name: synced.name,
1684
+ title: userFields.title,
1685
+ description: userFields.description,
1552
1686
  documentType,
1553
1687
  parentId: folderParentId(parentId) ?? parentId,
1554
1688
  ...initialDocumentLifecycleStatus(documentType),
1555
1689
  versioningEnabled: isTruthyFlag(documentType?.enableVersioning),
1556
1690
  distributionEnabled: isTruthyFlag(documentType?.enableDistributionCapability),
1557
- version: (version ?? 0) + 1,
1558
- metaDataForm: meta,
1559
- ...(meta?.expirationDate != null ? { expirationDate: meta.expirationDate } : {}),
1691
+ ...(userFields.metaDataForm ? { metaDataForm: userFields.metaDataForm } : {}),
1692
+ ...(enableExpiration && userFields.expirationDate != null
1693
+ ? { expirationDate: userFields.expirationDate }
1694
+ : {}),
1560
1695
  });
1561
1696
  return newId;
1562
1697
  });
@@ -1570,7 +1705,6 @@ class AXMDocumentDialogService {
1570
1705
  }
1571
1706
  catch (error) {
1572
1707
  await this.notifyAttachFailed(error);
1573
- // Dialog renderer keeps the dialog open when onAction throws.
1574
1708
  throw error;
1575
1709
  }
1576
1710
  finally {
@@ -1588,23 +1722,27 @@ class AXMDocumentDialogService {
1588
1722
  const enableExpiration = !!documentType?.enableExpiration;
1589
1723
  /** Get metaDataForm from a file item (widget may store under meta or metaDataForm). */
1590
1724
  const getFileMeta = (item) => item?.metaDataForm ?? (item?.meta && typeof item.meta === 'object' && !Array.isArray(item.meta) ? item.meta : undefined);
1591
- const hasMetaFields = (documentType?.metaDataList?.groups ?? []).some((g) => (g.fields?.length ?? 0) > 0);
1592
- // Build initial context for all files: each file-${index} gets that file's metaDataForm so form shows existing meta
1725
+ const editableMetaDataList = toEditableMetaDataList(collectDocumentScopedMetaDataList(documentType?.metaDataList));
1726
+ const hasMetaFields = (editableMetaDataList.groups ?? []).some((g) => (g.fields?.length ?? 0) > 0);
1593
1727
  const initialContext = {};
1594
- if (showMeta) {
1595
- fileList.forEach((item, index) => {
1596
- const fileMeta = getFileMeta(item) ?? metaData;
1597
- initialContext[`file-${index}`] = {
1598
- metaDataForm: fileMeta,
1599
- ...(enableExpiration && fileMeta && fileMeta.expirationDate != null
1600
- ? { expirationDate: fileMeta.expirationDate }
1601
- : {}),
1602
- };
1603
- });
1604
- if (fileList.length === 0)
1605
- initialContext['file-0'] = { metaDataForm: metaData };
1728
+ fileList.forEach((item, index) => {
1729
+ const fileMeta = getFileMeta(item) ?? metaData;
1730
+ initialContext[`file-${index}`] = {
1731
+ title: attachedFileDefaultTitle(item),
1732
+ description: asOptionalTrimmedString(item?.description) ?? '',
1733
+ ...(showMeta ? { metaDataForm: fileMeta } : {}),
1734
+ ...(enableExpiration
1735
+ ? { expirationDate: fileMeta?.expirationDate }
1736
+ : {}),
1737
+ };
1738
+ });
1739
+ if (fileList.length === 0) {
1740
+ initialContext['file-0'] = {
1741
+ title: '',
1742
+ description: '',
1743
+ ...(showMeta ? { metaDataForm: metaData } : {}),
1744
+ };
1606
1745
  }
1607
- // Initialize files array context with default values
1608
1746
  initialContext['files'] = fileList.map((item) => ({ file: [item] }));
1609
1747
  const result = await this.layoutBuilder
1610
1748
  .create()
@@ -1623,25 +1761,29 @@ class AXMDocumentDialogService {
1623
1761
  .setContext(initialContext)
1624
1762
  .content((flex) => {
1625
1763
  flex.setDirection('column');
1626
- // Add fields for each file dynamically
1627
1764
  for (let index = 0; index < fileList.length; index++) {
1628
1765
  const item = fileList[index];
1629
- if (showMeta) {
1630
- if (hasMetaFields) {
1631
- const metaListForWidget = documentType?.metaDataList ?? { groups: [] };
1632
- flex.customWidget('meta-data-form-editor', (widget) => {
1633
- widget.path(`file-${index}.metaDataForm`);
1634
- widget.options(metaListForWidget);
1635
- });
1636
- }
1637
- if (enableExpiration) {
1638
- flex.formField('@document-management:terms.document.expire-date', (field) => {
1639
- field.path(`file-${index}.expirationDate`);
1640
- field.dateTimeBox({});
1641
- });
1642
- }
1766
+ flex.formField('@general:terms.common.title', (field) => {
1767
+ field.path(`file-${index}.title`);
1768
+ field.textBox({ validations: [{ rule: 'required' }] });
1769
+ });
1770
+ flex.formField('@general:terms.common.description', (field) => {
1771
+ field.path(`file-${index}.description`);
1772
+ field.textBox({});
1773
+ });
1774
+ if (enableExpiration) {
1775
+ flex.formField('@document-management:terms.document.expire-date', (field) => {
1776
+ field.path(`file-${index}.expirationDate`);
1777
+ field.dateTimeBox({});
1778
+ });
1643
1779
  }
1644
- flex.formField('File', (field) => {
1780
+ if (showMeta && hasMetaFields) {
1781
+ flex.customWidget('meta-data-form-editor', (widget) => {
1782
+ widget.path(`file-${index}.metaDataForm`);
1783
+ widget.options(editableMetaDataList);
1784
+ });
1785
+ }
1786
+ flex.formField('@document-management:terms.common.file', (field) => {
1645
1787
  field.path(`files[${index}].file`);
1646
1788
  field.customWidget('attachments', {
1647
1789
  defaultValue: [item],
@@ -1665,15 +1807,23 @@ class AXMDocumentDialogService {
1665
1807
  };
1666
1808
  }
1667
1809
  const ctx = dialogRef.context();
1668
- const metaDataFormWithExpiration = (context, fileIndex) => {
1669
- const meta = context?.[`file-${fileIndex}`]?.['metaDataForm'];
1670
- const exp = context?.[`file-${fileIndex}`]?.['expirationDate'];
1671
- return { ...(meta || {}), ...(exp != null ? { expirationDate: exp } : {}) };
1672
- };
1673
- const outFiles = (ctx?.['files']).map((item, index) => ({
1674
- ...item,
1675
- ...(showMeta ? { metaDataForm: metaDataFormWithExpiration(ctx, index) } : {}),
1676
- }));
1810
+ const outFiles = (ctx?.['files']).map((item, index) => {
1811
+ const userFields = this.readUserDocumentFields(ctx, index, {
1812
+ showMeta,
1813
+ enableExpiration,
1814
+ });
1815
+ const sourceFile = Array.isArray(item?.file) ? item.file[0] : fileList[index];
1816
+ const synced = fileInfoWithTitle(sourceFile, userFields.title);
1817
+ return {
1818
+ ...item,
1819
+ name: synced.name,
1820
+ title: userFields.title,
1821
+ description: userFields.description,
1822
+ ...(synced.file ? { file: [synced.file] } : {}),
1823
+ ...(showMeta ? { metaDataForm: userFields.metaDataForm } : {}),
1824
+ ...(enableExpiration ? { expirationDate: userFields.expirationDate } : {}),
1825
+ };
1826
+ });
1677
1827
  return { data: { cancel: false, files: outFiles } };
1678
1828
  });
1679
1829
  })
@@ -1717,6 +1867,32 @@ class AXMDocumentDialogService {
1717
1867
  }
1718
1868
  //#endregion
1719
1869
  //#region ---- Private helpers ----
1870
+ async syncStoredFileName(file, nextName) {
1871
+ const storageId = resolveDocumentStorageFileId(file);
1872
+ if (!storageId || !nextName) {
1873
+ return;
1874
+ }
1875
+ try {
1876
+ await this.fileStorageService.update({
1877
+ fileId: storageId,
1878
+ name: nextName,
1879
+ metadata: {},
1880
+ });
1881
+ }
1882
+ catch {
1883
+ // Blob uploads persist the title-based name on save; do not fail attach if rename misses.
1884
+ }
1885
+ }
1886
+ readUserDocumentFields(context, fileIndex, options) {
1887
+ const bag = (context[`file-${fileIndex}`] ?? {});
1888
+ const title = asOptionalTrimmedString(bag['title']) ?? '';
1889
+ const description = asOptionalTrimmedString(bag['description']);
1890
+ const meta = options.showMeta ? bag['metaDataForm'] : undefined;
1891
+ const expirationDate = options.enableExpiration
1892
+ ? (bag['expirationDate'] ?? null)
1893
+ : undefined;
1894
+ return { title, description, metaDataForm: meta, expirationDate };
1895
+ }
1720
1896
  async notifyAttachFailed(error) {
1721
1897
  const info = extractRequestErrorInfo(error);
1722
1898
  const contentKey = (info?.code ? AXP_VERSIONING_ERROR_I18N[info.code] : undefined) ??
@@ -1745,7 +1921,6 @@ class DocumentAttachmentsService {
1745
1921
  .data();
1746
1922
  this.documentDialog = inject(AXMDocumentDialogService);
1747
1923
  this.translateService = inject(AXTranslationService);
1748
- this.toastService = inject(AXToastService);
1749
1924
  this.documentVersionData = this.entityService
1750
1925
  .withEntity(RootConfig.module.name, RootConfig.entities.documentVersion.name)
1751
1926
  .data();
@@ -1762,7 +1937,6 @@ class DocumentAttachmentsService {
1762
1937
  documentType: fileTypeEntity,
1763
1938
  files,
1764
1939
  parentId: options?.folderId ?? '',
1765
- version: 0,
1766
1940
  };
1767
1941
  const title = await this.translateService.translateAsync('@document-management:dialogs.attach-file.title', {
1768
1942
  params: { title: this.translateService.resolve(fileTypeEntity.title) },
@@ -1776,34 +1950,21 @@ class DocumentAttachmentsService {
1776
1950
  throw new Error('File not found');
1777
1951
  }
1778
1952
  const documentTypeEntity = await this.resolveFileType(file.documentType);
1779
- if (file.versioningEnabled) {
1780
- const draft = await this.findOpenVersionDraft(fileId);
1781
- if (!draft) {
1782
- await this.notifyHostContentLocked();
1783
- return false;
1784
- }
1785
- const draftRow = await this.documentVersionData.byKey(draft.id);
1786
- const popupData = {
1787
- documentType: documentTypeEntity,
1788
- files: [draftRow?.fileInfo ?? file.fileInfo],
1789
- parentId: options?.folderId ?? '',
1790
- metaData: draftRow?.metaDataForm ?? file.metaDataForm,
1791
- documentId: fileId,
1792
- versionDraftId: draft.id,
1793
- version: file.version,
1794
- };
1795
- const result = await this.documentDialog.openAttachmentDialog(`Edit ${file.name}`, popupData);
1796
- return this.handlePopupResult(result);
1797
- }
1798
1953
  const popupData = {
1799
1954
  documentType: documentTypeEntity,
1800
1955
  files: [file.fileInfo],
1801
1956
  parentId: options?.folderId ?? '',
1802
1957
  metaData: file.metaDataForm,
1803
1958
  documentId: fileId,
1804
- version: file.version,
1959
+ existingTitle: file.title,
1960
+ existingDescription: file.description,
1961
+ existingExpirationDate: file.expirationDate,
1805
1962
  };
1806
- const result = await this.documentDialog.openAttachmentDialog(`Edit ${file.name}`, popupData);
1963
+ const editTitle = await this.translateService.translateAsync('@document-management:dialogs.attach-file.edit-title', { params: { title: file.title || file.name } });
1964
+ const result = await this.documentDialog.openAttachmentDialog(editTitle, {
1965
+ ...popupData,
1966
+ skipMetadataAiFill: true,
1967
+ });
1807
1968
  return this.handlePopupResult(result);
1808
1969
  }
1809
1970
  /**
@@ -1823,23 +1984,17 @@ class DocumentAttachmentsService {
1823
1984
  if (fileItems.length === 0) {
1824
1985
  return false;
1825
1986
  }
1826
- const result = await this.documentDialog.openAttachmentDialogWithoutSave('@document-management:dialogs.manage-version.upload-new-version', {
1987
+ const dialogTitle = await this.translateService.translateAsync('@document-management:dialogs.manage-version.upload-new-version');
1988
+ const popupData = {
1827
1989
  documentType: documentTypeEntity,
1828
1990
  files: fileItems,
1829
1991
  parentId: document.parentId,
1830
1992
  metaData: document.metaDataForm,
1831
- showMeta: false,
1832
- });
1833
- if (result?.data?.cancel) {
1834
- return false;
1835
- }
1836
- const metaDataForm = document.metaDataForm;
1837
- const newName = fileItems[0]?.name ?? document.name;
1838
- const payload = {
1839
- fileInfo: fileItems[0],
1840
- metaDataForm,
1841
- name: newName,
1842
- title: newName,
1993
+ documentId: fileId,
1994
+ existingTitle: document.title,
1995
+ existingDescription: document.description,
1996
+ existingExpirationDate: document.expirationDate,
1997
+ replaceFile: true,
1843
1998
  };
1844
1999
  if (document.versioningEnabled) {
1845
2000
  let draft = await this.findOpenVersionDraft(fileId);
@@ -1849,14 +2004,14 @@ class DocumentAttachmentsService {
1849
2004
  });
1850
2005
  draft = { id: String(createdId) };
1851
2006
  }
1852
- await this.documentVersionData.update(draft.id, payload);
1853
- return true;
2007
+ const result = await this.documentDialog.openAttachmentDialog(dialogTitle, {
2008
+ ...popupData,
2009
+ versionDraftId: draft.id,
2010
+ });
2011
+ return this.handlePopupResult(result);
1854
2012
  }
1855
- await this.documentData.update(fileId, {
1856
- ...payload,
1857
- version: (document.version ?? 0) + 1,
1858
- });
1859
- return true;
2013
+ const result = await this.documentDialog.openAttachmentDialog(dialogTitle, popupData);
2014
+ return this.handlePopupResult(result);
1860
2015
  }
1861
2016
  async findOpenVersionDraft(documentId) {
1862
2017
  const result = await this.documentVersionData.query({
@@ -1877,13 +2032,6 @@ class DocumentAttachmentsService {
1877
2032
  const row = result?.items?.[0];
1878
2033
  return row?.id ? { id: String(row.id) } : null;
1879
2034
  }
1880
- async notifyHostContentLocked() {
1881
- this.toastService.show({
1882
- color: 'warning',
1883
- title: await this.translateService.translateAsync('@general:messages.generic.error.title'),
1884
- content: await this.translateService.translateAsync('@general:errors.versioning.host-content-locked'),
1885
- });
1886
- }
1887
2035
  validateAttachmentOptions(options) {
1888
2036
  if (!((options?.entityId && options?.entityRecordId) || options?.folderId)) {
1889
2037
  throw new Error('You must provide either both entityId and entityRecordId, or folderId.');
@@ -1940,6 +2088,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
1940
2088
  }]
1941
2089
  }] });
1942
2090
 
2091
+ //#endregion
2092
+ //#region ----- Service -----
2093
+ class AXMFolderMetadataDialogService {
2094
+ constructor() {
2095
+ //#region ----- Services & Dependencies -----
2096
+ this.entityService = inject(AXPEntityService);
2097
+ this.documentTypeData = this.entityService
2098
+ .withEntity(RootConfig.module.name, RootConfig.entities.documentType.name)
2099
+ .data();
2100
+ }
2101
+ //#endregion
2102
+ //#region ----- Public API -----
2103
+ /**
2104
+ * Fills `metaDataList` on picker rows when the list query omitted it.
2105
+ */
2106
+ async hydrateDocumentTypeCatalog(items) {
2107
+ const hydrated = [];
2108
+ for (const item of items) {
2109
+ if (item?.['metaDataList'] != null) {
2110
+ hydrated.push(item);
2111
+ continue;
2112
+ }
2113
+ const id = item['id'] ?? item['documentTypeId'];
2114
+ if (id == null || !String(id).trim()) {
2115
+ hydrated.push(item);
2116
+ continue;
2117
+ }
2118
+ try {
2119
+ const loaded = await this.documentTypeData.byKey(String(id));
2120
+ if (loaded?.metaDataList != null) {
2121
+ hydrated.push({ ...item, metaDataList: loaded.metaDataList });
2122
+ continue;
2123
+ }
2124
+ }
2125
+ catch {
2126
+ // Keep the slim picker row when the type cannot be loaded.
2127
+ }
2128
+ hydrated.push(item);
2129
+ }
2130
+ return hydrated;
2131
+ }
2132
+ /** Adds the reactive folder-scoped metadata form to a create/update folder dialog. */
2133
+ addFolderMetadataForm(flex, catalog) {
2134
+ flex.customWidget('meta-data-form-editor', (widget) => {
2135
+ widget.path('metaDataForm');
2136
+ widget.options({
2137
+ sourcePath: 'documentTypes',
2138
+ appliesTo: 'folder',
2139
+ hideEmpty: true,
2140
+ sourceCatalog: catalog,
2141
+ });
2142
+ });
2143
+ }
2144
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMFolderMetadataDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2145
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMFolderMetadataDialogService, providedIn: 'root' }); }
2146
+ }
2147
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMFolderMetadataDialogService, decorators: [{
2148
+ type: Injectable,
2149
+ args: [{ providedIn: 'root' }]
2150
+ }] });
2151
+
1943
2152
  //#region ---- Imports ----
1944
2153
  //#endregion
1945
2154
  //#region ---- Contract (Abstract Service) ----
@@ -1981,6 +2190,7 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
1981
2190
  this.layoutBuilder = inject(AXPLayoutBuilderService);
1982
2191
  this.fileViewerService = inject(AXPFileViewerService);
1983
2192
  this.attachmentsService = inject(DocumentAttachmentsService);
2193
+ this.folderMetadataDialog = inject(AXMFolderMetadataDialogService);
1984
2194
  this.hooks = inject(AXPHookService, { optional: true });
1985
2195
  //#endregion
1986
2196
  //#region ---- Private Properties ----
@@ -2008,9 +2218,12 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
2008
2218
  size: folder.size,
2009
2219
  color: folder.color,
2010
2220
  documentTypes: folder.documentTypes || [],
2221
+ childFolderDocumentTypes: folder.childFolderDocumentTypes || [],
2222
+ allowChildFolders: folder.allowChildFolders,
2011
2223
  storageType: 'physical',
2012
2224
  inherit: folder.inherit,
2013
2225
  isSystem: Boolean(folder.stateInfo?.isSystem),
2226
+ metaDataForm: folder.metaDataForm,
2014
2227
  children: [...(folder.folders?.map(this.mapFolderDtoToFolderNode) || []), ...(folder.documents?.map(this.mapFileToNode) || []), ...(folder.shortcuts?.map(this.mapShortcutToNode) || [])],
2015
2228
  };
2016
2229
  };
@@ -2084,6 +2297,8 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
2084
2297
  const node = {
2085
2298
  id: file.id,
2086
2299
  name: file.name,
2300
+ title: file.title,
2301
+ description: file.description,
2087
2302
  type: 'file',
2088
2303
  parentId: file.parentId,
2089
2304
  modifiedAt: file?.updated?.at,
@@ -2098,6 +2313,9 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
2098
2313
  versionId: file.versionId,
2099
2314
  versioningEnabled: file.versioningEnabled === true ||
2100
2315
  file.versioningEnabled === 'true',
2316
+ versioningStatus: typeof file.versioningStatus === 'string'
2317
+ ? String(file.versioningStatus)
2318
+ : undefined,
2101
2319
  distributionEnabled: file.distributionEnabled === true ||
2102
2320
  file.distributionEnabled === 'true' ||
2103
2321
  file.documentType?.enableDistributionCapability === true,
@@ -2587,20 +2805,7 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
2587
2805
  return node;
2588
2806
  }
2589
2807
  resolveStorageFileId(fileInfo) {
2590
- if (!fileInfo) {
2591
- return undefined;
2592
- }
2593
- if (typeof fileInfo === 'string') {
2594
- return fileInfo.startsWith('file:') ? fileInfo.slice(5) : fileInfo;
2595
- }
2596
- const item = fileInfo;
2597
- if (item.source?.kind === 'fileId' && typeof item.source.value === 'string') {
2598
- return item.source.value.replace(/^file:/, '');
2599
- }
2600
- if (typeof item.id === 'string' && item.id.trim() !== '') {
2601
- return item.id.replace(/^file:/, '');
2602
- }
2603
- return undefined;
2808
+ return resolveDocumentStorageFileId(fileInfo);
2604
2809
  }
2605
2810
  async resolveFileListItem(node) {
2606
2811
  const raw = node.fileId;
@@ -2785,7 +2990,7 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
2785
2990
  * Opens the drive picker popup with consistent layout (large dialog, optional embedded header).
2786
2991
  */
2787
2992
  async openDriveFolderPicker(options) {
2788
- const comp = (await import('./acorex-platform-module-document-management-client-drive-choose.component-Bq4semJF.mjs')).AXMDocumentDriveChooseComponent;
2993
+ const comp = (await import('./acorex-platform-module-document-management-client-drive-choose.component-up9sAsei.mjs')).AXMDocumentDriveChooseComponent;
2789
2994
  const popup = await this.popupService.open(comp, {
2790
2995
  title: await this.translate.translateAsync(options.titleKey),
2791
2996
  size: 'lg',
@@ -2856,13 +3061,13 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
2856
3061
  throw new Error(`File with ID ${options.node.id} not found`);
2857
3062
  }
2858
3063
  // Prepare file for copy by downloading from storage and converting to blob source
2859
- const fileListItem = await this.prepareFileForCopy(originalFile.fileInfo, options.node.name);
3064
+ const fileListItem = await this.prepareFileForCopy(originalFile.fileInfo, originalFile.name);
2860
3065
  if (!fileListItem) {
2861
3066
  throw new Error('Could not prepare file for copy');
2862
3067
  }
2863
3068
  await this.createFile({
2864
- title: options.node.name,
2865
- name: options.node.name,
3069
+ title: originalFile.title || originalFile.name,
3070
+ name: originalFile.name,
2866
3071
  parentId: selectedFolder.id,
2867
3072
  fileInfo: fileListItem,
2868
3073
  documentType: options.node.documentTypes[0],
@@ -3009,21 +3214,7 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3009
3214
  return await this.attachmentsService.uploadNewVersion(node.id);
3010
3215
  }
3011
3216
  async runNewVersionFlow(node) {
3012
- const created = await this.commandService.execute(AXPCommonCommandKeys.Versioning.CreateDraft, {
3013
- ...this.documentVersioningInput(node),
3014
- });
3015
- if (!created?.success) {
3016
- return;
3017
- }
3018
- const uploadNext = await this.confirmVersioningContinue('@document-management:dialogs.manage-version.continue-upload.title', '@document-management:dialogs.manage-version.continue-upload.message');
3019
- if (!uploadNext) {
3020
- return;
3021
- }
3022
- const uploaded = await this.uploadNewVersion(node);
3023
- if (!uploaded) {
3024
- return;
3025
- }
3026
- await this.continueToPublishVersion(node);
3217
+ await this.runUploadNewVersionFlow(node);
3027
3218
  }
3028
3219
  async runUploadNewVersionFlow(node) {
3029
3220
  const uploaded = await this.uploadNewVersion(node);
@@ -3036,15 +3227,12 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3036
3227
  return this.attachmentsService.findOpenVersionDraft(documentId);
3037
3228
  }
3038
3229
  /**
3039
- * Opens version history popup using common version-history command.
3230
+ * Opens companion version history for a versioned document.
3040
3231
  * For shortcut nodes, shows history of the target document.
3041
3232
  */
3042
3233
  async showVersionHistory(node) {
3043
- await this.commandService.execute('show-version-history-popup', {
3044
- options: {
3045
- refId: node.id,
3046
- refType: `${RootConfig.module.name}.${RootConfig.entities.document.name}`,
3047
- },
3234
+ await this.commandService.execute(AXPCommonCommandKeys.Versioning.ShowHistory, {
3235
+ ...this.documentVersioningInput(node),
3048
3236
  });
3049
3237
  }
3050
3238
  async continueToPublishVersion(node) {
@@ -3075,9 +3263,9 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3075
3263
  * Shows share dialog for a node
3076
3264
  */
3077
3265
  async showShareDialog(node) {
3078
- const comp = (await import('./acorex-platform-module-document-management-client-share-dialog.component-CyO_2Ppm.mjs')).AXMShareDialogComponent;
3266
+ const comp = (await import('./acorex-platform-module-document-management-client-share-dialog.component-CFI4hK3T.mjs')).AXMShareDialogComponent;
3079
3267
  const popup = await this.popupService.open(comp, {
3080
- title: 'Share',
3268
+ title: await this.translate.translateAsync('@document-management:dialogs.share-dialog.title'),
3081
3269
  data: {
3082
3270
  node,
3083
3271
  },
@@ -3090,9 +3278,9 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3090
3278
  * Shows share via email dialog for a node
3091
3279
  */
3092
3280
  async showShareWithEmailDialog(node) {
3093
- const comp = (await import('./acorex-platform-module-document-management-client-share-email-dialog.component-6B0KXT1Z.mjs')).AXMShareEmailDialogComponent;
3281
+ const comp = (await import('./acorex-platform-module-document-management-client-share-email-dialog.component-CUvlAcp6.mjs')).AXMShareEmailDialogComponent;
3094
3282
  const popup = await this.popupService.open(comp, {
3095
- title: 'Share via Email',
3283
+ title: await this.translate.translateAsync('@document-management:dialogs.share-email-dialog.title'),
3096
3284
  data: {
3097
3285
  node,
3098
3286
  },
@@ -3105,9 +3293,9 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3105
3293
  * Shows link dialog for a node
3106
3294
  */
3107
3295
  async showLinkDialog(node) {
3108
- const comp = (await import('./acorex-platform-module-document-management-client-link-dialog.component-CUFgI0_q.mjs')).AXMLinkDialogComponent;
3296
+ const comp = (await import('./acorex-platform-module-document-management-client-link-dialog.component-EYoimqRD.mjs')).AXMLinkDialogComponent;
3109
3297
  const popup = await this.popupService.open(comp, {
3110
- title: 'Share Link',
3298
+ title: await this.translate.translateAsync('@document-management:dialogs.share-link-dialog.title'),
3111
3299
  data: {
3112
3300
  node,
3113
3301
  },
@@ -3116,6 +3304,14 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3116
3304
  // Handle the link generation with popup.data.data
3117
3305
  }
3118
3306
  }
3307
+ async folderInheritSelectionOptions() {
3308
+ const t = this.translate;
3309
+ return [
3310
+ { value: 'None', text: (await t.translateAsync('@document-management:terms.inherit.options.none')) ?? '' },
3311
+ { value: 'Inherited', text: (await t.translateAsync('@document-management:terms.inherit.options.inherited')) ?? '' },
3312
+ { value: 'Extends', text: (await t.translateAsync('@document-management:terms.inherit.options.extends')) ?? '' },
3313
+ ];
3314
+ }
3119
3315
  /**
3120
3316
  * Shows lock dialog for a document
3121
3317
  */
@@ -3146,6 +3342,50 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3146
3342
  mapDocumentTypesForPicker(items) {
3147
3343
  return castArray(items ?? []).map((it) => this.toDocumentTypePickerRow(it));
3148
3344
  }
3345
+ async hydrateDocumentTypesForPicker(items) {
3346
+ return this.folderMetadataDialog.hydrateDocumentTypeCatalog(this.mapDocumentTypesForPicker(items));
3347
+ }
3348
+ documentTypeNamesOf(types) {
3349
+ if (!Array.isArray(types)) {
3350
+ return [];
3351
+ }
3352
+ return types
3353
+ .map((entry) => {
3354
+ const row = entry != null && typeof entry === 'object' ? entry : {};
3355
+ return typeof row['name'] === 'string' ? row['name'] : '';
3356
+ })
3357
+ .filter((name) => name !== '');
3358
+ }
3359
+ isTypeContainerFolder(folder) {
3360
+ return (folder?.childFolderDocumentTypes?.length ?? 0) > 0;
3361
+ }
3362
+ async folderAllowsCreateFolder(folder) {
3363
+ if (!folder) {
3364
+ return false;
3365
+ }
3366
+ if (folder.allowChildFolders === false) {
3367
+ return false;
3368
+ }
3369
+ if (this.isTypeContainerFolder(folder)) {
3370
+ return true;
3371
+ }
3372
+ if (!folder.parentId) {
3373
+ return true;
3374
+ }
3375
+ const parent = await this.loadFolderById(folder.parentId);
3376
+ return !this.isTypeContainerFolder(parent);
3377
+ }
3378
+ async loadFolderById(folderId) {
3379
+ if (!folderId) {
3380
+ return null;
3381
+ }
3382
+ try {
3383
+ return (await this.folderData.byKey(folderId)) ?? null;
3384
+ }
3385
+ catch {
3386
+ return null;
3387
+ }
3388
+ }
3149
3389
  /** Folder dialogs need a dense array; AXDataSource cache slots are undefined and break `pickerKey`. */
3150
3390
  async loadDocumentTypesForFolderDialog(allowedNames) {
3151
3391
  if (isArray(allowedNames) && allowedNames.length === 0) {
@@ -3164,7 +3404,25 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3164
3404
  }
3165
3405
  : {}),
3166
3406
  });
3167
- return this.mapDocumentTypesForPicker(res?.items ?? []);
3407
+ return this.hydrateDocumentTypesForPicker(res?.items ?? []);
3408
+ }
3409
+ buildFolderDialogForm(form, catalog, options) {
3410
+ const selected = Array.isArray(form['documentTypes']) ? form['documentTypes'] : [];
3411
+ if ((options?.requireDocumentTypes ?? true) && selected.length === 0) {
3412
+ return null;
3413
+ }
3414
+ const documentTypes = selected.map((value) => this.resolveSelectedDocumentType(value, catalog));
3415
+ const metaDataForm = form['metaDataForm'];
3416
+ return {
3417
+ title: String(form['title'] ?? form['name'] ?? ''),
3418
+ description: form['description'],
3419
+ inherit: form['inherit'],
3420
+ documentTypes,
3421
+ color: resolveFolderColor(form['color']),
3422
+ metaDataForm: pickMetaDataFormValues(metaDataForm != null && typeof metaDataForm === 'object' && !Array.isArray(metaDataForm)
3423
+ ? metaDataForm
3424
+ : {}, collectFolderScopedMetaDataList(documentTypes)),
3425
+ };
3168
3426
  }
3169
3427
  toDocumentTypePickerRow(item) {
3170
3428
  const row = (item != null && typeof item === 'object' ? item : { name: item, id: item });
@@ -3275,21 +3533,33 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3275
3533
  */
3276
3534
  async showFolderEditDialog(node) {
3277
3535
  const source = await this.resolveFolderNodeForEdit(node);
3278
- // Load document types for selection
3279
- const res = await this.documentTypeService.query({ skip: 0, take: 1000 });
3280
- const catalog = this.mapDocumentTypesForPicker(res?.items ?? []);
3281
- const { selected: initialDocumentTypes, dataSource: items } = this.resolveFolderDialogDocumentTypes(catalog, source.documentTypes);
3536
+ const isContainer = this.isTypeContainerFolder(source);
3537
+ const parent = isContainer ? null : await this.loadFolderById(source.parentId);
3538
+ const lockedStubs = parent?.childFolderDocumentTypes;
3539
+ const typesLocked = Array.isArray(lockedStubs) && lockedStubs.length > 0;
3540
+ const lockTypes = typesLocked || isContainer;
3541
+ const assignedTypes = typesLocked ? lockedStubs : source.documentTypes;
3542
+ const catalog = typesLocked
3543
+ ? await this.loadDocumentTypesForFolderDialog(this.documentTypeNamesOf(lockedStubs))
3544
+ : await this.hydrateDocumentTypesForPicker((await this.documentTypeService.query({ skip: 0, take: 1000 }))
3545
+ ?.items ?? []);
3546
+ const resolvedTypes = this.resolveFolderDialogDocumentTypes(catalog, isContainer ? [] : assignedTypes);
3547
+ const items = await this.folderMetadataDialog.hydrateDocumentTypeCatalog(resolvedTypes.dataSource);
3548
+ const initialDocumentTypes = resolvedTypes.selected.map((row) => items.find((item) => item.pickerKey === row.pickerKey) ?? row);
3549
+ const inheritOptions = await this.folderInheritSelectionOptions();
3282
3550
  const result = await this.layoutBuilder
3283
3551
  .create()
3284
3552
  .dialog((dialog) => {
3285
3553
  dialog
3286
3554
  .setTitle('@document-management:actions.update-folder')
3555
+ .setSize('lg')
3287
3556
  .setContext({
3288
3557
  name: source.name,
3289
3558
  description: source.description ?? '',
3290
- inherit: this.normalizeFolderInherit(source.inherit),
3291
- documentTypes: initialDocumentTypes,
3559
+ inherit: lockTypes ? 'None' : this.normalizeFolderInherit(source.inherit),
3560
+ documentTypes: isContainer ? [] : initialDocumentTypes,
3292
3561
  color: resolveFolderColor(source.color),
3562
+ metaDataForm: source.metaDataForm ?? {},
3293
3563
  })
3294
3564
  .content((flex) => {
3295
3565
  flex
@@ -3307,12 +3577,11 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3307
3577
  field.selectionList({
3308
3578
  valueField: 'value',
3309
3579
  textField: 'text',
3310
- dataSource: [
3311
- { value: 'None', text: 'None' },
3312
- { value: 'Inherited', text: 'Inherited' },
3313
- { value: 'Extends', text: 'Extends' },
3314
- ],
3580
+ dataSource: inheritOptions,
3315
3581
  });
3582
+ if (lockTypes) {
3583
+ field.visible(false);
3584
+ }
3316
3585
  })
3317
3586
  .formField('@document-management:entities.document-types.title-plural', (field) => {
3318
3587
  field.path('documentTypes');
@@ -3322,13 +3591,22 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3322
3591
  dataSource: items,
3323
3592
  multiple: true,
3324
3593
  allowSearch: true,
3325
- validations: [{ rule: 'required' }],
3594
+ validations: isContainer ? [] : [{ rule: 'required' }],
3326
3595
  });
3596
+ if (isContainer) {
3597
+ field.visible(false);
3598
+ }
3599
+ else if (typesLocked) {
3600
+ field.readonly(true);
3601
+ }
3327
3602
  })
3328
3603
  .formField('@general:terms.common.color', (field) => {
3329
3604
  field.path('color');
3330
3605
  field.colorBox({});
3331
3606
  });
3607
+ if (!isContainer) {
3608
+ this.folderMetadataDialog.addFolderMetadataForm(flex, items);
3609
+ }
3332
3610
  })
3333
3611
  .setActions((actions) => {
3334
3612
  actions.cancel('@general:actions.cancel.title').submit('@general:actions.save.title');
@@ -3337,26 +3615,27 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3337
3615
  const context = dialogRef.context();
3338
3616
  const action = dialogRef.action();
3339
3617
  if (!context || action === 'cancel') {
3340
- return false;
3341
- }
3342
- const form = context;
3343
- const selected = Array.isArray(form.documentTypes) ? form.documentTypes : [];
3344
- if (selected.length === 0) {
3345
- return false;
3618
+ return null;
3346
3619
  }
3347
- const selectedTypes = selected.map((v) => this.resolveSelectedDocumentType(v, items));
3348
- await this.updateFolder(node.id, {
3349
- title: form.title ?? form.name,
3350
- description: form.description,
3351
- inherit: form.inherit,
3352
- documentTypes: selectedTypes,
3353
- color: resolveFolderColor(form.color),
3620
+ return this.buildFolderDialogForm(context, items, {
3621
+ requireDocumentTypes: !isContainer,
3354
3622
  });
3355
- return true;
3356
3623
  });
3357
3624
  })
3358
3625
  .show();
3359
- return result;
3626
+ const form = resolveLayoutBuilderDialogResult(result);
3627
+ if (!form) {
3628
+ return false;
3629
+ }
3630
+ await this.updateFolder(node.id, {
3631
+ title: form.title,
3632
+ description: form.description,
3633
+ inherit: lockTypes ? 'None' : form.inherit,
3634
+ documentTypes: isContainer ? [] : form.documentTypes,
3635
+ color: form.color,
3636
+ metaDataForm: form.metaDataForm ?? {},
3637
+ });
3638
+ return true;
3360
3639
  }
3361
3640
  /**
3362
3641
  * Shows create folder dialog.
@@ -3364,20 +3643,37 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3364
3643
  * @param options.allowedDocumentTypeNames When set, only these document type names can be selected
3365
3644
  */
3366
3645
  async showCreateFolderDialog(parentId, options) {
3367
- const allowedNames = options?.allowedDocumentTypeNames;
3646
+ const parent = await this.loadFolderById(parentId);
3647
+ if (parent?.allowChildFolders === false) {
3648
+ return null;
3649
+ }
3650
+ const lockedStubs = parent?.childFolderDocumentTypes;
3651
+ const typesLocked = Array.isArray(lockedStubs) && lockedStubs.length > 0;
3652
+ if (!typesLocked && parent?.parentId) {
3653
+ const grandparent = await this.loadFolderById(parent.parentId);
3654
+ if (this.isTypeContainerFolder(grandparent)) {
3655
+ return null;
3656
+ }
3657
+ }
3658
+ const allowedNames = typesLocked
3659
+ ? this.documentTypeNamesOf(lockedStubs)
3660
+ : options?.allowedDocumentTypeNames;
3368
3661
  const catalog = await this.loadDocumentTypesForFolderDialog(allowedNames);
3369
- const { selected: defaultDocumentTypes } = this.resolveFolderDialogDocumentTypes(catalog, null);
3662
+ const { selected: defaultDocumentTypes } = this.resolveFolderDialogDocumentTypes(catalog, typesLocked ? lockedStubs : null);
3663
+ const inheritOptions = await this.folderInheritSelectionOptions();
3370
3664
  const result = await this.layoutBuilder
3371
3665
  .create()
3372
3666
  .dialog((dialog) => {
3373
3667
  dialog
3374
3668
  .setTitle('@document-management:actions.create-folder')
3669
+ .setSize('lg')
3375
3670
  .setContext({
3376
3671
  title: '',
3377
3672
  description: '',
3378
3673
  inherit: 'None',
3379
3674
  documentTypes: defaultDocumentTypes,
3380
3675
  color: AXM_DEFAULT_FOLDER_COLOR,
3676
+ metaDataForm: {},
3381
3677
  })
3382
3678
  .content((flex) => {
3383
3679
  flex
@@ -3395,12 +3691,11 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3395
3691
  field.selectionList({
3396
3692
  valueField: 'value',
3397
3693
  textField: 'text',
3398
- dataSource: [
3399
- { value: 'None', text: 'None' },
3400
- { value: 'Inherited', text: 'Inherited' },
3401
- { value: 'Extends', text: 'Extends' },
3402
- ],
3694
+ dataSource: inheritOptions,
3403
3695
  });
3696
+ if (typesLocked) {
3697
+ field.visible(false);
3698
+ }
3404
3699
  })
3405
3700
  .formField('@document-management:entities.document-types.title-plural', (field) => {
3406
3701
  field.path('documentTypes');
@@ -3412,11 +3707,15 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3412
3707
  allowSearch: true,
3413
3708
  validations: [{ rule: 'required' }],
3414
3709
  });
3710
+ if (typesLocked) {
3711
+ field.readonly(true);
3712
+ }
3415
3713
  })
3416
3714
  .formField('@general:terms.common.color', (field) => {
3417
3715
  field.path('color');
3418
3716
  field.colorBox({});
3419
3717
  });
3718
+ this.folderMetadataDialog.addFolderMetadataForm(flex, catalog);
3420
3719
  })
3421
3720
  .setActions((actions) => {
3422
3721
  actions.cancel('@general:actions.cancel.title').submit('@general:actions.save.title');
@@ -3427,32 +3726,30 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3427
3726
  if (!context || action === 'cancel') {
3428
3727
  return null;
3429
3728
  }
3430
- const form = context;
3431
- const selectedTypesRaw = Array.isArray(form.documentTypes) ? form.documentTypes : [];
3432
- if (selectedTypesRaw.length === 0) {
3433
- return null;
3434
- }
3435
- const selectedTypes = selectedTypesRaw.map((v) => this.resolveSelectedDocumentType(v, catalog));
3436
- try {
3437
- const folder = await this.createFolder({
3438
- title: form.title,
3439
- color: resolveFolderColor(form.color),
3440
- parentId,
3441
- description: form.description,
3442
- documentTypes: selectedTypes,
3443
- size: 0,
3444
- inherit: form.inherit,
3445
- });
3446
- return folder;
3447
- }
3448
- catch (err) {
3449
- console.error('[showCreateFolderDialog] createFolder failed', err);
3450
- throw err;
3451
- }
3729
+ return this.buildFolderDialogForm(context, catalog);
3452
3730
  });
3453
3731
  })
3454
3732
  .show();
3455
- return result;
3733
+ const form = resolveLayoutBuilderDialogResult(result);
3734
+ if (!form) {
3735
+ return null;
3736
+ }
3737
+ try {
3738
+ return await this.createFolder({
3739
+ title: form.title,
3740
+ color: form.color,
3741
+ parentId,
3742
+ description: form.description,
3743
+ documentTypes: form.documentTypes,
3744
+ size: 0,
3745
+ inherit: typesLocked ? 'None' : form.inherit,
3746
+ metaDataForm: form.metaDataForm ?? {},
3747
+ });
3748
+ }
3749
+ catch (err) {
3750
+ console.error('[showCreateFolderDialog] createFolder failed', err);
3751
+ throw err;
3752
+ }
3456
3753
  }
3457
3754
  /**
3458
3755
  * Shows rename popup for a node using dynamic form builder
@@ -3463,9 +3760,11 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3463
3760
  .dialog((dialog) => {
3464
3761
  dialog
3465
3762
  .setTitle('@document-management:actions.rename')
3466
- .setContext({ name: node.name })
3763
+ .setContext({ name: node.type === 'file' ? (node.title || node.name) : node.name })
3467
3764
  .content((flex) => {
3468
- flex.setDirection('column').formField('@document-management:dialogs.rename.name', (field) => {
3765
+ flex.setDirection('column').formField(node.type === 'file'
3766
+ ? '@general:terms.common.title'
3767
+ : '@document-management:dialogs.rename.name', (field) => {
3469
3768
  field.path('name');
3470
3769
  field.textBox({
3471
3770
  placeholder: '@document-management:dialogs.rename.name-placeholder',
@@ -3491,8 +3790,7 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3491
3790
  if (node.type === 'folder') {
3492
3791
  return await this.updateFolder(node.id, { title: formData.name });
3493
3792
  }
3494
- await this.updateFileName(node, formData.name);
3495
- return await this.updateFile(node.id, { name: formData.name });
3793
+ return await this.renameFileTitle(node, formData.name);
3496
3794
  }
3497
3795
  finally {
3498
3796
  dialogRef.setLoading(false);
@@ -3627,13 +3925,35 @@ class AXMDocumentManagerServiceImpl extends AXMDocumentManagerService {
3627
3925
  * Updates a file name
3628
3926
  */
3629
3927
  async updateFileName(node, name) {
3630
- if (node.storageType == 'physical') {
3631
- return this.mapFileToNode(await this.documentData.update(node.id, { name }));
3632
- }
3633
- else {
3634
- node.name = name;
3928
+ return this.renameFileTitle(node, name);
3929
+ }
3930
+ /**
3931
+ * Renames document title and keeps the stored file name in sync (same title + original extension).
3932
+ */
3933
+ async renameFileTitle(node, title) {
3934
+ const nextTitle = title.trim();
3935
+ const nextFileName = fileNameFromTitle(nextTitle, node.name);
3936
+ if (node.storageType !== 'physical') {
3937
+ node.title = nextTitle;
3938
+ node.name = nextFileName;
3635
3939
  return node;
3636
3940
  }
3941
+ const storageId = this.resolveStorageFileId(node.fileId);
3942
+ if (storageId) {
3943
+ await this.fileService.update({
3944
+ fileId: storageId,
3945
+ name: nextFileName,
3946
+ metadata: {},
3947
+ });
3948
+ }
3949
+ const nextFileInfo = node.fileId && typeof node.fileId === 'object'
3950
+ ? { ...node.fileId, name: nextFileName }
3951
+ : undefined;
3952
+ return this.mapFileToNode(await this.documentData.update(node.id, {
3953
+ title: nextTitle,
3954
+ name: nextFileName,
3955
+ ...(nextFileInfo ? { fileInfo: nextFileInfo } : {}),
3956
+ }));
3637
3957
  }
3638
3958
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentManagerServiceImpl, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
3639
3959
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentManagerServiceImpl }); }
@@ -3862,7 +4182,7 @@ const AXM_DRIVE_FILE_CHOOSER_PROVIDER = {
3862
4182
  const multiple = Boolean(context.options['multiple']);
3863
4183
  const browseMode = defaultTo(context.options['browseMode'], 'file');
3864
4184
  const accept = context.options['accept'];
3865
- const component = (await import('./acorex-platform-module-document-management-client-drive-choose.component-Bq4semJF.mjs')).AXMDocumentDriveChooseComponent;
4185
+ const component = (await import('./acorex-platform-module-document-management-client-drive-choose.component-up9sAsei.mjs')).AXMDocumentDriveChooseComponent;
3866
4186
  const popup = await popupService.open(component, {
3867
4187
  title: await translate.translateAsync('@document-management:actions.choose-from-drive'),
3868
4188
  size: 'lg',
@@ -4274,8 +4594,6 @@ const DocumentFileUploaderActionsByTypeProvider = {
4274
4594
  const { accept, fileType } = await buildFileChooserOptionsFromDocumentType(docType, fileService);
4275
4595
  const typeName = docType?.name;
4276
4596
  const title = docType?.title ?? typeName;
4277
- const metaGroups = docType?.metaDataList?.groups;
4278
- const hasMeta = Array.isArray(metaGroups) && metaGroups.some((g) => (g?.fields?.length ?? 0) > 0);
4279
4597
  return {
4280
4598
  plugin: 'document',
4281
4599
  global: false,
@@ -4305,27 +4623,34 @@ const DocumentFileUploaderActionsByTypeProvider = {
4305
4623
  status: item.status ?? 'attached',
4306
4624
  meta: { documentType, ...item.meta },
4307
4625
  }));
4308
- if (hasMeta) {
4309
- const result = await documentDialogService.openAttachmentDialogWithoutSave('Document Type Choose File', {
4310
- documentType: docType,
4311
- files: fileItems,
4626
+ const result = await documentDialogService.openAttachmentDialogWithoutSave(title, {
4627
+ documentType: docType,
4628
+ files: fileItems,
4629
+ });
4630
+ if (result.data?.cancel) {
4631
+ return;
4632
+ }
4633
+ if (result.data?.files) {
4634
+ result.data.files.forEach((f, i) => {
4635
+ if (!fileItems[i]) {
4636
+ return;
4637
+ }
4638
+ const meta = {
4639
+ ...fileItems[i].meta,
4640
+ documentType,
4641
+ metaDataForm: f?.metaDataForm,
4642
+ };
4643
+ set(fileItems[i], 'meta', meta);
4644
+ set(fileItems[i], 'metaDataForm', f?.metaDataForm);
4645
+ set(fileItems[i], 'title', f?.title);
4646
+ set(fileItems[i], 'description', f?.description);
4647
+ if (f?.name) {
4648
+ set(fileItems[i], 'name', f.name);
4649
+ }
4650
+ if (f?.expirationDate !== undefined) {
4651
+ set(fileItems[i], 'expirationDate', f.expirationDate);
4652
+ }
4312
4653
  });
4313
- if (result.data?.cancel != null && !result.data.cancel && result.data?.files) {
4314
- result.data.files.forEach((f, i) => {
4315
- if (fileItems[i]) {
4316
- const meta = {
4317
- ...fileItems[i].meta,
4318
- documentType,
4319
- metaDataForm: f?.metaDataForm,
4320
- };
4321
- set(fileItems[i], 'meta', meta);
4322
- set(fileItems[i], 'metaDataForm', f?.metaDataForm);
4323
- }
4324
- });
4325
- }
4326
- else if (result.data?.cancel) {
4327
- return;
4328
- }
4329
4654
  }
4330
4655
  capabilities.addFiles(fileItems);
4331
4656
  },
@@ -4362,7 +4687,7 @@ const DocumentFileUploaderEditDialogAfterFormProvider = {
4362
4687
  : undefined;
4363
4688
  if (!docType && (!metaObj || Object.keys(metaObj).length === 0))
4364
4689
  return payload;
4365
- const metaDataList = docType?.metaDataList ?? { groups: [] };
4690
+ const metaDataList = toEditableMetaDataList(collectDocumentScopedMetaDataList(docType?.metaDataList));
4366
4691
  const hasDefinitions = Array.isArray(metaDataList.groups) && metaDataList.groups.length > 0;
4367
4692
  const fields = [
4368
4693
  {
@@ -4514,6 +4839,153 @@ function resolveDocumentVersionNumber(source) {
4514
4839
  }
4515
4840
  //#endregion
4516
4841
 
4842
+ //#region ----- Imports -----
4843
+ //#endregion
4844
+ //#region ----- Detect -----
4845
+ function documentTypeKey(type) {
4846
+ if (type == null) {
4847
+ return '';
4848
+ }
4849
+ if (typeof type !== 'object') {
4850
+ return String(type);
4851
+ }
4852
+ const row = type;
4853
+ const name = row['name'];
4854
+ if (typeof name === 'string' && name.trim()) {
4855
+ return name.trim();
4856
+ }
4857
+ const id = row['id'] ?? row['documentTypeId'];
4858
+ return id == null ? '' : String(id);
4859
+ }
4860
+ function documentTypeSignature(node) {
4861
+ return (node.documentTypes ?? [])
4862
+ .map((type) => documentTypeKey(type))
4863
+ .filter(Boolean)
4864
+ .sort()
4865
+ .join('|');
4866
+ }
4867
+ function resolveHomogeneousExplorerGrid(folders, files) {
4868
+ const hasFolders = folders.length > 0;
4869
+ const hasFiles = files.length > 0;
4870
+ if (hasFolders === hasFiles) {
4871
+ return null;
4872
+ }
4873
+ const nodes = hasFolders ? folders : files;
4874
+ const signatures = nodes.map((node) => documentTypeSignature(node));
4875
+ if (signatures.some((signature) => !signature)) {
4876
+ return null;
4877
+ }
4878
+ if (new Set(signatures).size !== 1) {
4879
+ return null;
4880
+ }
4881
+ return {
4882
+ kind: hasFolders ? 'folder' : 'document',
4883
+ typeKeys: signatures[0].split('|'),
4884
+ };
4885
+ }
4886
+ function collectDocumentTypeIds(nodes) {
4887
+ const ids = new Set();
4888
+ for (const node of nodes) {
4889
+ for (const type of node.documentTypes ?? []) {
4890
+ const id = type?.id;
4891
+ if (id == null) {
4892
+ continue;
4893
+ }
4894
+ const key = String(id).trim();
4895
+ if (key) {
4896
+ ids.add(key);
4897
+ }
4898
+ }
4899
+ }
4900
+ return [...ids];
4901
+ }
4902
+ function collectDocumentTypeNames(nodes) {
4903
+ const names = new Set();
4904
+ for (const node of nodes) {
4905
+ for (const type of node.documentTypes ?? []) {
4906
+ const name = type?.name;
4907
+ if (typeof name === 'string' && name.trim()) {
4908
+ names.add(name.trim());
4909
+ }
4910
+ }
4911
+ }
4912
+ return [...names];
4913
+ }
4914
+ //#endregion
4915
+ //#region ----- Columns -----
4916
+ function parseInterfaceType(interfaceValue) {
4917
+ if (interfaceValue == null) {
4918
+ return '';
4919
+ }
4920
+ if (typeof interfaceValue === 'string') {
4921
+ try {
4922
+ const parsed = JSON.parse(interfaceValue);
4923
+ return String(parsed?.type ?? parsed?.name ?? '');
4924
+ }
4925
+ catch {
4926
+ return interfaceValue;
4927
+ }
4928
+ }
4929
+ if (typeof interfaceValue === 'object') {
4930
+ const row = interfaceValue;
4931
+ return String(row.type ?? row.name ?? '');
4932
+ }
4933
+ return '';
4934
+ }
4935
+ function formatFromInterface(interfaceValue) {
4936
+ const type = parseInterfaceType(interfaceValue).toLowerCase();
4937
+ if (type.includes('date-time') || type.includes('datetime')) {
4938
+ return 'datetime';
4939
+ }
4940
+ if (type.includes('date')) {
4941
+ return 'date';
4942
+ }
4943
+ if (type.includes('number') || type.includes('numeric') || type.includes('integer')) {
4944
+ return 'number';
4945
+ }
4946
+ return 'string';
4947
+ }
4948
+ function flattenMetaDataColumns(list, resolveTitle) {
4949
+ const columns = [];
4950
+ const seen = new Set();
4951
+ for (const group of list?.groups ?? []) {
4952
+ for (const field of group.fields ?? []) {
4953
+ const name = String(field?.name ?? '').trim();
4954
+ if (!name || seen.has(name)) {
4955
+ continue;
4956
+ }
4957
+ seen.add(name);
4958
+ columns.push({
4959
+ name,
4960
+ title: resolveTitle(field.title) || name,
4961
+ kind: 'metadata',
4962
+ format: formatFromInterface(field.interface),
4963
+ });
4964
+ }
4965
+ }
4966
+ return columns;
4967
+ }
4968
+ function readNodeMetaDataValue(node, fieldName) {
4969
+ return readMetaDataFormValue(node.metaDataForm, fieldName);
4970
+ }
4971
+ function readMetaDataFormValue(form, fieldName) {
4972
+ if (form == null || typeof form !== 'object' || Array.isArray(form)) {
4973
+ return undefined;
4974
+ }
4975
+ const row = form;
4976
+ if (Object.prototype.hasOwnProperty.call(row, fieldName)) {
4977
+ return row[fieldName];
4978
+ }
4979
+ for (const nested of Object.values(row)) {
4980
+ const found = readMetaDataFormValue(nested, fieldName);
4981
+ if (found !== undefined) {
4982
+ return found;
4983
+ }
4984
+ }
4985
+ return undefined;
4986
+ }
4987
+ //#endregion
4988
+
4517
4989
  function withMenuItemCheck(item, isSelected) {
4518
4990
  return isSelected ? { ...item, suffix: { text: '✓' } } : item;
4519
4991
  }
@@ -4528,9 +5000,26 @@ function nodeModifiedTime(node) {
4528
5000
  /**
4529
5001
  * User/tenant drive roots are system (cannot be deleted or moved) but users may create
4530
5002
  * children under those roots. Other system folders (Users, Entity, type folders) stay closed.
5003
+ * Typed children of Company Document type-containers cannot contain further folders.
4531
5004
  */
4532
- function canCreateFolderUnder(folder, scopeRootId) {
4533
- if (!folder?.isSystem) {
5005
+ function resolveExplorerParent(folder, path) {
5006
+ if (!folder) {
5007
+ return null;
5008
+ }
5009
+ const index = path.findIndex((node) => node.id === folder.id);
5010
+ return index > 0 ? path[index - 1] : null;
5011
+ }
5012
+ function canCreateFolderUnder(folder, scopeRootId, parentFolder) {
5013
+ if (!folder) {
5014
+ return false;
5015
+ }
5016
+ if (folder.allowChildFolders === false) {
5017
+ return false;
5018
+ }
5019
+ if ((parentFolder?.childFolderDocumentTypes?.length ?? 0) > 0) {
5020
+ return false;
5021
+ }
5022
+ if (!folder.isSystem) {
4534
5023
  return true;
4535
5024
  }
4536
5025
  return Boolean(scopeRootId && folder.id === scopeRootId);
@@ -4540,6 +5029,9 @@ const DOCUMENT_EXPLORER_LAYOUT_SETTINGS_SCOPE = AXPPlatformScope.User;
4540
5029
  const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withState(() => ({
4541
5030
  // View State
4542
5031
  viewMode: 'large-tiles',
5032
+ preferredViewMode: 'large-tiles',
5033
+ viewModeLocked: false,
5034
+ homogeneousGrid: null,
4543
5035
  isLoading: false,
4544
5036
  scope: AXPPlatformScope.User,
4545
5037
  // Navigation State
@@ -4620,6 +5112,7 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4620
5112
  isDetailsView: computed(() => store.viewMode() === 'details'),
4621
5113
  isLargeIconsView: computed(() => store.viewMode() === 'large-icons'),
4622
5114
  isSmallIconsView: computed(() => store.viewMode() === 'small-icons'),
5115
+ canUseHomogeneousGrid: computed(() => store.homogeneousGrid() != null),
4623
5116
  isBackAvailable: computed(() => store.backHistory().length > 0),
4624
5117
  isUpAvailable: computed(() => {
4625
5118
  const node = store.currentNode();
@@ -4628,6 +5121,7 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4628
5121
  selectedCount: computed(() => store.selectedNodes().length),
4629
5122
  hasSelectedItems: computed(() => store.selectedNodes().length > 0),
4630
5123
  hasMultipleSelectedItems: computed(() => store.selectedNodes().length > 1),
5124
+ showSelectionDeleteActions: computed(() => store.selectedNodes().length > 1 || (store.viewMode() === 'details' && store.selectedNodes().length > 0)),
4631
5125
  isMultiSelect: computed(() => store.selectionMode() === 'multiple'),
4632
5126
  selectedNode: computed(() => store.selectedNodes()[0] ?? null),
4633
5127
  isDetailPanelOpen: computed(() => store.detailPanel()),
@@ -4653,18 +5147,36 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4653
5147
  node.result.children = node.result.children?.sort((a, b) => directionMultiplier * a.name.localeCompare(b.name));
4654
5148
  break;
4655
5149
  }
5150
+ const folders = node.result.children?.filter((item) => item.type === 'folder') || [];
5151
+ const files = node.result.children?.filter((item) => store.browseMode() == 'file' && item.type === 'file') || [];
4656
5152
  patchState(store, {
4657
5153
  currentNode: node.result,
4658
5154
  currentPath: node.path,
4659
- folders: node.result.children?.filter((item) => item.type === 'folder') || [],
4660
- files: node.result.children?.filter((item) => store.browseMode() == 'file' && item.type === 'file') || [],
5155
+ folders,
5156
+ files,
4661
5157
  itemsCount: node.result.children?.length || 0,
4662
5158
  loadingFolderId: null,
4663
5159
  isLoading: false,
4664
5160
  navigatingFolderId: null,
4665
5161
  scopeRootId: node.scopeRootId ?? store.scopeRootId(),
5162
+ ...resolveHomogeneousGridViewState(folders, files),
4666
5163
  });
4667
5164
  };
5165
+ const resolveHomogeneousGridViewState = (folders, files) => {
5166
+ const homogeneousGrid = resolveHomogeneousExplorerGrid(folders, files);
5167
+ if (store.viewModeLocked()) {
5168
+ return { homogeneousGrid, viewMode: store.viewMode() };
5169
+ }
5170
+ if (homogeneousGrid) {
5171
+ return { homogeneousGrid, viewMode: 'details' };
5172
+ }
5173
+ const preferred = store.preferredViewMode();
5174
+ const fallback = preferred !== 'details' ? preferred : 'large-tiles';
5175
+ return {
5176
+ homogeneousGrid: null,
5177
+ viewMode: store.viewMode() === 'details' ? fallback : store.viewMode(),
5178
+ };
5179
+ };
4668
5180
  return {
4669
5181
  setAllowedDocumentTypeNames(names) {
4670
5182
  patchState(store, { allowedDocumentTypeNames: names });
@@ -4704,8 +5216,10 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4704
5216
  const sortDirection = await layoutSettings.get(AXPDocumentManagementSettings.SortDirection);
4705
5217
  const groupByType = await layoutSettings.get(AXPDocumentManagementSettings.GroupByType);
4706
5218
  const detailPanel = await layoutSettings.get(AXPDocumentManagementSettings.DetailPanelOpen);
5219
+ const savedViewMode = viewMode === 'details' || !viewMode ? 'large-tiles' : viewMode;
4707
5220
  patchState(store, {
4708
- viewMode: viewMode === 'details' ? 'large-tiles' : (viewMode ?? 'large-tiles'),
5221
+ viewMode: savedViewMode,
5222
+ preferredViewMode: savedViewMode,
4709
5223
  sortField: sortField ?? 'name',
4710
5224
  sortDirection: sortDirection ?? 'asc',
4711
5225
  groupByType: groupByType ?? true,
@@ -4775,23 +5289,35 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4775
5289
  documentTypes: [],
4776
5290
  storageType: 'virtual',
4777
5291
  };
5292
+ const folders = files.filter((item) => item.type === 'folder');
5293
+ const virtualFiles = files.filter((item) => item.type === 'file');
4778
5294
  patchState(store, {
4779
5295
  currentNode: node,
4780
5296
  currentPath: [node],
4781
- folders: files.filter((item) => item.type === 'folder'),
4782
- files: files.filter((item) => item.type === 'file'),
5297
+ folders,
5298
+ files: virtualFiles,
4783
5299
  itemsCount: files.length,
4784
5300
  availableSpace: await driveService.getAvailableSpace(),
4785
5301
  loadingFolderId: null,
4786
5302
  isLoading: false,
4787
5303
  navigatingFolderId: null,
5304
+ ...resolveHomogeneousGridViewState(folders, virtualFiles),
4788
5305
  });
4789
5306
  },
5307
+ setViewModeLocked(locked) {
5308
+ patchState(store, { viewModeLocked: locked });
5309
+ },
4790
5310
  setViewMode(mode) {
4791
- patchState(store, { viewMode: mode });
4792
- void settingsService
4793
- .scope(DOCUMENT_EXPLORER_LAYOUT_SETTINGS_SCOPE)
4794
- .set(AXPDocumentManagementSettings.ViewMode, mode);
5311
+ const nextMode = mode;
5312
+ patchState(store, {
5313
+ viewMode: nextMode,
5314
+ ...(nextMode !== 'details' ? { preferredViewMode: nextMode } : {}),
5315
+ });
5316
+ if (nextMode !== 'details') {
5317
+ void settingsService
5318
+ .scope(DOCUMENT_EXPLORER_LAYOUT_SETTINGS_SCOPE)
5319
+ .set(AXPDocumentManagementSettings.ViewMode, nextMode);
5320
+ }
4795
5321
  },
4796
5322
  isViewMode(mode) {
4797
5323
  return store.viewMode() === mode;
@@ -4866,15 +5392,30 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4866
5392
  return resolveFolderColor(node.color);
4867
5393
  },
4868
5394
  getNodeInfo(node) {
5395
+ const detailI18n = {
5396
+ sections: { details: '@document-management:explorer.detail-panel.sections.details' },
5397
+ metadata: '@document-management:terms.common.meta-data',
5398
+ description: '@document-management:explorer.detail-panel.fields.description',
5399
+ size: '@document-management:terms.common.size',
5400
+ expireDate: '@document-management:terms.document.expire-date',
5401
+ createdAt: '@document-management:terms.timestamps.created-at',
5402
+ modifiedAt: '@document-management:terms.timestamps.modified-at',
5403
+ version: '@document-management:terms.common.version',
5404
+ items: '@document-management:explorer.grid.columns.items',
5405
+ shortcut: '@document-management:explorer.detail-panel.fields.shortcut',
5406
+ linksToDocument: '@document-management:explorer.detail-panel.fields.links-to-document',
5407
+ linksToFolder: '@document-management:explorer.detail-panel.fields.links-to-folder',
5408
+ folderType: '@document-management:explorer.detail-panel.folder-type',
5409
+ };
4869
5410
  // If no node, return a default object
4870
5411
  if (!node) {
4871
5412
  return {
4872
5413
  name: '---',
4873
5414
  icon: 'fa-light fa-folder',
4874
- type: 'Folder',
5415
+ type: detailI18n.folderType,
4875
5416
  sections: [
4876
5417
  {
4877
- title: 'Details',
5418
+ title: detailI18n.sections.details,
4878
5419
  details: [],
4879
5420
  },
4880
5421
  ],
@@ -4887,12 +5428,12 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4887
5428
  const versionNumber = resolveDocumentVersionNumber(node);
4888
5429
  const details = [
4889
5430
  {
4890
- title: 'Description',
5431
+ title: detailI18n.description,
4891
5432
  content: node.description,
4892
5433
  icon: 'fa-solid fa-file-lines',
4893
5434
  },
4894
5435
  {
4895
- title: 'Size',
5436
+ title: detailI18n.size,
4896
5437
  content: node.size || 0,
4897
5438
  format: 'filesize',
4898
5439
  icon: 'fa-solid fa-file-lines',
@@ -4900,7 +5441,7 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4900
5441
  ...(node.expirationDate
4901
5442
  ? [
4902
5443
  {
4903
- title: 'Expire Date',
5444
+ title: detailI18n.expireDate,
4904
5445
  content: node.expirationDate,
4905
5446
  format: 'date',
4906
5447
  icon: 'fa-solid fa-calendar-days',
@@ -4908,13 +5449,13 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4908
5449
  ]
4909
5450
  : []),
4910
5451
  {
4911
- title: 'Created at',
5452
+ title: detailI18n.createdAt,
4912
5453
  content: node.createdAt || new Date(),
4913
5454
  format: 'datetime',
4914
5455
  icon: 'fa-solid fa-calendar-days',
4915
5456
  },
4916
5457
  {
4917
- title: 'Modified at',
5458
+ title: detailI18n.modifiedAt,
4918
5459
  content: node.modifiedAt || new Date(),
4919
5460
  format: 'datetime',
4920
5461
  icon: 'fa-solid fa-calendar-days',
@@ -4922,7 +5463,7 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4922
5463
  ...(versionNumber != null
4923
5464
  ? [
4924
5465
  {
4925
- title: 'Version',
5466
+ title: detailI18n.version,
4926
5467
  content: versionNumber,
4927
5468
  format: 'number',
4928
5469
  icon: 'fa-solid fa-code-branch',
@@ -4932,8 +5473,8 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4932
5473
  ];
4933
5474
  if (node.storageType === 'shortcut' || node.isShortcut) {
4934
5475
  details.unshift({
4935
- title: 'Shortcut',
4936
- content: node.targetDocumentId ? 'Links to a document' : 'Links to a folder',
5476
+ title: detailI18n.shortcut,
5477
+ content: node.targetDocumentId ? detailI18n.linksToDocument : detailI18n.linksToFolder,
4937
5478
  icon: 'fa-light fa-up-right-from-square',
4938
5479
  });
4939
5480
  }
@@ -4944,17 +5485,17 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4944
5485
  sections: node.metaDataForm && typeof node.metaDataForm === 'object'
4945
5486
  ? [
4946
5487
  {
4947
- title: 'Details',
5488
+ title: detailI18n.sections.details,
4948
5489
  details,
4949
5490
  },
4950
5491
  {
4951
- title: 'Metadata',
5492
+ title: detailI18n.metadata,
4952
5493
  details: [],
4953
5494
  },
4954
5495
  ]
4955
5496
  : [
4956
5497
  {
4957
- title: 'Details',
5498
+ title: detailI18n.sections.details,
4958
5499
  details,
4959
5500
  },
4960
5501
  ],
@@ -4964,29 +5505,29 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4964
5505
  else {
4965
5506
  const folderDetails = [
4966
5507
  {
4967
- title: 'Description',
5508
+ title: detailI18n.description,
4968
5509
  content: node.description,
4969
5510
  icon: 'fa-solid fa-file-lines',
4970
5511
  },
4971
5512
  {
4972
- title: 'Items',
5513
+ title: detailI18n.items,
4973
5514
  content: node.children?.length ?? 0,
4974
5515
  icon: 'fa-solid fa-file-lines',
4975
5516
  },
4976
5517
  {
4977
- title: 'Size',
5518
+ title: detailI18n.size,
4978
5519
  content: node.size || 0,
4979
5520
  format: 'filesize',
4980
5521
  icon: 'fa-solid fa-file-lines',
4981
5522
  },
4982
5523
  {
4983
- title: 'Created at',
5524
+ title: detailI18n.createdAt,
4984
5525
  content: node.createdAt || new Date(),
4985
5526
  format: 'datetime',
4986
5527
  icon: 'fa-solid fa-calendar-days',
4987
5528
  },
4988
5529
  {
4989
- title: 'Modified at',
5530
+ title: detailI18n.modifiedAt,
4990
5531
  content: node.modifiedAt || new Date(),
4991
5532
  format: 'datetime',
4992
5533
  icon: 'fa-solid fa-calendar-days',
@@ -4994,21 +5535,32 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
4994
5535
  ];
4995
5536
  if (node.storageType === 'shortcut' || node.isShortcut) {
4996
5537
  folderDetails.unshift({
4997
- title: 'Shortcut',
4998
- content: 'Links to a folder',
5538
+ title: detailI18n.shortcut,
5539
+ content: detailI18n.linksToFolder,
4999
5540
  icon: 'fa-light fa-up-right-from-square',
5000
5541
  });
5001
5542
  }
5002
5543
  return {
5003
5544
  name: node.name,
5004
5545
  icon: 'fa-light fa-folder',
5005
- type: 'Folder',
5006
- sections: [
5007
- {
5008
- title: 'Details',
5009
- details: folderDetails,
5010
- },
5011
- ],
5546
+ type: detailI18n.folderType,
5547
+ sections: node.metaDataForm && typeof node.metaDataForm === 'object'
5548
+ ? [
5549
+ {
5550
+ title: detailI18n.sections.details,
5551
+ details: folderDetails,
5552
+ },
5553
+ {
5554
+ title: detailI18n.metadata,
5555
+ details: [],
5556
+ },
5557
+ ]
5558
+ : [
5559
+ {
5560
+ title: detailI18n.sections.details,
5561
+ details: folderDetails,
5562
+ },
5563
+ ],
5012
5564
  };
5013
5565
  }
5014
5566
  },
@@ -5144,6 +5696,9 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5144
5696
  selectedNodes: [...store.filteredFolders(), ...store.filteredFiles()],
5145
5697
  });
5146
5698
  },
5699
+ setSelectedNodes(nodes) {
5700
+ patchState(store, { selectedNodes: [...nodes] });
5701
+ },
5147
5702
  deselectAll() {
5148
5703
  patchState(store, { selectedNodes: [] });
5149
5704
  },
@@ -5184,14 +5739,20 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5184
5739
  // Upload types come only from the current folder's assigned documentTypes.
5185
5740
  // Do not fall back to plugin allowedDocumentTypeNames — the entity root has no types;
5186
5741
  // type-specific subfolders carry their own.
5187
- const folderTypes = store.currentFolder()?.documentTypes ?? [];
5742
+ const current = store.currentFolder();
5743
+ const folderTypes = current?.documentTypes ?? [];
5744
+ const isTypeContainer = (current?.childFolderDocumentTypes?.length ?? 0) > 0;
5188
5745
  const allowedNames = store.allowedDocumentTypeNames();
5189
- const typesToShow = allowedNames != null
5190
- ? allowedNames.length > 0
5191
- ? folderTypes.filter((t) => t?.name && allowedNames.includes(t.name))
5192
- : []
5193
- : folderTypes;
5194
- const allowCreateFolder = canAddFolder && canCreateFolderUnder(store.currentFolder(), store.scopeRootId());
5746
+ const typesToShow = isTypeContainer
5747
+ ? []
5748
+ : allowedNames != null
5749
+ ? allowedNames.length > 0
5750
+ ? folderTypes.filter((t) => t?.name && allowedNames.includes(t.name))
5751
+ : []
5752
+ : folderTypes;
5753
+ const allowCreateFolder = canAddFolder &&
5754
+ canCreateFolderUnder(current, store.scopeRootId(), resolveExplorerParent(current, store.currentPath())) &&
5755
+ (await driveService.folderAllowsCreateFolder(current));
5195
5756
  return [
5196
5757
  ...(allowCreateFolder
5197
5758
  ? [
@@ -5290,6 +5851,16 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5290
5851
  text: await trans('view-modes.list'),
5291
5852
  icon: 'fa-light fa-list',
5292
5853
  }, store.viewMode() === 'list'),
5854
+ ...(store.homogeneousGrid()
5855
+ ? [
5856
+ withMenuItemCheck({
5857
+ name: 'view.details',
5858
+ text: await trans('view-modes.details'),
5859
+ icon: 'fa-light fa-table',
5860
+ break: true,
5861
+ }, store.viewMode() === 'details'),
5862
+ ]
5863
+ : []),
5293
5864
  ];
5294
5865
  const groupByItems = [
5295
5866
  withMenuItemCheck({
@@ -5407,6 +5978,10 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5407
5978
  if (!node.versioningEnabled || node.type !== 'file' || node.storageType === 'shortcut') {
5408
5979
  return null;
5409
5980
  }
5981
+ const canMaintainVersioning = isMaintainVersioningPermissionGranted((key) => sessionService.authorize(key), `${RootConfig.module.name}.${RootConfig.entities.document.name}`);
5982
+ if (!canMaintainVersioning) {
5983
+ return null;
5984
+ }
5410
5985
  const draft = await driveService.findOpenVersionDraft(node.id);
5411
5986
  const versionItems = [];
5412
5987
  if (!draft) {
@@ -5435,6 +6010,16 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5435
6010
  data: node,
5436
6011
  });
5437
6012
  }
6013
+ const lastItem = versionItems[versionItems.length - 1];
6014
+ if (lastItem) {
6015
+ lastItem.break = true;
6016
+ }
6017
+ versionItems.push({
6018
+ name: 'show-version-history',
6019
+ text: await trans('menus.context.show-version-history'),
6020
+ icon: 'fa-light fa-clock-rotate-left',
6021
+ data: node,
6022
+ });
5438
6023
  return {
5439
6024
  name: 'manage-versions',
5440
6025
  text: await trans('menus.context.manage-versions'),
@@ -5633,7 +6218,7 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5633
6218
  },
5634
6219
  ];
5635
6220
  // Add upload menu only if not locked
5636
- if (!isNodeLocked && node?.documentTypes?.length) {
6221
+ if (!isNodeLocked && node?.documentTypes?.length && !node.childFolderDocumentTypes?.length) {
5637
6222
  items.push({
5638
6223
  text: await trans('menus.context.upload'),
5639
6224
  icon: 'fa-light fa-file-arrow-up',
@@ -5837,6 +6422,7 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5837
6422
  case 'view.large-tiles':
5838
6423
  case 'view.small-tiles':
5839
6424
  case 'view.list':
6425
+ case 'view.details':
5840
6426
  this.setViewMode(name.replace('view.', ''));
5841
6427
  break;
5842
6428
  case 'upload-new-version':
@@ -5933,7 +6519,8 @@ const AXPDocumentExplorerViewModel = signalStore({ providedIn: 'root' }, withSta
5933
6519
  */
5934
6520
  async createFolder(node) {
5935
6521
  const parent = node ?? store.currentFolder() ?? store.currentNode();
5936
- if (!canCreateFolderUnder(parent, store.scopeRootId())) {
6522
+ if (!canCreateFolderUnder(parent, store.scopeRootId(), resolveExplorerParent(parent, store.currentPath())) ||
6523
+ !(await driveService.folderAllowsCreateFolder(parent))) {
5937
6524
  return;
5938
6525
  }
5939
6526
  const parentId = parent?.id ?? store.currentNode()?.id;
@@ -6119,32 +6706,31 @@ class AXMDocumentExplorerComponent {
6119
6706
  /** Drops stale async open results when the user right-clicks again before items resolve. */
6120
6707
  this.contextMenuOpenToken = 0;
6121
6708
  this.viewMap = {
6122
- list: async () => (await import('./acorex-platform-module-document-management-client-list-view.component-CDldLoV-.mjs')).AXMDocumentExplorerListViewComponent,
6123
- 'small-tiles': async () => (await import('./acorex-platform-module-document-management-client-small-tiles-view.component-NUNfAl3M.mjs')).AXMDocumentExplorerSmallTilesViewComponent,
6124
- 'large-tiles': async () => (await import('./acorex-platform-module-document-management-client-large-tiles-view.component-Dm-MSIUn.mjs')).AXMDocumentExplorerLargeTilesViewComponent,
6125
- // details: async () =>
6126
- // (await import('./views/details/details-view.component')).AXMDocumentExplorerDetailsViewComponent,
6127
- 'large-icons': async () => (await import('./acorex-platform-module-document-management-client-large-icons-view.component-COT_8z2S.mjs')).AXMDocumentExplorerLargeIconsViewComponent,
6128
- 'small-icons': async () => (await import('./acorex-platform-module-document-management-client-small-icons-view.component-IC5bdYey.mjs')).AXMDocumentExplorerSmallIconsViewComponent,
6129
- 'attachment': async () => (await import('./acorex-platform-module-document-management-client-attachment-widget.component-DmgzUrWY.mjs')).AXMDocumentExplorerAttachmentComponent,
6709
+ list: async () => (await import('./acorex-platform-module-document-management-client-list-view.component-DVUfHWHB.mjs')).AXMDocumentExplorerListViewComponent,
6710
+ 'small-tiles': async () => (await import('./acorex-platform-module-document-management-client-small-tiles-view.component-DtsBSVCq.mjs')).AXMDocumentExplorerSmallTilesViewComponent,
6711
+ 'large-tiles': async () => (await import('./acorex-platform-module-document-management-client-large-tiles-view.component-DzWIUZtv.mjs')).AXMDocumentExplorerLargeTilesViewComponent,
6712
+ details: async () => (await import('./acorex-platform-module-document-management-client-details-view.component-DkCD8RSd.mjs')).AXMDocumentExplorerDetailsViewComponent,
6713
+ 'large-icons': async () => (await import('./acorex-platform-module-document-management-client-large-icons-view.component-Cece4n22.mjs')).AXMDocumentExplorerLargeIconsViewComponent,
6714
+ 'small-icons': async () => (await import('./acorex-platform-module-document-management-client-small-icons-view.component-CL5cNRtI.mjs')).AXMDocumentExplorerSmallIconsViewComponent,
6715
+ 'attachment': async () => (await import('./acorex-platform-module-document-management-client-attachment-widget.component-CsrcMMC9.mjs')).AXMDocumentExplorerAttachmentComponent,
6130
6716
  };
6131
6717
  this.skeletonViewMap = {
6132
- list: async () => (await import('./acorex-platform-module-document-management-client-list-view-skeleton.component-D-QA5J07.mjs')).AXMDocumentExplorerListViewSkeletonComponent,
6133
- 'small-tiles': async () => (await import('./acorex-platform-module-document-management-client-small-tiles-view-skeleton.component-DzDonT_e.mjs'))
6718
+ list: async () => (await import('./acorex-platform-module-document-management-client-list-view-skeleton.component-Dgx8lVyN.mjs')).AXMDocumentExplorerListViewSkeletonComponent,
6719
+ 'small-tiles': async () => (await import('./acorex-platform-module-document-management-client-small-tiles-view-skeleton.component-DBJldDaS.mjs'))
6134
6720
  .AXMDocumentExplorerSmallTilesViewSkeletonComponent,
6135
6721
  'large-tiles': async () => (await Promise.resolve().then(function () { return largeTilesViewSkeleton_component; }))
6136
6722
  .AXMDocumentExplorerLargeTilesViewSkeletonComponent,
6137
- // details: async () =>
6138
- // (await import('./views/details/details-view-skeleton.component')).AXMDocumentExplorerDetailsViewSkeletonComponent,
6139
- 'large-icons': async () => (await import('./acorex-platform-module-document-management-client-large-icons-view-skeleton.component-CXDBviff.mjs'))
6723
+ details: async () => (await import('./acorex-platform-module-document-management-client-details-view-skeleton.component-BnRZrzCX.mjs')).AXMDocumentExplorerDetailsViewSkeletonComponent,
6724
+ 'large-icons': async () => (await import('./acorex-platform-module-document-management-client-large-icons-view-skeleton.component-C_VbFRKl.mjs'))
6140
6725
  .AXMDocumentExplorerLargeIconsViewSkeletonComponent,
6141
- 'small-icons': async () => (await import('./acorex-platform-module-document-management-client-small-icons-view-skeleton.component-Cmgqsr4e.mjs'))
6726
+ 'small-icons': async () => (await import('./acorex-platform-module-document-management-client-small-icons-view-skeleton.component-CU2MiVUi.mjs'))
6142
6727
  .AXMDocumentExplorerSmallIconsViewSkeletonComponent,
6143
- attachment: async () => (await import('./acorex-platform-module-document-management-client-attachment-view-skeleton.component-CP6yjHx7.mjs'))
6728
+ attachment: async () => (await import('./acorex-platform-module-document-management-client-attachment-view-skeleton.component-BeQSbax5.mjs'))
6144
6729
  .AXMDocumentExplorerAttachmentViewSkeletonComponent,
6145
6730
  };
6146
6731
  this.#effect2 = effect(() => {
6147
6732
  if (this.viewMode()) {
6733
+ this.vm.setViewModeLocked(true);
6148
6734
  this.vm.setViewMode(this.viewMode());
6149
6735
  }
6150
6736
  if (this.selectionMode()) {
@@ -6167,7 +6753,7 @@ class AXMDocumentExplorerComponent {
6167
6753
  //#region Menu and Context Menu
6168
6754
  handleExplorerClick(event) {
6169
6755
  const target = event.target;
6170
- if (target?.closest('.__explorer-item')) {
6756
+ if (target?.closest('.__explorer-item, .details-view')) {
6171
6757
  return;
6172
6758
  }
6173
6759
  if (this.vm.hasSelectedItems()) {
@@ -6236,12 +6822,12 @@ class AXMDocumentExplorerComponent {
6236
6822
  }
6237
6823
  }
6238
6824
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentExplorerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6239
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMDocumentExplorerComponent, isStandalone: true, selector: "axm-document-explorer", inputs: { browseMode: { classPropertyName: "browseMode", publicName: "browseMode", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, showContextMenu: { classPropertyName: "showContextMenu", publicName: "showContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "handleExplorerClick($event)", "contextmenu": "handleExplorerContextMenu($event)" }, classAttribute: "flex flex-1 min-h-full w-full flex-col" }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["itemsContextMenu"], descendants: true, isSignal: true }, { propertyName: "rootContextMenu", first: true, predicate: ["rootContextMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"view-container\">\n @if (showSkeleton()) {\n @if (skeletonView(); as skeleton) {\n <ng-container [ngComponentOutlet]=\"skeleton\"></ng-container>\n } @else {\n <axm-document-explorer-large-tiles-view-skeleton></axm-document-explorer-large-tiles-view-skeleton>\n }\n } @else if (showEmptyState()) {\n <axp-state-message\n icon=\"fa-light fa-folder-open\"\n [title]=\"'@document-management:empty-states.no-items.title'\"\n [description]=\"'@document-management:empty-states.no-items.description'\"\n >\n </axp-state-message>\n } @else {\n <ng-container [ngComponentOutlet]=\"view()\"></ng-container>\n }\n</div>\n\n<!-- Context Menu: opened via host contextmenu after items are resolved (not via [target]/onOpening). -->\n@if (showContextMenu()) {\n <ax-context-menu\n #itemsContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n <ax-context-menu\n #rootContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n}\n", styles: ["axm-document-explorer>.view-container{display:flex;min-height:100%;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 4);-webkit-user-select:none;user-select:none}axm-document-explorer .animation-duration-2s{--fa-animation-duration: 2s}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXMenuModule }, { kind: "component", type: i2$1.AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXMFileTypeModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXMDocumentExplorerLargeTilesViewSkeletonComponent, selector: "axm-document-explorer-large-tiles-view-skeleton" }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None }); }
6825
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMDocumentExplorerComponent, isStandalone: true, selector: "axm-document-explorer", inputs: { browseMode: { classPropertyName: "browseMode", publicName: "browseMode", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: true, isRequired: false, transformFunction: null }, selectionMode: { classPropertyName: "selectionMode", publicName: "selectionMode", isSignal: true, isRequired: false, transformFunction: null }, showContextMenu: { classPropertyName: "showContextMenu", publicName: "showContextMenu", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "click": "handleExplorerClick($event)", "contextmenu": "handleExplorerContextMenu($event)" }, classAttribute: "flex min-h-0 min-w-0 flex-1 flex-col" }, viewQueries: [{ propertyName: "contextMenu", first: true, predicate: ["itemsContextMenu"], descendants: true, isSignal: true }, { propertyName: "rootContextMenu", first: true, predicate: ["rootContextMenu"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"view-container\">\n @if (showSkeleton()) {\n @if (skeletonView(); as skeleton) {\n <ng-container [ngComponentOutlet]=\"skeleton\"></ng-container>\n } @else {\n <axm-document-explorer-large-tiles-view-skeleton></axm-document-explorer-large-tiles-view-skeleton>\n }\n } @else if (showEmptyState()) {\n <axp-state-message\n icon=\"fa-light fa-folder-open\"\n [title]=\"'@document-management:empty-states.no-items.title'\"\n [description]=\"'@document-management:empty-states.no-items.description'\"\n >\n </axp-state-message>\n } @else {\n <ng-container [ngComponentOutlet]=\"view()\"></ng-container>\n }\n</div>\n\n<!-- Context Menu: opened via host contextmenu after items are resolved (not via [target]/onOpening). -->\n@if (showContextMenu()) {\n <ax-context-menu\n #itemsContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n <ax-context-menu\n #rootContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n}\n", styles: ["axm-document-explorer>.view-container{display:flex;min-height:0px;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 4);-webkit-user-select:none;user-select:none}axm-document-explorer .animation-duration-2s{--fa-animation-duration: 2s}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$2.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "ngmodule", type: AXMenuModule }, { kind: "component", type: i2$1.AXContextMenuComponent, selector: "ax-context-menu", inputs: ["orientation", "openOn", "closeOn", "closeOnRouteChange", "items", "target"], outputs: ["onItemClick", "onOpening", "onClose"] }, { kind: "ngmodule", type: AXMFileTypeModule }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "component", type: AXMDocumentExplorerLargeTilesViewSkeletonComponent, selector: "axm-document-explorer-large-tiles-view-skeleton" }], changeDetection: i0.ChangeDetectionStrategy.Eager, encapsulation: i0.ViewEncapsulation.None }); }
6240
6826
  }
6241
6827
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentExplorerComponent, decorators: [{
6242
6828
  type: Component,
6243
6829
  args: [{ selector: 'axm-document-explorer', standalone: true, encapsulation: ViewEncapsulation.None, host: {
6244
- class: 'flex flex-1 min-h-full w-full flex-col',
6830
+ class: 'flex min-h-0 min-w-0 flex-1 flex-col',
6245
6831
  '(click)': 'handleExplorerClick($event)',
6246
6832
  '(contextmenu)': 'handleExplorerContextMenu($event)',
6247
6833
  }, changeDetection: ChangeDetectionStrategy.Eager, imports: [
@@ -6255,7 +6841,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
6255
6841
  AXMFileTypeModule,
6256
6842
  AXPStateMessageComponent,
6257
6843
  AXMDocumentExplorerLargeTilesViewSkeletonComponent,
6258
- ], template: "<div class=\"view-container\">\n @if (showSkeleton()) {\n @if (skeletonView(); as skeleton) {\n <ng-container [ngComponentOutlet]=\"skeleton\"></ng-container>\n } @else {\n <axm-document-explorer-large-tiles-view-skeleton></axm-document-explorer-large-tiles-view-skeleton>\n }\n } @else if (showEmptyState()) {\n <axp-state-message\n icon=\"fa-light fa-folder-open\"\n [title]=\"'@document-management:empty-states.no-items.title'\"\n [description]=\"'@document-management:empty-states.no-items.description'\"\n >\n </axp-state-message>\n } @else {\n <ng-container [ngComponentOutlet]=\"view()\"></ng-container>\n }\n</div>\n\n<!-- Context Menu: opened via host contextmenu after items are resolved (not via [target]/onOpening). -->\n@if (showContextMenu()) {\n <ax-context-menu\n #itemsContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n <ax-context-menu\n #rootContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n}\n", styles: ["axm-document-explorer>.view-container{display:flex;min-height:100%;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 4);-webkit-user-select:none;user-select:none}axm-document-explorer .animation-duration-2s{--fa-animation-duration: 2s}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
6844
+ ], template: "<div class=\"view-container\">\n @if (showSkeleton()) {\n @if (skeletonView(); as skeleton) {\n <ng-container [ngComponentOutlet]=\"skeleton\"></ng-container>\n } @else {\n <axm-document-explorer-large-tiles-view-skeleton></axm-document-explorer-large-tiles-view-skeleton>\n }\n } @else if (showEmptyState()) {\n <axp-state-message\n icon=\"fa-light fa-folder-open\"\n [title]=\"'@document-management:empty-states.no-items.title'\"\n [description]=\"'@document-management:empty-states.no-items.description'\"\n >\n </axp-state-message>\n } @else {\n <ng-container [ngComponentOutlet]=\"view()\"></ng-container>\n }\n</div>\n\n<!-- Context Menu: opened via host contextmenu after items are resolved (not via [target]/onOpening). -->\n@if (showContextMenu()) {\n <ax-context-menu\n #itemsContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n <ax-context-menu\n #rootContextMenu\n [orientation]=\"'vertical'\"\n [closeOn]=\"'leave'\"\n (onItemClick)=\"handleContextMenuItemClick($event)\"\n >\n </ax-context-menu>\n}\n", styles: ["axm-document-explorer>.view-container{display:flex;min-height:0px;min-width:0px;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * 4);-webkit-user-select:none;user-select:none}axm-document-explorer .animation-duration-2s{--fa-animation-duration: 2s}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
6259
6845
  }], propDecorators: { contextMenu: [{ type: i0.ViewChild, args: ['itemsContextMenu', { isSignal: true }] }], rootContextMenu: [{ type: i0.ViewChild, args: ['rootContextMenu', { isSignal: true }] }], browseMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "browseMode", required: false }] }], viewMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "viewMode", required: false }] }], selectionMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectionMode", required: false }] }], showContextMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "showContextMenu", required: false }] }] } });
6260
6846
 
6261
6847
  //#endregion
@@ -6264,6 +6850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
6264
6850
  * Document explorer side panel; maps view-model state into {@link AXPLayoutSideDetailPanelComponent}.
6265
6851
  */
6266
6852
  class AXMDocumentExplorerDetailPanelComponent {
6853
+ static { this.METADATA_SECTION_KEY = '@document-management:terms.common.meta-data'; }
6267
6854
  //#endregion
6268
6855
  //#region ---- Lifecycle ----
6269
6856
  constructor() {
@@ -6284,6 +6871,8 @@ class AXMDocumentExplorerDetailPanelComponent {
6284
6871
  //#region ---- i18n ----
6285
6872
  this.multiSelectLabel = signal(null, /* @ts-ignore */
6286
6873
  ...(ngDevMode ? [{ debugName: "multiSelectLabel" }] : /* istanbul ignore next */ []));
6874
+ this.panelSections = signal([], /* @ts-ignore */
6875
+ ...(ngDevMode ? [{ debugName: "panelSections" }] : /* istanbul ignore next */ []));
6287
6876
  //#endregion
6288
6877
  //#region ---- Panel model ----
6289
6878
  this.panelHeader = computed(() => {
@@ -6313,56 +6902,46 @@ class AXMDocumentExplorerDetailPanelComponent {
6313
6902
  };
6314
6903
  }, /* @ts-ignore */
6315
6904
  ...(ngDevMode ? [{ debugName: "panelHeader" }] : /* istanbul ignore next */ []));
6316
- this.panelSections = computed(() => {
6317
- if (this.vm.hasMultipleSelectedItems()) {
6318
- return [];
6319
- }
6320
- const node = (this.vm.selectedNode() ?? this.vm.currentFolder());
6321
- if (node == null) {
6322
- return [];
6323
- }
6324
- const nodeInfo = this.vm.getNodeInfo(node);
6325
- return nodeInfo.sections.map((section) => ({
6326
- title: section.title,
6327
- projectionKey: section.title === 'Metadata' ? 'metadata' : undefined,
6328
- rows: section.title === 'Metadata'
6329
- ? undefined
6330
- : section.details.map((detail) => ({
6331
- label: detail.title,
6332
- value: detail.content,
6333
- format: detail.format,
6334
- })),
6335
- }));
6336
- }, /* @ts-ignore */
6337
- ...(ngDevMode ? [{ debugName: "panelSections" }] : /* istanbul ignore next */ []));
6338
6905
  effect(() => {
6339
6906
  void this.loadMultiSelectLabel();
6340
6907
  });
6908
+ effect(() => {
6909
+ this.vm.hasMultipleSelectedItems();
6910
+ this.vm.selectedNode();
6911
+ this.vm.currentFolder();
6912
+ void this.rebuildPanelSections();
6913
+ });
6341
6914
  effect(() => {
6342
6915
  const node = this.vm.selectedNode();
6343
- if (!node || node.type !== 'file' || !node.documentTypes?.[0]?.id) {
6916
+ if (!node || !node.documentTypes?.length) {
6917
+ this.metadataSchema.set(null);
6918
+ this.metadataContext.set({ metaDataForm: {} });
6919
+ this.metadataWidgetNode.set(null);
6920
+ return;
6921
+ }
6922
+ const typeIds = node.documentTypes
6923
+ .map((documentType) => documentType?.id)
6924
+ .filter((id) => typeof id === 'string' && id.length > 0);
6925
+ if (typeIds.length === 0) {
6344
6926
  this.metadataSchema.set(null);
6345
6927
  this.metadataContext.set({ metaDataForm: {} });
6346
6928
  this.metadataWidgetNode.set(null);
6347
6929
  return;
6348
6930
  }
6349
- const documentTypeId = node.documentTypes[0].id;
6350
- this.documentTypeService
6351
- .byKey(documentTypeId)
6352
- .then((doc) => {
6353
- const metaDataList = doc?.metaDataList ?? null;
6354
- this.metadataSchema.set(metaDataList);
6931
+ const appliesTo = node.type === 'folder' ? 'folder' : 'document';
6932
+ Promise.all(typeIds.map((id) => this.documentTypeService.byKey(id)))
6933
+ .then((types) => {
6934
+ const metaDataList = appliesTo === 'folder'
6935
+ ? collectFolderScopedMetaDataList(types)
6936
+ : collectDocumentScopedMetaDataList(types[0]?.metaDataList);
6937
+ const viewList = toViewMetaDataList(metaDataList);
6938
+ this.metadataSchema.set(viewList);
6355
6939
  this.metadataContext.set({ metaDataForm: (node.metaDataForm ?? {}) });
6356
- this.metadataWidgetNode.set(metaDataList
6940
+ this.metadataWidgetNode.set((viewList.groups ?? []).length
6357
6941
  ? {
6358
6942
  type: 'meta-data-form-editor',
6359
6943
  path: 'metaDataForm',
6360
- options: {
6361
- groups: (metaDataList.groups ?? []).map((group) => ({
6362
- ...group,
6363
- fields: (group.fields ?? []).map((field) => ({ ...field, mode: 'view' })),
6364
- })),
6365
- },
6944
+ options: { groups: viewList.groups },
6366
6945
  }
6367
6946
  : null);
6368
6947
  })
@@ -6388,6 +6967,40 @@ class AXMDocumentExplorerDetailPanelComponent {
6388
6967
  const itemsSelected = (await this.translationService.translateAsync('@general:terms.interface.items-selected')) ?? 'items selected';
6389
6968
  this.multiSelectLabel.set(`${this.vm.selectedCount()} ${itemsSelected}`);
6390
6969
  }
6970
+ async rebuildPanelSections() {
6971
+ if (this.vm.hasMultipleSelectedItems()) {
6972
+ this.panelSections.set([]);
6973
+ return;
6974
+ }
6975
+ const node = (this.vm.selectedNode() ?? this.vm.currentFolder());
6976
+ if (node == null) {
6977
+ this.panelSections.set([]);
6978
+ return;
6979
+ }
6980
+ const nodeInfo = this.vm.getNodeInfo(node);
6981
+ const t = this.translationService;
6982
+ const sections = [];
6983
+ for (const section of nodeInfo.sections) {
6984
+ const title = (await t.translateAsync(section.title)) ?? section.title;
6985
+ const isMetadata = section.title === AXMDocumentExplorerDetailPanelComponent.METADATA_SECTION_KEY;
6986
+ if (isMetadata) {
6987
+ sections.push({ title, projectionKey: 'metadata' });
6988
+ continue;
6989
+ }
6990
+ const rows = await Promise.all(section.details.map(async (detail) => {
6991
+ const content = typeof detail.content === 'string' && detail.content.startsWith('@document-management:')
6992
+ ? ((await t.translateAsync(detail.content)) ?? detail.content)
6993
+ : detail.content;
6994
+ return {
6995
+ label: (await t.translateAsync(detail.title)) ?? detail.title,
6996
+ value: content,
6997
+ format: detail.format,
6998
+ };
6999
+ }));
7000
+ sections.push({ title, rows });
7001
+ }
7002
+ this.panelSections.set(sections);
7003
+ }
6391
7004
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentExplorerDetailPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6392
7005
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMDocumentExplorerDetailPanelComponent, isStandalone: true, selector: "axm-document-explorer-detail-panel", ngImport: i0, template: "@if (vm.hasMultipleSelectedItems() && multiSelectLabel(); as multiLabel) {\n <axp-layout-side-detail-panel [multiSelectLabel]=\"multiLabel\" (panelClose)=\"onPanelClose()\" />\n} @else {\n <axp-layout-side-detail-panel\n [header]=\"panelHeader()\"\n [sections]=\"panelSections()\"\n (panelClose)=\"onPanelClose()\"\n >\n @if (metadataWidgetNode(); as widgetNode) {\n <ng-template axpLayoutSideDetailPanelSection=\"metadata\">\n <axp-widgets-container [context]=\"metadataContext()\">\n <ng-container axp-widget-renderer [node]=\"widgetNode\" [mode]=\"'view'\"></ng-container>\n </axp-widgets-container>\n </ng-template>\n }\n </axp-layout-side-detail-panel>\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i6.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i6.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "component", type: AXPLayoutSideDetailPanelComponent, selector: "axp-layout-side-detail-panel", inputs: ["multiSelectLabel", "header", "sections", "rows", "rowsSectionTitle", "noRowsMessage", "emptyState"], outputs: ["panelClose"] }, { kind: "directive", type: AXPLayoutSideDetailPanelSectionDirective, selector: "[axpLayoutSideDetailPanelSection]", inputs: ["axpLayoutSideDetailPanelSection"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6393
7006
  }
@@ -6477,18 +7090,20 @@ class AXMDocumentVersionBadgeComponent {
6477
7090
  //#region ----- Computed Properties -----
6478
7091
  this.versionNumber = computed(() => resolveDocumentVersionNumber(this.node()), /* @ts-ignore */
6479
7092
  ...(ngDevMode ? [{ debugName: "versionNumber" }] : /* istanbul ignore next */ []));
7093
+ this.isDraft = computed(() => this.node().versioningStatus === AXPVersioningStatus.Draft, /* @ts-ignore */
7094
+ ...(ngDevMode ? [{ debugName: "isDraft" }] : /* istanbul ignore next */ []));
6480
7095
  this.textKey = `${VERSION_BADGE_I18N}.text`;
6481
7096
  this.tooltipKey = `${VERSION_BADGE_I18N}.tooltip`;
6482
7097
  }
6483
7098
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentVersionBadgeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6484
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMDocumentVersionBadgeComponent, isStandalone: true, selector: "axm-document-version-badge", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "hidden": "versionNumber() == null" }, classAttribute: "axm-document-version-badge" }, ngImport: i0, template: "@if (versionNumber(); as version) {\n <!-- ----- Version number when versioning is enabled ----- -->\n <span\n class=\"axm-document-version-badge__chip\"\n [axTooltip]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n axTooltipPlacement=\"top\"\n [attr.aria-label]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n >\n <i class=\"fa-light fa-code-branch\" aria-hidden=\"true\"></i>\n <span class=\"axm-document-version-badge__text\">{{\n (textKey | translate: { params: { version } } | async) ?? ''\n }}</span>\n </span>\n}\n", styles: ["@layer properties;.axm-document-version-badge{display:inline-flex;flex-shrink:0;align-items:center}.axm-document-version-badge__chip{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * .5);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:1px;background-color:var(--color-primary-lightest);color:var(--color-on-primary-lightest);border-color:var(--color-border-primary-lightest);border-color:rgba(var(--ax-sys-color-primary-200));color:rgba(var(--ax-sys-color-primary-surface));--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);cursor:help;font-size:10px;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em)}.axm-document-version-badge__chip i{font-size:9px;opacity:75%}.axm-document-version-badge__text{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXTooltipModule }, { kind: "directive", type: i2$2.AXTooltipDirective, selector: "[axTooltip]", inputs: ["axTooltipDisabled", "axTooltip", "axTooltipContext", "axTooltipPlacement", "axTooltipOffsetX", "axTooltipOffsetY", "axTooltipOpenAfter", "axTooltipCloseAfter"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$2.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
7099
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMDocumentVersionBadgeComponent, isStandalone: true, selector: "axm-document-version-badge", inputs: { node: { classPropertyName: "node", publicName: "node", isSignal: true, isRequired: true, transformFunction: null } }, host: { properties: { "hidden": "versionNumber() == null" }, classAttribute: "axm-document-version-badge" }, ngImport: i0, template: "@if (versionNumber(); as version) {\n <!-- ----- Version number when versioning is enabled ----- -->\n <span\n class=\"axm-document-version-badge__chip\"\n [class.axm-document-version-badge__chip--draft]=\"isDraft()\"\n [axTooltip]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n axTooltipPlacement=\"top\"\n [attr.aria-label]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n >\n <i class=\"fa-light fa-code-branch\" aria-hidden=\"true\"></i>\n <span class=\"axm-document-version-badge__text\">{{\n (textKey | translate: { params: { version } } | async) ?? ''\n }}</span>\n </span>\n}\n", styles: ["@layer properties;.axm-document-version-badge{display:inline-flex;flex-shrink:0;align-items:center}.axm-document-version-badge__chip{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * .5);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:1px;background-color:var(--color-primary-lightest);color:var(--color-on-primary-lightest);border-color:var(--color-border-primary-lightest);border-color:rgba(var(--ax-sys-color-primary-200));color:rgba(var(--ax-sys-color-primary-surface));--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);cursor:help;font-size:10px;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em)}.axm-document-version-badge__chip--draft{background-color:var(--color-warning-lightest);color:var(--color-on-warning-lightest);border-color:var(--color-border-warning-lightest);border-color:rgba(var(--ax-sys-color-warning-200));color:rgba(var(--ax-sys-color-warning-surface))}.axm-document-version-badge__chip i{font-size:9px;opacity:75%}.axm-document-version-badge__text{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXTooltipModule }, { kind: "directive", type: i2$2.AXTooltipDirective, selector: "[axTooltip]", inputs: ["axTooltipDisabled", "axTooltip", "axTooltipContext", "axTooltipPlacement", "axTooltipOffsetX", "axTooltipOffsetY", "axTooltipOpenAfter", "axTooltipCloseAfter"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i3$2.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6485
7100
  }
6486
7101
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentVersionBadgeComponent, decorators: [{
6487
7102
  type: Component,
6488
7103
  args: [{ selector: 'axm-document-version-badge', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
6489
7104
  class: 'axm-document-version-badge',
6490
7105
  '[hidden]': 'versionNumber() == null',
6491
- }, imports: [AXTooltipModule, AXTranslationModule, AsyncPipe], template: "@if (versionNumber(); as version) {\n <!-- ----- Version number when versioning is enabled ----- -->\n <span\n class=\"axm-document-version-badge__chip\"\n [axTooltip]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n axTooltipPlacement=\"top\"\n [attr.aria-label]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n >\n <i class=\"fa-light fa-code-branch\" aria-hidden=\"true\"></i>\n <span class=\"axm-document-version-badge__text\">{{\n (textKey | translate: { params: { version } } | async) ?? ''\n }}</span>\n </span>\n}\n", styles: ["@layer properties;.axm-document-version-badge{display:inline-flex;flex-shrink:0;align-items:center}.axm-document-version-badge__chip{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * .5);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:1px;background-color:var(--color-primary-lightest);color:var(--color-on-primary-lightest);border-color:var(--color-border-primary-lightest);border-color:rgba(var(--ax-sys-color-primary-200));color:rgba(var(--ax-sys-color-primary-surface));--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);cursor:help;font-size:10px;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em)}.axm-document-version-badge__chip i{font-size:9px;opacity:75%}.axm-document-version-badge__text{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
7106
+ }, imports: [AXTooltipModule, AXTranslationModule, AsyncPipe], template: "@if (versionNumber(); as version) {\n <!-- ----- Version number when versioning is enabled ----- -->\n <span\n class=\"axm-document-version-badge__chip\"\n [class.axm-document-version-badge__chip--draft]=\"isDraft()\"\n [axTooltip]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n axTooltipPlacement=\"top\"\n [attr.aria-label]=\"(tooltipKey | translate: { params: { version } } | async) ?? ''\"\n >\n <i class=\"fa-light fa-code-branch\" aria-hidden=\"true\"></i>\n <span class=\"axm-document-version-badge__text\">{{\n (textKey | translate: { params: { version } } | async) ?? ''\n }}</span>\n </span>\n}\n", styles: ["@layer properties;.axm-document-version-badge{display:inline-flex;flex-shrink:0;align-items:center}.axm-document-version-badge__chip{display:inline-flex;align-items:center;gap:calc(var(--spacing, .25rem) * .5);border-radius:calc(infinity * 1px);border-style:var(--tw-border-style);border-width:1px;padding-inline:calc(var(--spacing, .25rem) * 1.5);padding-block:1px;background-color:var(--color-primary-lightest);color:var(--color-on-primary-lightest);border-color:var(--color-border-primary-lightest);border-color:rgba(var(--ax-sys-color-primary-200));color:rgba(var(--ax-sys-color-primary-surface));--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / .1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / .1));box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);cursor:help;font-size:10px;--tw-leading: 1;line-height:1;--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);--tw-tracking: var(--tracking-wide, .025em);letter-spacing:var(--tracking-wide, .025em)}.axm-document-version-badge__chip--draft{background-color:var(--color-warning-lightest);color:var(--color-on-warning-lightest);border-color:var(--color-border-warning-lightest);border-color:rgba(var(--ax-sys-color-warning-200));color:rgba(var(--ax-sys-color-warning-surface))}.axm-document-version-badge__chip i{font-size:9px;opacity:75%}.axm-document-version-badge__text{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-inset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-shadow-color{syntax: \"*\"; inherits: false;}@property --tw-inset-shadow-alpha{syntax: \"<percentage>\"; inherits: false; initial-value: 100%;}@property --tw-ring-color{syntax: \"*\"; inherits: false;}@property --tw-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-inset-ring-color{syntax: \"*\"; inherits: false;}@property --tw-inset-ring-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-ring-inset{syntax: \"*\"; inherits: false;}@property --tw-ring-offset-width{syntax: \"<length>\"; inherits: false; initial-value: 0px;}@property --tw-ring-offset-color{syntax: \"*\"; inherits: false; initial-value: #fff;}@property --tw-ring-offset-shadow{syntax: \"*\"; inherits: false; initial-value: 0 0 #0000;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{syntax: \"*\"; inherits: false;}@property --tw-tracking{syntax: \"*\"; inherits: false;}@property --tw-ordinal{syntax: \"*\"; inherits: false;}@property --tw-slashed-zero{syntax: \"*\"; inherits: false;}@property --tw-numeric-figure{syntax: \"*\"; inherits: false;}@property --tw-numeric-spacing{syntax: \"*\"; inherits: false;}@property --tw-numeric-fraction{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-shadow: 0 0 #0000;--tw-shadow-color: initial;--tw-shadow-alpha: 100%;--tw-inset-shadow: 0 0 #0000;--tw-inset-shadow-color: initial;--tw-inset-shadow-alpha: 100%;--tw-ring-color: initial;--tw-ring-shadow: 0 0 #0000;--tw-inset-ring-color: initial;--tw-inset-ring-shadow: 0 0 #0000;--tw-ring-inset: initial;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-offset-shadow: 0 0 #0000;--tw-leading: initial;--tw-font-weight: initial;--tw-tracking: initial;--tw-ordinal: initial;--tw-slashed-zero: initial;--tw-numeric-figure: initial;--tw-numeric-spacing: initial;--tw-numeric-fraction: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
6492
7107
  }], propDecorators: { node: [{ type: i0.Input, args: [{ isSignal: true, alias: "node", required: true }] }] } });
6493
7108
 
6494
7109
  //#region ----- Imports -----
@@ -6626,14 +7241,19 @@ class AXMDocumentDrivePageComponent extends AXPPageLayoutBaseComponent {
6626
7241
  { key: 'size', textKey: 'actions.sort-by-size', icon: 'fa-light fa-weight-hanging' },
6627
7242
  ], /* @ts-ignore */
6628
7243
  ...(ngDevMode ? [{ debugName: "sortItems" }] : /* istanbul ignore next */ []));
6629
- this.viewsItems = signal([
6630
- { key: 'large-icons', icon: 'fa-light fa-grid' },
6631
- { key: 'small-icons', icon: 'fa-light fa-grid', break: true },
6632
- { key: 'large-tiles', icon: 'fa-grid-2' },
6633
- { key: 'small-tiles', icon: 'fa-grid-2', break: true },
6634
- // { key: 'details', icon: 'fa-bars', break: true },
6635
- { key: 'list', icon: 'fa-list' },
6636
- ], /* @ts-ignore */
7244
+ this.viewsItems = computed(() => {
7245
+ const items = [
7246
+ { key: 'large-icons', icon: 'fa-light fa-grid' },
7247
+ { key: 'small-icons', icon: 'fa-light fa-grid', break: true },
7248
+ { key: 'large-tiles', icon: 'fa-grid-2' },
7249
+ { key: 'small-tiles', icon: 'fa-grid-2', break: true },
7250
+ { key: 'list', icon: 'fa-list' },
7251
+ ];
7252
+ if (this.vm.canUseHomogeneousGrid()) {
7253
+ items.splice(items.length - 1, 0, { key: 'details', icon: 'fa-light fa-table', break: true });
7254
+ }
7255
+ return items;
7256
+ }, /* @ts-ignore */
6637
7257
  ...(ngDevMode ? [{ debugName: "viewsItems" }] : /* istanbul ignore next */ []));
6638
7258
  this.selectedViewMode = computed(() => this.viewsItems().find((item) => item.key === this.vm.viewMode()) ?? this.viewsItems()[0], /* @ts-ignore */
6639
7259
  ...(ngDevMode ? [{ debugName: "selectedViewMode" }] : /* istanbul ignore next */ []));
@@ -6678,6 +7298,8 @@ class AXMDocumentDrivePageComponent extends AXPPageLayoutBaseComponent {
6678
7298
  this.#pageMetadataEffect = effect(() => {
6679
7299
  this.vm.isLoading();
6680
7300
  this.vm.currentNode();
7301
+ this.vm.selectedCount();
7302
+ this.vm.viewMode();
6681
7303
  untracked(() => {
6682
7304
  this.recompute();
6683
7305
  });
@@ -6855,7 +7477,7 @@ class AXMDocumentDrivePageComponent extends AXPPageLayoutBaseComponent {
6855
7477
  //#endregion
6856
7478
  //#region ---- Page Layout Overrides ----
6857
7479
  async getPrimaryMenuItems() {
6858
- if (this.vm.hasMultipleSelectedItems()) {
7480
+ if (this.vm.showSelectionDeleteActions()) {
6859
7481
  return [
6860
7482
  {
6861
7483
  name: 'deleteItems',
@@ -6881,7 +7503,7 @@ class AXMDocumentDrivePageComponent extends AXPPageLayoutBaseComponent {
6881
7503
  return [];
6882
7504
  }
6883
7505
  async getSecondaryMenuItems() {
6884
- if (this.vm.hasMultipleSelectedItems()) {
7506
+ if (this.vm.showSelectionDeleteActions()) {
6885
7507
  return [
6886
7508
  {
6887
7509
  name: 'delete',
@@ -6968,7 +7590,7 @@ class AXMDocumentDrivePageComponent extends AXPPageLayoutBaseComponent {
6968
7590
  provide: AXPPageLayoutBase,
6969
7591
  useExisting: AXMDocumentDrivePageComponent,
6970
7592
  },
6971
- ], usesInheritance: true, ngImport: i0, template: "<div class=\"flex flex-col gap-2\">\n <!-- Back (left) + View Mode & Detail Panel Toggle (right) -->\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n @if (canGoBackInPage()) {\n <ax-button (onClick)=\"handleBack()\" [title]=\"'@general:actions.back.title' | translate | async\">\n <ax-icon icon=\"fa-light fa-arrow-left\"></ax-icon>\n </ax-button>\n }\n </div>\n <div class=\"flex gap-2 items-center\">\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <ax-button-item\n [text]=\"('@document-management:view-modes.' + item.key | translate | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n @if (deviceService.isLarge()) {\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </div>\n </div>\n <div class=\"overflow-auto flex flex-row gap-4\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50\"></axm-document-explorer-detail-panel>\n }\n </div>\n</div>\n\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXMenuModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$5.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$5.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$5.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i2$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: AXMDocumentExplorerComponent, selector: "axm-document-explorer", inputs: ["browseMode", "viewMode", "selectionMode", "showContextMenu"] }, { kind: "component", type: AXMDocumentExplorerDetailPanelComponent, selector: "axm-document-explorer-detail-panel" }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
7593
+ ], usesInheritance: true, ngImport: i0, template: "<div class=\"flex min-h-0 min-w-0 flex-col gap-2\">\n <!-- Back (left) + View Mode & Detail Panel Toggle (right) -->\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n @if (canGoBackInPage()) {\n <ax-button (onClick)=\"handleBack()\" [title]=\"'@general:actions.back.title' | translate | async\">\n <ax-icon icon=\"fa-light fa-arrow-left\"></ax-icon>\n </ax-button>\n }\n </div>\n <div class=\"flex gap-2 items-center\">\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <ax-button-item\n [text]=\"('@document-management:view-modes.' + item.key | translate | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n @if (deviceService.isLarge()) {\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </div>\n </div>\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-row gap-4 overflow-hidden\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50 h-full w-80 shrink-0\"></axm-document-explorer-detail-panel>\n }\n </div>\n</div>\n\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXMenuModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$5.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$5.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$5.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i2$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXSearchBoxModule }, { kind: "component", type: AXMDocumentExplorerComponent, selector: "axm-document-explorer", inputs: ["browseMode", "viewMode", "selectionMode", "showContextMenu"] }, { kind: "component", type: AXMDocumentExplorerDetailPanelComponent, selector: "axm-document-explorer-detail-panel" }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: i3$2.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
6972
7594
  }
6973
7595
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMDocumentDrivePageComponent, decorators: [{
6974
7596
  type: Component,
@@ -6992,7 +7614,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
6992
7614
  provide: AXPPageLayoutBase,
6993
7615
  useExisting: AXMDocumentDrivePageComponent,
6994
7616
  },
6995
- ], template: "<div class=\"flex flex-col gap-2\">\n <!-- Back (left) + View Mode & Detail Panel Toggle (right) -->\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n @if (canGoBackInPage()) {\n <ax-button (onClick)=\"handleBack()\" [title]=\"'@general:actions.back.title' | translate | async\">\n <ax-icon icon=\"fa-light fa-arrow-left\"></ax-icon>\n </ax-button>\n }\n </div>\n <div class=\"flex gap-2 items-center\">\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <ax-button-item\n [text]=\"('@document-management:view-modes.' + item.key | translate | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n @if (deviceService.isLarge()) {\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </div>\n </div>\n <div class=\"overflow-auto flex flex-row gap-4\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50\"></axm-document-explorer-detail-panel>\n }\n </div>\n</div>\n\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
7617
+ ], template: "<div class=\"flex min-h-0 min-w-0 flex-col gap-2\">\n <!-- Back (left) + View Mode & Detail Panel Toggle (right) -->\n <div class=\"flex justify-between items-center\">\n <div class=\"flex gap-2 items-center\">\n @if (canGoBackInPage()) {\n <ax-button (onClick)=\"handleBack()\" [title]=\"'@general:actions.back.title' | translate | async\">\n <ax-icon icon=\"fa-light fa-arrow-left\"></ax-icon>\n </ax-button>\n }\n </div>\n <div class=\"flex gap-2 items-center\">\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <ax-button-item\n [text]=\"('@document-management:view-modes.' + item.key | translate | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n @if (deviceService.isLarge()) {\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </div>\n </div>\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-row gap-4 overflow-hidden\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50 h-full w-80 shrink-0\"></axm-document-explorer-detail-panel>\n }\n </div>\n</div>\n\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
6996
7618
  }], propDecorators: { rootContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "rootContext", required: false }] }], pageConfig: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageConfig", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }] } });
6997
7619
 
6998
7620
  var documentDrivePage_component = /*#__PURE__*/Object.freeze({
@@ -7383,15 +8005,15 @@ class AXMDocumentManagementModule {
7383
8005
  provideCommandSetups([
7384
8006
  {
7385
8007
  key: 'DocumentManagement.Document:Upload',
7386
- command: () => import('./acorex-platform-module-document-management-client-upload-document.command-CCRAgI9w.mjs').then((c) => c.AXMUploadDocumentCommand),
8008
+ command: () => import('./acorex-platform-module-document-management-client-upload-document.command-D3L6x6CQ.mjs').then((c) => c.AXMUploadDocumentCommand),
7387
8009
  },
7388
8010
  {
7389
8011
  key: 'DocumentManagement.Document:Open',
7390
- command: () => import('./acorex-platform-module-document-management-client-open-document.command--tM4SRV7.mjs').then((c) => c.AXMOpenDocumentCommand),
8012
+ command: () => import('./acorex-platform-module-document-management-client-open-document.command-Bimm2bzt.mjs').then((c) => c.AXMOpenDocumentCommand),
7391
8013
  },
7392
8014
  {
7393
8015
  key: 'DocumentManagement.Document:Distribute',
7394
- command: () => import('./acorex-platform-module-document-management-client-distribute-document.command-CCLwJcFb.mjs').then((c) => c.AXMDistributeDocumentCommand),
8016
+ command: () => import('./acorex-platform-module-document-management-client-distribute-document.command-BaCdm2YF.mjs').then((c) => c.AXMDistributeDocumentCommand),
7395
8017
  },
7396
8018
  {
7397
8019
  key: 'DocumentManagement.DocumentDistribution:SignOff',
@@ -7482,15 +8104,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
7482
8104
  provideCommandSetups([
7483
8105
  {
7484
8106
  key: 'DocumentManagement.Document:Upload',
7485
- command: () => import('./acorex-platform-module-document-management-client-upload-document.command-CCRAgI9w.mjs').then((c) => c.AXMUploadDocumentCommand),
8107
+ command: () => import('./acorex-platform-module-document-management-client-upload-document.command-D3L6x6CQ.mjs').then((c) => c.AXMUploadDocumentCommand),
7486
8108
  },
7487
8109
  {
7488
8110
  key: 'DocumentManagement.Document:Open',
7489
- command: () => import('./acorex-platform-module-document-management-client-open-document.command--tM4SRV7.mjs').then((c) => c.AXMOpenDocumentCommand),
8111
+ command: () => import('./acorex-platform-module-document-management-client-open-document.command-Bimm2bzt.mjs').then((c) => c.AXMOpenDocumentCommand),
7490
8112
  },
7491
8113
  {
7492
8114
  key: 'DocumentManagement.Document:Distribute',
7493
- command: () => import('./acorex-platform-module-document-management-client-distribute-document.command-CCLwJcFb.mjs').then((c) => c.AXMDistributeDocumentCommand),
8115
+ command: () => import('./acorex-platform-module-document-management-client-distribute-document.command-BaCdm2YF.mjs').then((c) => c.AXMDistributeDocumentCommand),
7494
8116
  },
7495
8117
  {
7496
8118
  key: 'DocumentManagement.DocumentDistribution:SignOff',
@@ -7578,14 +8200,19 @@ class AXMDocumentDriveComponent extends AXPPageLayoutBaseComponent {
7578
8200
  { key: 'size', textKey: 'actions.sort-by-size', icon: 'fa-light fa-weight-hanging' },
7579
8201
  ], /* @ts-ignore */
7580
8202
  ...(ngDevMode ? [{ debugName: "sortItems" }] : /* istanbul ignore next */ []));
7581
- this.viewsItems = signal([
7582
- { key: 'large-icons', icon: 'fa-light fa-grid' },
7583
- { key: 'small-icons', icon: 'fa-light fa-grid', break: true },
7584
- { key: 'large-tiles', icon: 'fa-grid-2' },
7585
- { key: 'small-tiles', icon: 'fa-grid-2', break: true },
7586
- // { key: 'details', icon: 'fa-bars', break: true },
7587
- { key: 'list', icon: 'fa-list' },
7588
- ], /* @ts-ignore */
8203
+ this.viewsItems = computed(() => {
8204
+ const items = [
8205
+ { key: 'large-icons', icon: 'fa-light fa-grid' },
8206
+ { key: 'small-icons', icon: 'fa-light fa-grid', break: true },
8207
+ { key: 'large-tiles', icon: 'fa-grid-2' },
8208
+ { key: 'small-tiles', icon: 'fa-grid-2', break: true },
8209
+ { key: 'list', icon: 'fa-list' },
8210
+ ];
8211
+ if (this.vm.canUseHomogeneousGrid()) {
8212
+ items.splice(items.length - 1, 0, { key: 'details', icon: 'fa-light fa-table', break: true });
8213
+ }
8214
+ return items;
8215
+ }, /* @ts-ignore */
7589
8216
  ...(ngDevMode ? [{ debugName: "viewsItems" }] : /* istanbul ignore next */ []));
7590
8217
  this.selectedViewMode = computed(() => this.viewsItems().find((item) => item.key === this.vm.viewMode()) || this.viewsItems()[0], /* @ts-ignore */
7591
8218
  ...(ngDevMode ? [{ debugName: "selectedViewMode" }] : /* istanbul ignore next */ []));
@@ -7619,6 +8246,8 @@ class AXMDocumentDriveComponent extends AXPPageLayoutBaseComponent {
7619
8246
  this.#pageMetadataEffect = effect(() => {
7620
8247
  this.vm.isLoading();
7621
8248
  this.vm.currentNode();
8249
+ this.vm.selectedCount();
8250
+ this.vm.viewMode();
7622
8251
  untracked(() => {
7623
8252
  this.recompute();
7624
8253
  });
@@ -8092,7 +8721,7 @@ class AXMDocumentDriveComponent extends AXPPageLayoutBaseComponent {
8092
8721
  //#endregion
8093
8722
  //#region ---------------- Page Configuration Overrides ----------------
8094
8723
  async getPrimaryMenuItems() {
8095
- if (this.vm.hasMultipleSelectedItems()) {
8724
+ if (this.vm.showSelectionDeleteActions()) {
8096
8725
  return [
8097
8726
  {
8098
8727
  name: 'deleteItems',
@@ -8104,6 +8733,9 @@ class AXMDocumentDriveComponent extends AXPPageLayoutBaseComponent {
8104
8733
  ];
8105
8734
  }
8106
8735
  const addItemItems = await this.vm.getFolderAddMenuItems();
8736
+ if (addItemItems.length === 0) {
8737
+ return [];
8738
+ }
8107
8739
  addItemItems[addItemItems.length - 1].break = false;
8108
8740
  return [
8109
8741
  {
@@ -8115,7 +8747,7 @@ class AXMDocumentDriveComponent extends AXPPageLayoutBaseComponent {
8115
8747
  ];
8116
8748
  }
8117
8749
  async getSecondaryMenuItems() {
8118
- if (this.vm.hasMultipleSelectedItems()) {
8750
+ if (this.vm.showSelectionDeleteActions()) {
8119
8751
  return [
8120
8752
  {
8121
8753
  name: 'delete',
@@ -8229,7 +8861,7 @@ class AXMDocumentDriveComponent extends AXPPageLayoutBaseComponent {
8229
8861
  provide: AXPPageLayoutBase,
8230
8862
  useExisting: AXMDocumentDriveComponent,
8231
8863
  },
8232
- ], viewQueries: [{ propertyName: "documentExplorer", first: true, predicate: AXMDocumentExplorerComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Main Layout -->\n<axp-page-layout *translate=\"let t\">\n <axp-page-toolbar>\n <!-- Left Side Toolbar -->\n <div class=\"w-full flex items-center\">\n <axp-layout-prefix class=\"w-full\">\n @if (vm.hasMultipleSelectedItems()) {\n <div class=\"flex gap-3 items-center h-10\">\n <span class=\"text-xl font-bold\">\n {{ vm.selectedCount() }} {{ '@general:terms.interface.items-selected' | translate | async }}\n </span>\n <span (click)=\"vm.deselectAll()\" class=\"text-sm text-secondary underline cursor-pointer\">{{\n '@general:actions.unselect.title' | translate | async\n }}</span>\n </div>\n } @else {\n @for (_k of [queryFiltersKey()]; track _k) {\n <axp-query-filters\n [filtersDefinitions]=\"advancedFilterDefinitions()\"\n [initialFilters]=\"panelInitialFilters()\"\n (onFiltersChanged)=\"handleAdvancedFiltersChanged($event)\"\n [quickSearch]=\"true\"\n ></axp-query-filters>\n }\n }\n </axp-layout-prefix>\n\n <!-- Right Side Toolbar -->\n\n <axp-layout-suffix class=\"flex gap-2\">\n <!-- Sort Dropdown -->\n <ax-button>\n <ax-icon\n [icon]=\"'fa-light fa-arrow-' + (vm.sortDirection() === 'asc' ? 'up' : 'down') + '-wide-short'\"\n ></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <!-- Sort By Options -->\n @for (item of sortItems(); track item.key) {\n <ax-button-item\n [text]=\"(t(item.textKey, { scope: rootConfig.config.i18n }) | async)!\"\n (onClick)=\"vm.setSortField(item.key)\"\n [selected]=\"vm.sortField() === item.key\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n <ax-divider></ax-divider>\n <!-- Sort Direction Options -->\n <ax-button-item\n [text]=\"(t('actions.sort-ascending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'asc'\"\n (onClick)=\"vm.setSortDirection('asc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-up-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"(t('actions.sort-descending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'desc'\"\n (onClick)=\"vm.setSortDirection('desc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-down-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n <!-- View Mode Toggle -->\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <!-- view mode items -->\n <ax-button-item\n [text]=\"(t('view-modes.' + item.key, { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n <!-- end of view mode items -->\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n @if (deviceService.isLarge()) {\n <!-- Detail Panel Toggle -->\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </axp-layout-suffix>\n </div>\n </axp-page-toolbar>\n\n <!-- Content Section -->\n <axp-page-content class=\"overflow-auto flex flex-col\">\n <div class=\"flex flex-row gap-4 flex-1 overflow-auto\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50\"></axm-document-explorer-detail-panel>\n }\n </div>\n </axp-page-content>\n\n <!-- Footer Section removed: breadcrumbs are now provided via page-level breadcrumbs -->\n</axp-page-layout>\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type:
8864
+ ], viewQueries: [{ propertyName: "documentExplorer", first: true, predicate: AXMDocumentExplorerComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<!-- Main Layout -->\n<axp-page-layout *translate=\"let t\">\n <axp-page-toolbar>\n <!-- Left Side Toolbar -->\n <div class=\"w-full flex items-center\">\n <axp-layout-prefix class=\"w-full\">\n @if (vm.hasMultipleSelectedItems() && !vm.isDetailsView()) {\n <div class=\"flex gap-3 items-center h-10\">\n <span class=\"text-xl font-bold\">\n {{ vm.selectedCount() }} {{ '@general:terms.interface.items-selected' | translate | async }}\n </span>\n <span (click)=\"vm.deselectAll()\" class=\"text-sm text-secondary underline cursor-pointer\">{{\n '@general:actions.unselect.title' | translate | async\n }}</span>\n </div>\n } @else {\n @for (_k of [queryFiltersKey()]; track _k) {\n <axp-query-filters\n [filtersDefinitions]=\"advancedFilterDefinitions()\"\n [initialFilters]=\"panelInitialFilters()\"\n (onFiltersChanged)=\"handleAdvancedFiltersChanged($event)\"\n [quickSearch]=\"true\"\n ></axp-query-filters>\n }\n }\n </axp-layout-prefix>\n\n <!-- Right Side Toolbar -->\n\n <axp-layout-suffix class=\"flex gap-2\">\n <!-- Sort Dropdown -->\n <ax-button>\n <ax-icon\n [icon]=\"'fa-light fa-arrow-' + (vm.sortDirection() === 'asc' ? 'up' : 'down') + '-wide-short'\"\n ></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <!-- Sort By Options -->\n @for (item of sortItems(); track item.key) {\n <ax-button-item\n [text]=\"(t(item.textKey, { scope: rootConfig.config.i18n }) | async)!\"\n (onClick)=\"vm.setSortField(item.key)\"\n [selected]=\"vm.sortField() === item.key\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n <ax-divider></ax-divider>\n <!-- Sort Direction Options -->\n <ax-button-item\n [text]=\"(t('actions.sort-ascending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'asc'\"\n (onClick)=\"vm.setSortDirection('asc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-up-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"(t('actions.sort-descending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'desc'\"\n (onClick)=\"vm.setSortDirection('desc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-down-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n <!-- View Mode Toggle -->\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <!-- view mode items -->\n <ax-button-item\n [text]=\"(t('view-modes.' + item.key, { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n <!-- end of view mode items -->\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n @if (deviceService.isLarge()) {\n <!-- Detail Panel Toggle -->\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </axp-layout-suffix>\n </div>\n </axp-page-toolbar>\n\n <!-- Content Section -->\n <axp-page-content class=\"flex min-w-0 flex-col overflow-x-hidden overflow-y-auto\">\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-row gap-4 overflow-hidden\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50 h-full w-80 shrink-0\"></axm-document-explorer-detail-panel>\n }\n </div>\n </axp-page-content>\n\n <!-- Footer Section removed: breadcrumbs are now provided via page-level breadcrumbs -->\n</axp-page-layout>\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type:
8233
8865
  //
8234
8866
  AXMenuModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$5.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "component", type: i1$5.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1$5.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXButtonGroupModule }, { kind: "ngmodule", type: AXDropdownButtonModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i2$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i3$2.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXBreadcrumbsModule }, { kind: "ngmodule", type: AXBadgeModule }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXFileModule }, { kind: "ngmodule", type: AXDateTimeModule }, { kind: "component", type:
8235
8867
  //
@@ -8269,7 +8901,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
8269
8901
  provide: AXPPageLayoutBase,
8270
8902
  useExisting: AXMDocumentDriveComponent,
8271
8903
  },
8272
- ], template: "<!-- Main Layout -->\n<axp-page-layout *translate=\"let t\">\n <axp-page-toolbar>\n <!-- Left Side Toolbar -->\n <div class=\"w-full flex items-center\">\n <axp-layout-prefix class=\"w-full\">\n @if (vm.hasMultipleSelectedItems()) {\n <div class=\"flex gap-3 items-center h-10\">\n <span class=\"text-xl font-bold\">\n {{ vm.selectedCount() }} {{ '@general:terms.interface.items-selected' | translate | async }}\n </span>\n <span (click)=\"vm.deselectAll()\" class=\"text-sm text-secondary underline cursor-pointer\">{{\n '@general:actions.unselect.title' | translate | async\n }}</span>\n </div>\n } @else {\n @for (_k of [queryFiltersKey()]; track _k) {\n <axp-query-filters\n [filtersDefinitions]=\"advancedFilterDefinitions()\"\n [initialFilters]=\"panelInitialFilters()\"\n (onFiltersChanged)=\"handleAdvancedFiltersChanged($event)\"\n [quickSearch]=\"true\"\n ></axp-query-filters>\n }\n }\n </axp-layout-prefix>\n\n <!-- Right Side Toolbar -->\n\n <axp-layout-suffix class=\"flex gap-2\">\n <!-- Sort Dropdown -->\n <ax-button>\n <ax-icon\n [icon]=\"'fa-light fa-arrow-' + (vm.sortDirection() === 'asc' ? 'up' : 'down') + '-wide-short'\"\n ></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <!-- Sort By Options -->\n @for (item of sortItems(); track item.key) {\n <ax-button-item\n [text]=\"(t(item.textKey, { scope: rootConfig.config.i18n }) | async)!\"\n (onClick)=\"vm.setSortField(item.key)\"\n [selected]=\"vm.sortField() === item.key\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n <ax-divider></ax-divider>\n <!-- Sort Direction Options -->\n <ax-button-item\n [text]=\"(t('actions.sort-ascending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'asc'\"\n (onClick)=\"vm.setSortDirection('asc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-up-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"(t('actions.sort-descending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'desc'\"\n (onClick)=\"vm.setSortDirection('desc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-down-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n <!-- View Mode Toggle -->\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <!-- view mode items -->\n <ax-button-item\n [text]=\"(t('view-modes.' + item.key, { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n <!-- end of view mode items -->\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n @if (deviceService.isLarge()) {\n <!-- Detail Panel Toggle -->\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </axp-layout-suffix>\n </div>\n </axp-page-toolbar>\n\n <!-- Content Section -->\n <axp-page-content class=\"overflow-auto flex flex-col\">\n <div class=\"flex flex-row gap-4 flex-1 overflow-auto\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50\"></axm-document-explorer-detail-panel>\n }\n </div>\n </axp-page-content>\n\n <!-- Footer Section removed: breadcrumbs are now provided via page-level breadcrumbs -->\n</axp-page-layout>\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
8904
+ ], template: "<!-- Main Layout -->\n<axp-page-layout *translate=\"let t\">\n <axp-page-toolbar>\n <!-- Left Side Toolbar -->\n <div class=\"w-full flex items-center\">\n <axp-layout-prefix class=\"w-full\">\n @if (vm.hasMultipleSelectedItems() && !vm.isDetailsView()) {\n <div class=\"flex gap-3 items-center h-10\">\n <span class=\"text-xl font-bold\">\n {{ vm.selectedCount() }} {{ '@general:terms.interface.items-selected' | translate | async }}\n </span>\n <span (click)=\"vm.deselectAll()\" class=\"text-sm text-secondary underline cursor-pointer\">{{\n '@general:actions.unselect.title' | translate | async\n }}</span>\n </div>\n } @else {\n @for (_k of [queryFiltersKey()]; track _k) {\n <axp-query-filters\n [filtersDefinitions]=\"advancedFilterDefinitions()\"\n [initialFilters]=\"panelInitialFilters()\"\n (onFiltersChanged)=\"handleAdvancedFiltersChanged($event)\"\n [quickSearch]=\"true\"\n ></axp-query-filters>\n }\n }\n </axp-layout-prefix>\n\n <!-- Right Side Toolbar -->\n\n <axp-layout-suffix class=\"flex gap-2\">\n <!-- Sort Dropdown -->\n <ax-button>\n <ax-icon\n [icon]=\"'fa-light fa-arrow-' + (vm.sortDirection() === 'asc' ? 'up' : 'down') + '-wide-short'\"\n ></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n <!-- Sort By Options -->\n @for (item of sortItems(); track item.key) {\n <ax-button-item\n [text]=\"(t(item.textKey, { scope: rootConfig.config.i18n }) | async)!\"\n (onClick)=\"vm.setSortField(item.key)\"\n [selected]=\"vm.sortField() === item.key\"\n >\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n }\n <ax-divider></ax-divider>\n <!-- Sort Direction Options -->\n <ax-button-item\n [text]=\"(t('actions.sort-ascending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'asc'\"\n (onClick)=\"vm.setSortDirection('asc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-up-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n <ax-button-item\n [text]=\"(t('actions.sort-descending', { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.sortDirection() === 'desc'\"\n (onClick)=\"vm.setSortDirection('desc')\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light fa-arrow-down-wide-short\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n <!-- View Mode Toggle -->\n <ax-button>\n <ax-icon icon=\"fa-light {{ selectedViewMode().icon }}\"></ax-icon>\n <ax-dropdown-panel>\n <ax-button-item-list>\n @for (item of viewsItems(); track item.key) {\n <!-- view mode items -->\n <ax-button-item\n [text]=\"(t('view-modes.' + item.key, { scope: rootConfig.config.i18n }) | async)!\"\n [selected]=\"vm.isViewMode(item.key)\"\n (onClick)=\"vm.setViewMode(item.key)\"\n >\n <ax-prefix>\n <ax-icon icon=\"fa-light {{ item.icon }}\"></ax-icon>\n </ax-prefix>\n </ax-button-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n <!-- end of view mode items -->\n }\n </ax-button-item-list>\n </ax-dropdown-panel>\n </ax-button>\n\n @if (deviceService.isLarge()) {\n <!-- Detail Panel Toggle -->\n <ax-button (onClick)=\"vm.toggleDetailPanel()\">\n <ax-icon\n icon=\"{{ vm.isDetailPanelOpen() ? 'fa-solid fa-square-info' : 'fa-light fa-square-info' }}\"\n ></ax-icon>\n </ax-button>\n }\n </axp-layout-suffix>\n </div>\n </axp-page-toolbar>\n\n <!-- Content Section -->\n <axp-page-content class=\"flex min-w-0 flex-col overflow-x-hidden overflow-y-auto\">\n <div class=\"flex min-h-0 min-w-0 flex-1 flex-row gap-4 overflow-hidden\">\n <axm-document-explorer [selectionMode]=\"selectionMode()\"></axm-document-explorer>\n @if (vm.isDetailPanelOpen() && deviceService.isLarge()) {\n <axm-document-explorer-detail-panel class=\"sticky top-0 z-50 h-full w-80 shrink-0\"></axm-document-explorer-detail-panel>\n }\n </div>\n </axp-page-content>\n\n <!-- Footer Section removed: breadcrumbs are now provided via page-level breadcrumbs -->\n</axp-page-layout>\n", styles: ["/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"] }]
8273
8905
  }], propDecorators: { documentExplorer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXMDocumentExplorerComponent), { isSignal: true }] }], handleCtrlKey: [{
8274
8906
  type: HostListener,
8275
8907
  args: ['document:keydown.control', ['$event']]
@@ -8287,5 +8919,5 @@ var drive_component = /*#__PURE__*/Object.freeze({
8287
8919
  * Generated bundle index. Do not edit.
8288
8920
  */
8289
8921
 
8290
- export { AXPDocumentExplorerViewModel as A, AXM_DOCUMENT_EXPIRATION_STATUS as B, AXM_DOCUMENT_EXPIRATION_STATUS_DEFINITION_KEY as C, AXPDocumentManagementService as D, AXPDocumentManagementSettingProvider as E, AXmFileTypeExtensionWidget as F, DM_AUDIO_EXTENSION_ICONS as G, DM_DOCUMENT_EXTENSION_ICONS as H, DM_FILE_EXTENSION_ICONS as I, DM_FILE_TYPE_ICONS as J, DM_VIDEO_EXTENSION_ICONS as K, DOCUMENT_DRIVE_PAGE_COMPONENT_KEY as L, buildDocumentManagementFileTypeCatalog as M, documentPlugin as N, resolveDocumentExpirationBadge as O, resolveDocumentVersionNumber as P, resolveFolderExpirationCountBadges as Q, ScopedDriveService as S, AXMDocumentExpirationBadgeComponent as a, AXMDocumentVersionBadgeComponent as b, AXMFolderExpirationBadgesComponent as c, AXMDocumentManagerService as d, AXMDocumentDialogService as e, buildFileChooserOptionsFromDocumentType as f, AXMDocumentExplorerComponent as g, AXMFolderPathBreadcrumbsComponent as h, AXMDocumentDriveComponent as i, AXMDocumentDrivePageComponent as j, AXMDocumentDrivePageComponentProvider as k, AXMDocumentExpirationStatusProvider as l, AXMDocumentManagementApiService as m, AXMDocumentManagementFileTypeProvider as n, AXMDocumentManagementModule as o, AXMDocumentManagerServiceImpl as p, AXMFileTypeExtensionWidgetColumnComponent as q, AXMFileTypeExtensionWidgetDesignerComponent as r, AXMFileTypeExtensionWidgetEditComponent as s, AXMFileTypeExtensionWidgetViewComponent as t, AXMFileTypeModule as u, AXMMenuProvider as v, AXMSearchCommandProvider as w, AXM_DOCUMENT_ATTACHMENT_DIALOG_ON_ACTION_HOOK_KEY as x, AXM_DOCUMENT_DIALOG_SURFACE_ATTACHMENT as y, AXM_DOCUMENT_DIALOG_SURFACE_ATTACHMENT_NO_SAVE as z };
8291
- //# sourceMappingURL=acorex-platform-module-document-management-client-acorex-platform-module-document-management-client--0oIEHPI.mjs.map
8922
+ export { AXPDocumentExplorerViewModel as A, AXMFileTypeModule as B, AXMMenuProvider as C, AXMSearchCommandProvider as D, AXM_DOCUMENT_ATTACHMENT_DIALOG_ON_ACTION_HOOK_KEY as E, AXM_DOCUMENT_DIALOG_SURFACE_ATTACHMENT as F, AXM_DOCUMENT_DIALOG_SURFACE_ATTACHMENT_NO_SAVE as G, AXM_DOCUMENT_EXPIRATION_STATUS as H, AXM_DOCUMENT_EXPIRATION_STATUS_DEFINITION_KEY as I, AXPDocumentManagementService as J, AXPDocumentManagementSettingProvider as K, AXmFileTypeExtensionWidget as L, DM_AUDIO_EXTENSION_ICONS as M, DM_DOCUMENT_EXTENSION_ICONS as N, DM_FILE_EXTENSION_ICONS as O, DM_FILE_TYPE_ICONS as P, DM_VIDEO_EXTENSION_ICONS as Q, DOCUMENT_DRIVE_PAGE_COMPONENT_KEY as R, ScopedDriveService as S, buildDocumentManagementFileTypeCatalog as T, documentPlugin as U, resolveDocumentExpirationBadge as V, resolveDocumentVersionNumber as W, resolveFolderExpirationCountBadges as X, AXMDocumentExpirationBadgeComponent as a, AXMDocumentVersionBadgeComponent as b, AXMFolderExpirationBadgesComponent as c, collectFolderScopedMetaDataList as d, collectDocumentScopedMetaDataList as e, flattenMetaDataColumns as f, collectDocumentTypeIds as g, collectDocumentTypeNames as h, AXMDocumentManagerService as i, AXMDocumentDialogService as j, buildFileChooserOptionsFromDocumentType as k, AXMDocumentExplorerComponent as l, AXMFolderPathBreadcrumbsComponent as m, AXMDocumentDriveComponent as n, AXMDocumentDrivePageComponent as o, AXMDocumentDrivePageComponentProvider as p, AXMDocumentExpirationStatusProvider as q, readNodeMetaDataValue as r, AXMDocumentManagementApiService as s, AXMDocumentManagementFileTypeProvider as t, AXMDocumentManagementModule as u, AXMDocumentManagerServiceImpl as v, AXMFileTypeExtensionWidgetColumnComponent as w, AXMFileTypeExtensionWidgetDesignerComponent as x, AXMFileTypeExtensionWidgetEditComponent as y, AXMFileTypeExtensionWidgetViewComponent as z };
8923
+ //# sourceMappingURL=acorex-platform-module-document-management-client-acorex-platform-module-document-management-client-qhcOFKFu.mjs.map