@acorex-platform/framework-client 0.0.10 → 0.0.14
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.
- package/fesm2022/acorex-platform-framework-client-auth.mjs +285 -50
- package/fesm2022/acorex-platform-framework-client-auth.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs → acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs} +55 -36
- package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs +29 -0
- package/fesm2022/acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-common.mjs +1576 -408
- package/fesm2022/acorex-platform-framework-client-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-core.mjs +561 -25
- package/fesm2022/acorex-platform-framework-client-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-builder.mjs +154 -42
- package/fesm2022/acorex-platform-framework-client-layout-builder.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CWVU3wXL.mjs → acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs} +7 -7
- package/fesm2022/acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CjnQ9hAJ.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs +77 -0
- package/fesm2022/acorex-platform-framework-client-layout-components-file-provider-picker.popup.component-fFen8w8M.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-components.mjs +2378 -1274
- package/fesm2022/acorex-platform-framework-client-layout-components.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-designer.mjs +92 -84
- package/fesm2022/acorex-platform-framework-client-layout-designer.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-CxBxxpmA.mjs → acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs} +3 -3
- package/fesm2022/{acorex-platform-framework-client-layout-entity-attachments-page.component-CxBxxpmA.mjs.map → acorex-platform-framework-client-layout-entity-attachments-page.component-BzUM-JMC.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-entity-file-list-popup.component-l0JAHKIH.mjs → acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs} +6 -6
- package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-Ci_CTFtq.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs +256 -0
- package/fesm2022/acorex-platform-framework-client-layout-entity-gallery-page.component-DmiB__JR.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-entity.mjs +17599 -17114
- package/fesm2022/acorex-platform-framework-client-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-views.mjs +120 -70
- package/fesm2022/acorex-platform-framework-client-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs +302 -263
- package/fesm2022/acorex-platform-framework-client-layout-widget-core.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CpkWwygb.mjs → acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs} +2 -2
- package/fesm2022/acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CIwpAXbL.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-image-preview.popup-C_EPAvCU.mjs → acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs} +3 -3
- package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-CazpERbX.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-CmtTq2Mt.mjs → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs} +5 -5
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-page-widget-designer.component-CmtTq2Mt.mjs.map → acorex-platform-framework-client-layout-widgets-page-widget-designer.component-DKkJi40s.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DSx0E3NV.mjs → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs} +3 -3
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DSx0E3NV.mjs.map → acorex-platform-framework-client-layout-widgets-repeater-widget-column.component-DtYZfA79.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-DdfcGV1C.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs} +10 -10
- package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-nMUtxAyy.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-CntopmDS.mjs → acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs} +5 -5
- package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-DvUSZ4hJ.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs +61 -0
- package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-BihIfkZW.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs +2218 -1504
- package/fesm2022/acorex-platform-framework-client-layout-widgets.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-realtime.mjs +227 -0
- package/fesm2022/acorex-platform-framework-client-realtime.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-runtime.mjs +201 -13
- package/fesm2022/acorex-platform-framework-client-runtime.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs +158 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-QIFX11dh.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs +119 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BBdellyL.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-default-entity-master-single-view.component-D1a7UI71.mjs → acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs} +5 -6
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-CIf1VWNW.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs +48 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-C_czT_JC.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs +42 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-C2Wu0YtF.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs +19 -0
- package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DRz-kVsT.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs +123 -96
- package/fesm2022/acorex-platform-framework-client-themes-default.mjs.map +1 -1
- package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CXSGiTCK.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs} +3 -3
- package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-column.component-Ci_oH7NE.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BY5clQ1J.mjs → acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs} +3 -3
- package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-view.component-Lb1G2Xz7.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-shared-settings.provider-DEL2YOTP.mjs → acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs} +11 -2
- package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-D2XPkc71.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BXl8u4Yp.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs} +7 -7
- package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-D4ubvFYf.mjs.map +1 -0
- package/fesm2022/{acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-i2sOOkVj.mjs → acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs} +7 -7
- package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-Br8j_BF_.mjs.map +1 -0
- package/fesm2022/acorex-platform-framework-client-themes-shared.mjs +124 -112
- package/fesm2022/acorex-platform-framework-client-themes-shared.mjs.map +1 -1
- package/fesm2022/acorex-platform-framework-client-workflow.mjs +26 -483
- package/fesm2022/acorex-platform-framework-client-workflow.mjs.map +1 -1
- package/package.json +14 -9
- package/types/acorex-platform-framework-client-auth.d.ts +76 -5
- package/types/acorex-platform-framework-client-common.d.ts +499 -129
- package/types/acorex-platform-framework-client-core.d.ts +291 -10
- package/types/acorex-platform-framework-client-layout-builder.d.ts +81 -31
- package/types/acorex-platform-framework-client-layout-components.d.ts +295 -41
- package/types/acorex-platform-framework-client-layout-entity.d.ts +1895 -1743
- package/types/acorex-platform-framework-client-layout-views.d.ts +8 -18
- package/types/acorex-platform-framework-client-layout-widget-core.d.ts +20 -35
- package/types/acorex-platform-framework-client-layout-widgets.d.ts +167 -33
- package/types/acorex-platform-framework-client-realtime.d.ts +100 -0
- package/types/acorex-platform-framework-client-runtime.d.ts +60 -2
- package/types/acorex-platform-framework-client-themes-default.d.ts +4 -48
- package/types/acorex-platform-framework-client-workflow.d.ts +16 -127
- package/fesm2022/acorex-platform-framework-client-common-common-settings.provider-CbzOYCnI.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-components-binding-expression-editor-popup.component-CWVU3wXL.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-entity-file-list-popup.component-l0JAHKIH.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-button-widget-designer.component-CpkWwygb.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-image-preview.popup-C_EPAvCU.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-edit-popup.component-DdfcGV1C.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-tabular-data-view-popup.component-CntopmDS.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-B5kSWxGk.mjs +0 -34
- package/fesm2022/acorex-platform-framework-client-layout-widgets-text-block-widget-designer.component-B5kSWxGk.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DnTHwsDJ.mjs +0 -160
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-create-view.component-DnTHwsDJ.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BpR9g6QS.mjs +0 -121
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-modify-view.component-BpR9g6QS.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-entity-master-single-view.component-D1a7UI71.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-D--_MIar.mjs +0 -48
- package/fesm2022/acorex-platform-framework-client-themes-default-error-401.component-D--_MIar.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-Byyqk8pH.mjs +0 -42
- package/fesm2022/acorex-platform-framework-client-themes-default-error-404.component-Byyqk8pH.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DR6G8gPC.mjs +0 -19
- package/fesm2022/acorex-platform-framework-client-themes-default-error-offline.component-DR6G8gPC.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-column.component-CXSGiTCK.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared-icon-chooser-view.component-BY5clQ1J.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared-settings.provider-DEL2YOTP.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-column.component-BXl8u4Yp.mjs.map +0 -1
- package/fesm2022/acorex-platform-framework-client-themes-shared-theme-color-chooser-view.component-i2sOOkVj.mjs.map +0 -1
|
@@ -2,13 +2,13 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { InjectionToken, inject, Injectable, Injector, signal, DestroyRef, makeEnvironmentProviders, NgModule, computed, input, output, ViewEncapsulation, ChangeDetectionStrategy, Component, viewChild, effect, untracked, ErrorHandler, EventEmitter, Input, Output, Directive, Inject, runInInjectionContext, model, linkedSignal, afterNextRender } from '@angular/core';
|
|
3
3
|
import { Router, NavigationEnd, NavigationStart, ROUTES, RedirectCommand, RouterModule } from '@angular/router';
|
|
4
4
|
import { AXPSessionService, AXPSessionStatus, AXPAuthGuard } from '@acorex-platform/framework-client/auth';
|
|
5
|
-
import { combineLatest, map, distinctUntilChanged, Subject, ReplaySubject, firstValueFrom, filter, take, merge as merge$1, first, switchMap, from } from 'rxjs';
|
|
5
|
+
import { combineLatest, map, distinctUntilChanged, Subject, ReplaySubject, firstValueFrom, filter, take, merge as merge$1, first, switchMap, from, debounceTime } from 'rxjs';
|
|
6
6
|
import { unwrapValueProperty, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToBoolean, coerceUnknownToTrimmedString, AXPPlatformScope, AXPRegionalSetting, AXPWidgetsCatalog, AXPKeyboardShortcutPriority, AXPSystemActionType, isLocaleStringMap } from '@acorex-platform/framework-shared/core';
|
|
7
7
|
import * as i3$1 from '@acorex-platform/framework-client/core';
|
|
8
|
-
import { AXPDebugService, AXPBroadcastEventService, objectKeyValueTransforms, AXPDataGenerator, AXPKeyboardShortcutRegistry, normalizeKeyboardShortcuts, AXPDeviceService, chordToKbdItemKeys, hasForegroundOverlayLayer, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPModuleManifestModule, AXPComponentSlotModule, AXPAppStartUpProvider, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXPHookService } from '@acorex-platform/framework-client/core';
|
|
8
|
+
import { AXPDebugService, AXPBroadcastEventService, AXP_SETTINGS_DEFINITION_DIALOG_OPENER, objectKeyValueTransforms, AXPDataGenerator, AXPKeyboardShortcutRegistry, normalizeKeyboardShortcuts, AXPDeviceService, chordToKbdItemKeys, hasForegroundOverlayLayer, AXPExpressionEvaluatorService, AXPContextEvalFactory, AXPModuleManifestModule, AXPComponentSlotModule, AXPAppStartUpProvider, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_LOGO_IMAGE_SRC_RESOLVER, AXPHookService } from '@acorex-platform/framework-client/core';
|
|
9
9
|
export { AXPDebugService } from '@acorex-platform/framework-client/core';
|
|
10
|
-
import { merge, sortBy, isString, toString, defaultTo, isEmpty, cloneDeep, get, isNumber, isNil, isObject, isPlainObject, omit } from 'lodash-es';
|
|
11
|
-
import { AXPQueryService, AXPCommandService,
|
|
10
|
+
import { merge, sortBy, isString, toString, defaultTo, isEmpty, cloneDeep, get, isNumber, isNil, isObject, isPlainObject, omit, uniq } from 'lodash-es';
|
|
11
|
+
import { AXPQueryService, AXPCommandService, provideCommandSetups } from '@acorex-platform/framework-client/runtime';
|
|
12
12
|
import Dexie from 'dexie';
|
|
13
13
|
import { AXCalendarService, AXDateTimeModule } from '@acorex/core/date-time';
|
|
14
14
|
import { AXDialogService } from '@acorex/components/dialog';
|
|
@@ -26,17 +26,18 @@ import { AXButtonModule } from '@acorex/components/button';
|
|
|
26
26
|
import * as i3 from '@acorex/components/progress-bar';
|
|
27
27
|
import { AXProgressBarModule } from '@acorex/components/progress-bar';
|
|
28
28
|
import { filter as filter$1 } from 'rxjs/operators';
|
|
29
|
-
import * as i4$2 from '@acorex-platform/framework-client/workflow';
|
|
30
|
-
import { AXPWorkflowService, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowError, AXPWorkflowModule } from '@acorex-platform/framework-client/workflow';
|
|
31
29
|
import { signalStore, withState, withMethods, patchState, withHooks } from '@ngrx/signals';
|
|
32
30
|
import { AXPopupService, AXPopupModule } from '@acorex/components/popup';
|
|
33
|
-
import {
|
|
31
|
+
import { AXToastModule, AXToastService } from '@acorex/components/toast';
|
|
34
32
|
import * as i2$1 from '@acorex/core/format';
|
|
35
33
|
import { AXFormatService } from '@acorex/core/format';
|
|
34
|
+
import { HttpErrorResponse } from '@angular/common/http';
|
|
36
35
|
import { AXKBDComponent, AXKBDItemComponent } from '@acorex/components/kbd';
|
|
37
36
|
import { AXDataSource } from '@acorex/cdk/common';
|
|
38
37
|
import { normalizeEntityDisplayTemplate, sanitizeResolvedEntityDisplayTitle, resolveEntityModifyRecordTitleTemplate, isMeaningfulEntityDisplayTitle, isUnresolvedEntityDisplayTemplate, ENTITY_ROW_POPUP_TITLE_OPTION, ENTITY_ROW_TITLE_TEMPLATE_OPTION, ENTITY_LAYOUT_SINGLE_TITLE_PATH, buildEntitySearchTitleContext, resolveEntityRowTitleTemplate } from '@acorex-platform/framework-shared/entity';
|
|
39
|
-
import
|
|
38
|
+
import * as i1$1 from '@acorex/core/file';
|
|
39
|
+
import { getFileExtension, resolveFileTypeExtension, resolveFileTypeOpen, runFileTypeOpen, AX_FILE_TYPE_METADATA_PURPOSE, getFileTypePurposes, AXFileTypeRegistryService, AXFileModule } from '@acorex/core/file';
|
|
40
|
+
export { AX_FILE_TYPE_METADATA_PURPOSE, filterFileTypesByPurpose, getFileTypePurposes } from '@acorex/core/file';
|
|
40
41
|
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
41
42
|
import * as i6 from '@acorex/components/color-box';
|
|
42
43
|
import { AXColorBoxModule } from '@acorex/components/color-box';
|
|
@@ -46,8 +47,10 @@ import * as i2$2 from '@acorex/components/number-box';
|
|
|
46
47
|
import { AXNumberBoxModule } from '@acorex/components/number-box';
|
|
47
48
|
import { AXBasePageComponent } from '@acorex/components/page';
|
|
48
49
|
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
49
|
-
import * as i1$
|
|
50
|
+
import * as i1$2 from '@angular/forms';
|
|
50
51
|
import { FormsModule } from '@angular/forms';
|
|
52
|
+
import { defineCommand, AXP_COMMAND_DEFINITION_CATEGORY_PLATFORM } from '@acorex-platform/framework-shared/runtime';
|
|
53
|
+
import { createWorkFlowEvent } from '@acorex-platform/framework-client/workflow';
|
|
51
54
|
|
|
52
55
|
//#region ---- Datasource keys ----
|
|
53
56
|
/** Platform common datasource registry names. */
|
|
@@ -372,6 +375,29 @@ const AXP_HOME_PAGE_DEFAULT_KEY = new InjectionToken('AXP_HOME_PAGE_DEFAULT_KEY'
|
|
|
372
375
|
factory: () => 'home'
|
|
373
376
|
});
|
|
374
377
|
|
|
378
|
+
/** Strict descendants allowed to override a setting owned at `scope`. */
|
|
379
|
+
const AXP_SETTING_SCOPE_DESCENDANTS = {
|
|
380
|
+
P: ['T', 'U'],
|
|
381
|
+
T: ['U'],
|
|
382
|
+
U: [],
|
|
383
|
+
};
|
|
384
|
+
function normalizeOverridableAt(ownerScope, overridableAt) {
|
|
385
|
+
const scopes = overridableAt ?? [];
|
|
386
|
+
const allowed = AXP_SETTING_SCOPE_DESCENDANTS[ownerScope];
|
|
387
|
+
for (const scope of scopes) {
|
|
388
|
+
if (!allowed.includes(scope)) {
|
|
389
|
+
throw new Error(`Setting at scope "${ownerScope}" cannot be overridable at "${scope}". Allowed: [${allowed.join(', ')}].`);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return scopes;
|
|
393
|
+
}
|
|
394
|
+
function isSettingVisibleOnScope(setting, pageScope) {
|
|
395
|
+
if (setting.scope === pageScope) {
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
return (setting.overridableAt ?? []).includes(pageScope);
|
|
399
|
+
}
|
|
400
|
+
|
|
375
401
|
var AXPCommonSettings;
|
|
376
402
|
(function (AXPCommonSettings) {
|
|
377
403
|
AXPCommonSettings["EnableOperationToasts"] = "Common:Setting:Notifications.EnableOperationToasts";
|
|
@@ -387,6 +413,8 @@ var AXPCommonSettings;
|
|
|
387
413
|
AXPCommonSettings["EntityListPersistenceMode"] = "Common:Setting:Entity.ListPersistenceMode";
|
|
388
414
|
AXPCommonSettings["NavigationMode"] = "Common:Setting:Navigation.Mode";
|
|
389
415
|
AXPCommonSettings["MaxOpenTabs"] = "Common:Setting:Navigation.MaxOpenTabs";
|
|
416
|
+
/** When true with entity list quick-search input, filters emit {@link AXP_QUERY_QUICK_SEARCH_FIELD} instead of inline OR. */
|
|
417
|
+
AXPCommonSettings["QuickSearchEnabled"] = "Common:Setting:Entity.QuickSearchEnabled";
|
|
390
418
|
})(AXPCommonSettings || (AXPCommonSettings = {}));
|
|
391
419
|
|
|
392
420
|
class AXPSettingDefinitionProviderContext {
|
|
@@ -478,6 +506,7 @@ class AXPSettingDefinitionSectionBuilder {
|
|
|
478
506
|
this.section = section;
|
|
479
507
|
}
|
|
480
508
|
addSetting(setting) {
|
|
509
|
+
const scope = setting.scope ?? 'P';
|
|
481
510
|
const newSetting = {
|
|
482
511
|
name: setting.key,
|
|
483
512
|
title: setting.title,
|
|
@@ -485,10 +514,11 @@ class AXPSettingDefinitionSectionBuilder {
|
|
|
485
514
|
searchTagKeys: setting.searchTagKeys,
|
|
486
515
|
isRequired: setting.isRequired ?? false,
|
|
487
516
|
isInherited: setting.isInherited ?? false,
|
|
517
|
+
overridableAt: normalizeOverridableAt(scope, setting.overridableAt),
|
|
488
518
|
isEncrypted: setting.isEncrypted ?? false,
|
|
489
519
|
requiresPageRefresh: setting.requiresPageRefresh ?? false,
|
|
490
520
|
defaultValue: setting.defaultValue,
|
|
491
|
-
scope
|
|
521
|
+
scope,
|
|
492
522
|
layout: setting.widget.layout,
|
|
493
523
|
widget: {
|
|
494
524
|
type: setting.widget.type,
|
|
@@ -506,6 +536,13 @@ class AXPSettingDefinitionSectionBuilder {
|
|
|
506
536
|
this.section.settings.push(newSetting);
|
|
507
537
|
return this;
|
|
508
538
|
}
|
|
539
|
+
addAction(action) {
|
|
540
|
+
if (!this.section.actions) {
|
|
541
|
+
this.section.actions = [];
|
|
542
|
+
}
|
|
543
|
+
this.section.actions.push(action);
|
|
544
|
+
return this;
|
|
545
|
+
}
|
|
509
546
|
endSection() {
|
|
510
547
|
return this.groupBuilder;
|
|
511
548
|
}
|
|
@@ -517,28 +554,48 @@ class AXPSettingDefinitionProviderService {
|
|
|
517
554
|
constructor() {
|
|
518
555
|
this.providers = inject(AXP_SETTING_DEFINITION_PROVIDER, { optional: true });
|
|
519
556
|
this.cache = null;
|
|
557
|
+
this.loadPromise = null;
|
|
520
558
|
}
|
|
521
559
|
async load() {
|
|
560
|
+
if (this.cache) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (!this.loadPromise) {
|
|
564
|
+
this.loadPromise = this.loadDefinitions().finally(() => {
|
|
565
|
+
this.loadPromise = null;
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
await this.loadPromise;
|
|
569
|
+
}
|
|
570
|
+
async loadDefinitions() {
|
|
522
571
|
if (this.cache) {
|
|
523
572
|
return;
|
|
524
573
|
}
|
|
525
574
|
const context = new AXPSettingDefinitionProviderContext();
|
|
526
|
-
// Load providers from DI tokens
|
|
527
|
-
|
|
528
|
-
|
|
575
|
+
// Load providers from DI tokens — isolate failures so one provider cannot block bootstrap.
|
|
576
|
+
const providerList = this.normalizeProviders(this.providers);
|
|
577
|
+
for (const provider of providerList) {
|
|
578
|
+
try {
|
|
529
579
|
if (provider instanceof Promise) {
|
|
530
|
-
// If provider is a promise, resolve it
|
|
531
580
|
const resolvedProvider = await provider;
|
|
532
581
|
await resolvedProvider.provide(context);
|
|
533
582
|
}
|
|
534
583
|
else {
|
|
535
|
-
// If provider is a direct instance, use it directly
|
|
536
584
|
await provider.provide(context);
|
|
537
585
|
}
|
|
538
586
|
}
|
|
587
|
+
catch (error) {
|
|
588
|
+
console.warn('Setting definition provider failed; continuing with remaining providers', error);
|
|
589
|
+
}
|
|
539
590
|
}
|
|
540
591
|
this.cache = context.getGroups();
|
|
541
592
|
}
|
|
593
|
+
normalizeProviders(providers) {
|
|
594
|
+
if (!providers) {
|
|
595
|
+
return [];
|
|
596
|
+
}
|
|
597
|
+
return Array.isArray(providers) ? providers : [providers];
|
|
598
|
+
}
|
|
542
599
|
async reload() {
|
|
543
600
|
this.cache = null;
|
|
544
601
|
await this.load();
|
|
@@ -551,30 +608,14 @@ class AXPSettingDefinitionProviderService {
|
|
|
551
608
|
if (!this.cache) {
|
|
552
609
|
return [];
|
|
553
610
|
}
|
|
554
|
-
const scopeOrder = ['P', 'T', 'U']; // Scopes hierarchy in ascending order
|
|
555
611
|
const filterByScope = (groups, currentScope) => {
|
|
556
|
-
const currentScopeIndex = scopeOrder.indexOf(currentScope);
|
|
557
612
|
return groups
|
|
558
613
|
.map((group) => ({
|
|
559
614
|
...group,
|
|
560
615
|
sections: group.sections
|
|
561
616
|
.map((section) => ({
|
|
562
617
|
...section,
|
|
563
|
-
settings: section.settings.filter((setting) =>
|
|
564
|
-
const settingScopeIndex = scopeOrder.indexOf(setting.scope);
|
|
565
|
-
// Include settings where:
|
|
566
|
-
// 1. The scope matches the requested scope.
|
|
567
|
-
if (setting.scope === currentScope)
|
|
568
|
-
return true;
|
|
569
|
-
// 2. The setting scope is higher (closer to 'U') and is inherited.
|
|
570
|
-
if (setting.isInherited &&
|
|
571
|
-
settingScopeIndex > currentScopeIndex // Higher scope
|
|
572
|
-
) {
|
|
573
|
-
return true;
|
|
574
|
-
}
|
|
575
|
-
// 3. Exclude settings with a lower or irrelevant scope.
|
|
576
|
-
return false;
|
|
577
|
-
}),
|
|
618
|
+
settings: section.settings.filter((setting) => isSettingVisibleOnScope(setting, currentScope)),
|
|
578
619
|
}))
|
|
579
620
|
.filter((section) => section.settings.length > 0), // Keep only sections with settings
|
|
580
621
|
groups: filterByScope(group.groups, currentScope), // Recursively filter nested groups
|
|
@@ -664,6 +705,53 @@ class AXPSettingDefinitionProviderService {
|
|
|
664
705
|
findGroup(scope, groupName) {
|
|
665
706
|
return this.searchRecursive(this.getList(scope), groupName, []); // Initialize with an empty breadcrumb
|
|
666
707
|
}
|
|
708
|
+
async findSection(scope, sectionName, groupName) {
|
|
709
|
+
await this.load();
|
|
710
|
+
return this.searchSectionRecursive(this.getList(scope), sectionName, groupName);
|
|
711
|
+
}
|
|
712
|
+
async collectSettingsByKeys(scope, keys) {
|
|
713
|
+
if (!keys.length) {
|
|
714
|
+
return [];
|
|
715
|
+
}
|
|
716
|
+
await this.load();
|
|
717
|
+
const keySet = new Set(keys);
|
|
718
|
+
const found = new Map();
|
|
719
|
+
const walk = (groups) => {
|
|
720
|
+
for (const group of groups) {
|
|
721
|
+
for (const section of group.sections) {
|
|
722
|
+
for (const setting of section.settings) {
|
|
723
|
+
if (keySet.has(setting.name) && !found.has(setting.name)) {
|
|
724
|
+
found.set(setting.name, setting);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
walk(group.groups);
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
walk(this.getList(scope));
|
|
732
|
+
return keys.map((key) => found.get(key)).filter((setting) => !!setting);
|
|
733
|
+
}
|
|
734
|
+
searchSectionRecursive(groups, sectionName, groupName) {
|
|
735
|
+
for (const group of groups) {
|
|
736
|
+
if (groupName && group.name !== groupName) {
|
|
737
|
+
const nested = this.searchSectionRecursive(group.groups, sectionName, groupName);
|
|
738
|
+
if (nested) {
|
|
739
|
+
return nested;
|
|
740
|
+
}
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
for (const section of group.sections) {
|
|
744
|
+
if (section.name === sectionName) {
|
|
745
|
+
return { group, section };
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
const nested = this.searchSectionRecursive(group.groups, sectionName, groupName);
|
|
749
|
+
if (nested) {
|
|
750
|
+
return nested;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
667
755
|
searchRecursive(groups, groupName, breadcrumb) {
|
|
668
756
|
for (const group of groups) {
|
|
669
757
|
const currentBreadcrumb = [
|
|
@@ -807,7 +895,6 @@ function coerceAXPSettingRawValue(raw, kind) {
|
|
|
807
895
|
//#endregion
|
|
808
896
|
|
|
809
897
|
const AXP_SETTINGS_SYNC_KEYS = new InjectionToken('AXP_SETTINGS_SYNC_KEYS');
|
|
810
|
-
//#endregion
|
|
811
898
|
|
|
812
899
|
//#region ---- Settings bulk sync (query + command) ----
|
|
813
900
|
class AXPSettingsBulkSyncService {
|
|
@@ -888,9 +975,13 @@ function traceSettingsLocalPersist(scope, payload) {
|
|
|
888
975
|
keys: payload.keys,
|
|
889
976
|
dirtyKeyCount: payload.dirtyKeyCount,
|
|
890
977
|
flush: payload.flush,
|
|
891
|
-
note:
|
|
892
|
-
?
|
|
893
|
-
|
|
978
|
+
note: scope === AXPPlatformScope.User
|
|
979
|
+
? payload.flush
|
|
980
|
+
? 'IndexedDB updated — ServerSync flush runs immediately (flush: true)'
|
|
981
|
+
: 'IndexedDB updated — dirty keys queued; ServerSync runs after debounce'
|
|
982
|
+
: payload.flush
|
|
983
|
+
? 'In-memory snapshot updated — ServerSync flush runs immediately (flush: true)'
|
|
984
|
+
: 'In-memory snapshot updated — dirty keys queued; ServerSync runs after debounce',
|
|
894
985
|
}));
|
|
895
986
|
}
|
|
896
987
|
//#endregion
|
|
@@ -1040,9 +1131,20 @@ function createEmptyScopedSettingsSnapshot(id, scope) {
|
|
|
1040
1131
|
retryAttempt: 0,
|
|
1041
1132
|
};
|
|
1042
1133
|
}
|
|
1134
|
+
/** Only user-scoped settings are persisted in IndexedDB; platform/tenant stay in memory. */
|
|
1135
|
+
function shouldPersistSettingsInIndexedDb(scope) {
|
|
1136
|
+
return scope === AXPPlatformScope.User;
|
|
1137
|
+
}
|
|
1138
|
+
/** Removes legacy platform/tenant rows written before user-only IndexedDB persistence. */
|
|
1139
|
+
async function purgeNonUserScopedSettingsSnapshots() {
|
|
1140
|
+
await axpSettingsIndexedDb.scoped_snapshots
|
|
1141
|
+
.where('scope')
|
|
1142
|
+
.anyOf([AXPPlatformScope.Platform, AXPPlatformScope.Tenant])
|
|
1143
|
+
.delete();
|
|
1144
|
+
}
|
|
1043
1145
|
//#endregion
|
|
1044
1146
|
|
|
1045
|
-
//#region ----
|
|
1147
|
+
//#region ---- Scoped settings provider (IndexedDB for user scope only) ----
|
|
1046
1148
|
class AXPIndexedDbSettingValueProvider {
|
|
1047
1149
|
constructor(_scope, injector) {
|
|
1048
1150
|
this._scope = _scope;
|
|
@@ -1075,7 +1177,9 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1075
1177
|
return;
|
|
1076
1178
|
}
|
|
1077
1179
|
if (status === AXPSessionStatus.Authorized || status === AXPSessionStatus.Authenticated) {
|
|
1078
|
-
this.
|
|
1180
|
+
if (this.canSyncScopeWithServer()) {
|
|
1181
|
+
this.tryBindSessionContext();
|
|
1182
|
+
}
|
|
1079
1183
|
}
|
|
1080
1184
|
});
|
|
1081
1185
|
if (this._scope === AXPPlatformScope.User) {
|
|
@@ -1160,7 +1264,7 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1160
1264
|
await this.revalidateNow();
|
|
1161
1265
|
}
|
|
1162
1266
|
async revalidateIfNeeded() {
|
|
1163
|
-
if (!this.snapshotId) {
|
|
1267
|
+
if (!this.snapshotId || !this.canSyncScopeWithServer()) {
|
|
1164
1268
|
return;
|
|
1165
1269
|
}
|
|
1166
1270
|
if (!this.snapshot) {
|
|
@@ -1184,13 +1288,15 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1184
1288
|
if (!expectedSnapshotId) {
|
|
1185
1289
|
return;
|
|
1186
1290
|
}
|
|
1187
|
-
const existing =
|
|
1291
|
+
const existing = shouldPersistSettingsInIndexedDb(this._scope)
|
|
1292
|
+
? await axpSettingsIndexedDb.scoped_snapshots.get(expectedSnapshotId)
|
|
1293
|
+
: undefined;
|
|
1188
1294
|
if (this.snapshotId !== expectedSnapshotId) {
|
|
1189
1295
|
return;
|
|
1190
1296
|
}
|
|
1191
1297
|
this.snapshot = existing ?? createEmptyScopedSettingsSnapshot(expectedSnapshotId, this._scope);
|
|
1192
1298
|
const needsInitialSync = isEmpty(this.snapshot.values);
|
|
1193
|
-
if (needsInitialSync || this.shouldRevalidate(this.snapshot)) {
|
|
1299
|
+
if (this.canSyncScopeWithServer() && (needsInitialSync || this.shouldRevalidate(this.snapshot))) {
|
|
1194
1300
|
await this.revalidateNow();
|
|
1195
1301
|
}
|
|
1196
1302
|
this.hydrated = true;
|
|
@@ -1237,6 +1343,9 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1237
1343
|
if (this._scope === AXPPlatformScope.Platform) {
|
|
1238
1344
|
return;
|
|
1239
1345
|
}
|
|
1346
|
+
if (!this.canSyncScopeWithServer()) {
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1240
1349
|
if (this._scope === AXPPlatformScope.User && (!this.sessionService.user?.id || !this.sessionService.tenant?.id)) {
|
|
1241
1350
|
return;
|
|
1242
1351
|
}
|
|
@@ -1269,12 +1378,24 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1269
1378
|
await this.persistSnapshotRecord(this.snapshot);
|
|
1270
1379
|
}
|
|
1271
1380
|
async persistSnapshotRecord(snapshot) {
|
|
1381
|
+
if (!shouldPersistSettingsInIndexedDb(snapshot.scope)) {
|
|
1382
|
+
return;
|
|
1383
|
+
}
|
|
1272
1384
|
await axpSettingsIndexedDb.scoped_snapshots.put(snapshot);
|
|
1273
1385
|
}
|
|
1274
1386
|
toSettingValues(values) {
|
|
1275
1387
|
return Object.entries(values).map(([key, value]) => ({ key, value }));
|
|
1276
1388
|
}
|
|
1277
1389
|
//#endregion
|
|
1390
|
+
//#region ---- Server sync eligibility ----
|
|
1391
|
+
/** Platform settings are public; tenant/user bulk sync requires a Bearer token. */
|
|
1392
|
+
canSyncScopeWithServer() {
|
|
1393
|
+
if (this._scope === AXPPlatformScope.Platform) {
|
|
1394
|
+
return true;
|
|
1395
|
+
}
|
|
1396
|
+
return Boolean(this.sessionService.getToken());
|
|
1397
|
+
}
|
|
1398
|
+
//#endregion
|
|
1278
1399
|
//#region ---- Revalidation ----
|
|
1279
1400
|
shouldRevalidate(record) {
|
|
1280
1401
|
const ttl = AXP_SETTINGS_SYNC_TTL_MS[this._scope];
|
|
@@ -1304,7 +1425,7 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1304
1425
|
}
|
|
1305
1426
|
async doRevalidate() {
|
|
1306
1427
|
const snapshot = this.snapshot;
|
|
1307
|
-
if (!snapshot) {
|
|
1428
|
+
if (!snapshot || !this.canSyncScopeWithServer()) {
|
|
1308
1429
|
return;
|
|
1309
1430
|
}
|
|
1310
1431
|
try {
|
|
@@ -1384,7 +1505,7 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1384
1505
|
}
|
|
1385
1506
|
async doFlush() {
|
|
1386
1507
|
const snapshot = this.snapshot;
|
|
1387
|
-
if (!snapshot || isEmpty(snapshot.dirty)) {
|
|
1508
|
+
if (!snapshot || isEmpty(snapshot.dirty) || !this.canSyncScopeWithServer()) {
|
|
1388
1509
|
return;
|
|
1389
1510
|
}
|
|
1390
1511
|
const payload = { ...snapshot.dirty };
|
|
@@ -1461,6 +1582,7 @@ class AXPIndexedDbSettingValueProvider {
|
|
|
1461
1582
|
|
|
1462
1583
|
//#region ---- Provider factories ----
|
|
1463
1584
|
function createIndexedDbSettingValueProviders(injector) {
|
|
1585
|
+
void purgeNonUserScopedSettingsSnapshots();
|
|
1464
1586
|
return [
|
|
1465
1587
|
new AXPIndexedDbSettingValueProvider(AXPPlatformScope.Platform, injector),
|
|
1466
1588
|
new AXPIndexedDbSettingValueProvider(AXPPlatformScope.Tenant, injector),
|
|
@@ -1589,6 +1711,9 @@ class AXPSettingsService {
|
|
|
1589
1711
|
this.clearScopedCache(AXPPlatformScope.User);
|
|
1590
1712
|
return;
|
|
1591
1713
|
}
|
|
1714
|
+
if (!this.shouldLoadProvider(AXPPlatformScope.User)) {
|
|
1715
|
+
return;
|
|
1716
|
+
}
|
|
1592
1717
|
await this.reload(AXPPlatformScope.User, 'session-user-changed');
|
|
1593
1718
|
});
|
|
1594
1719
|
this.sessionService.tenant$
|
|
@@ -1602,6 +1727,9 @@ class AXPSettingsService {
|
|
|
1602
1727
|
this.clearScopedCache(AXPPlatformScope.Tenant);
|
|
1603
1728
|
return;
|
|
1604
1729
|
}
|
|
1730
|
+
if (!this.shouldLoadProvider(AXPPlatformScope.Tenant)) {
|
|
1731
|
+
return;
|
|
1732
|
+
}
|
|
1605
1733
|
await this.reload(AXPPlatformScope.Tenant, 'session-tenant-changed');
|
|
1606
1734
|
});
|
|
1607
1735
|
if (typeof document !== 'undefined') {
|
|
@@ -1709,11 +1837,14 @@ class AXPSettingsService {
|
|
|
1709
1837
|
throw error;
|
|
1710
1838
|
}
|
|
1711
1839
|
}
|
|
1712
|
-
/** Platform always; tenant when
|
|
1840
|
+
/** Platform always; tenant/user only when a Bearer token is present. */
|
|
1713
1841
|
shouldLoadProvider(scope) {
|
|
1714
1842
|
if (scope === AXPPlatformScope.Platform) {
|
|
1715
1843
|
return true;
|
|
1716
1844
|
}
|
|
1845
|
+
if (!this.sessionService.getToken()) {
|
|
1846
|
+
return false;
|
|
1847
|
+
}
|
|
1717
1848
|
if (scope === AXPPlatformScope.Tenant) {
|
|
1718
1849
|
return !!this.sessionService.tenant?.id;
|
|
1719
1850
|
}
|
|
@@ -1754,6 +1885,24 @@ class AXPSettingsService {
|
|
|
1754
1885
|
}
|
|
1755
1886
|
return cloneDeep(effective);
|
|
1756
1887
|
}
|
|
1888
|
+
/**
|
|
1889
|
+
* Synchronous read from the in-memory scope cache (User → Tenant → Platform).
|
|
1890
|
+
* Returns `undefined` when the key is not cached yet (e.g. before {@link load} completes).
|
|
1891
|
+
*/
|
|
1892
|
+
peekCached(key) {
|
|
1893
|
+
const scopeOrder = [AXPPlatformScope.User, AXPPlatformScope.Tenant, AXPPlatformScope.Platform];
|
|
1894
|
+
for (const scope of scopeOrder) {
|
|
1895
|
+
const scopeCache = this.scopedSettingsCache.get(scope);
|
|
1896
|
+
if (!scopeCache?.has(key)) {
|
|
1897
|
+
continue;
|
|
1898
|
+
}
|
|
1899
|
+
const value = scopeCache.get(key);
|
|
1900
|
+
if (value !== undefined && value !== null) {
|
|
1901
|
+
return value;
|
|
1902
|
+
}
|
|
1903
|
+
}
|
|
1904
|
+
return undefined;
|
|
1905
|
+
}
|
|
1757
1906
|
/**
|
|
1758
1907
|
* Inherited settings at tenant/user scope may match the definition default while still being an explicit
|
|
1759
1908
|
* override of a different parent value (e.g. tenant enables lock while platform default is disabled).
|
|
@@ -1833,6 +1982,51 @@ class AXPSettingsService {
|
|
|
1833
1982
|
}
|
|
1834
1983
|
return new ScopedSettingService(this, provider, this.scopedSettingsCache.get(scope), (s) => this.shouldLoadProvider(s));
|
|
1835
1984
|
}
|
|
1985
|
+
/**
|
|
1986
|
+
* Opens a dialog to quick-edit a settings definition section using canonical widgets.
|
|
1987
|
+
*/
|
|
1988
|
+
async showSectionPopup(options) {
|
|
1989
|
+
const definitionService = this.injector.get(AXPSettingDefinitionProviderService);
|
|
1990
|
+
const lookup = await definitionService.findSection(options.scope, options.section, options.group);
|
|
1991
|
+
if (!lookup) {
|
|
1992
|
+
return false;
|
|
1993
|
+
}
|
|
1994
|
+
const opener = this.injector.get(AXP_SETTINGS_DEFINITION_DIALOG_OPENER);
|
|
1995
|
+
const { openSettingsDefinitionDialog } = await import('./acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs');
|
|
1996
|
+
return openSettingsDefinitionDialog(this, opener, {
|
|
1997
|
+
scope: options.scope,
|
|
1998
|
+
sections: [lookup.section],
|
|
1999
|
+
title: options.title ?? lookup.section.title,
|
|
2000
|
+
description: options.description ?? lookup.section.description,
|
|
2001
|
+
size: options.size,
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* Opens a dialog to quick-edit one or more settings by key using their canonical widget definitions.
|
|
2006
|
+
*/
|
|
2007
|
+
async showSettingsPopup(options) {
|
|
2008
|
+
const definitionService = this.injector.get(AXPSettingDefinitionProviderService);
|
|
2009
|
+
const settings = await definitionService.collectSettingsByKeys(options.scope, options.keys);
|
|
2010
|
+
if (!settings.length) {
|
|
2011
|
+
return false;
|
|
2012
|
+
}
|
|
2013
|
+
const opener = this.injector.get(AXP_SETTINGS_DEFINITION_DIALOG_OPENER);
|
|
2014
|
+
const { openSettingsDefinitionDialog } = await import('./acorex-platform-framework-client-common-settings-dialog.helper-DQNOCRL6.mjs');
|
|
2015
|
+
return openSettingsDefinitionDialog(this, opener, {
|
|
2016
|
+
scope: options.scope,
|
|
2017
|
+
sections: [
|
|
2018
|
+
{
|
|
2019
|
+
name: 'quick-edit',
|
|
2020
|
+
title: options.title ?? '@settings-management:module.menus.root.title',
|
|
2021
|
+
description: options.description,
|
|
2022
|
+
settings,
|
|
2023
|
+
},
|
|
2024
|
+
],
|
|
2025
|
+
title: options.title ?? '@settings-management:module.menus.root.title',
|
|
2026
|
+
description: options.description,
|
|
2027
|
+
size: options.size,
|
|
2028
|
+
});
|
|
2029
|
+
}
|
|
1836
2030
|
/** Applies remote values into the in-memory scope cache and notifies listeners. */
|
|
1837
2031
|
syncScopeCache(scope, values) {
|
|
1838
2032
|
const scopeCache = this.scopedSettingsCache.get(scope);
|
|
@@ -2580,6 +2774,8 @@ function createUnsavedChangesCanDeactivateGuard() {
|
|
|
2580
2774
|
}
|
|
2581
2775
|
//#endregion
|
|
2582
2776
|
|
|
2777
|
+
//#endregion
|
|
2778
|
+
|
|
2583
2779
|
var AXPHomePageSettings;
|
|
2584
2780
|
(function (AXPHomePageSettings) {
|
|
2585
2781
|
AXPHomePageSettings["UserHomePath"] = "Common:Setting:Startup.HomePage";
|
|
@@ -2730,6 +2926,17 @@ function provideDynamicHomePage() {
|
|
|
2730
2926
|
]);
|
|
2731
2927
|
}
|
|
2732
2928
|
|
|
2929
|
+
//#region ---- Experience settings group ----
|
|
2930
|
+
/** Root Settings nav group for startup, widgets, notifications, and entity UX preferences. */
|
|
2931
|
+
const AXP_EXPERIENCE_SETTINGS_GROUP = 'experience';
|
|
2932
|
+
const AXP_EXPERIENCE_SETTINGS_SECTIONS = {
|
|
2933
|
+
Startup: 'startup',
|
|
2934
|
+
Widgets: 'widgets',
|
|
2935
|
+
Notifications: 'notifications',
|
|
2936
|
+
Entity: 'entity',
|
|
2937
|
+
};
|
|
2938
|
+
//#endregion
|
|
2939
|
+
|
|
2733
2940
|
const I18N = '@general:settings';
|
|
2734
2941
|
class AXPHomePageSettingProvider {
|
|
2735
2942
|
constructor(injector) {
|
|
@@ -2742,16 +2949,14 @@ class AXPHomePageSettingProvider {
|
|
|
2742
2949
|
if (list.length === 0) {
|
|
2743
2950
|
return;
|
|
2744
2951
|
}
|
|
2745
|
-
// Define the 'General Settings' group
|
|
2746
2952
|
context
|
|
2747
|
-
.addGroup(
|
|
2748
|
-
|
|
2749
|
-
.addSection('startup', `${I18N}.general.startup.title`, `${I18N}.general.startup.description`)
|
|
2750
|
-
// Add the 'Home Page' setting
|
|
2953
|
+
.addGroup(AXP_EXPERIENCE_SETTINGS_GROUP, `${I18N}.experience.nav-title`, `${I18N}.experience.description`, 'fa-light fa-wand-magic-sparkles', `${I18N}.experience.title`, 1)
|
|
2954
|
+
.addSection(AXP_EXPERIENCE_SETTINGS_SECTIONS.Startup, `${I18N}.experience.startup.title`, `${I18N}.experience.startup.description`)
|
|
2751
2955
|
.addSetting({
|
|
2752
2956
|
key: AXPHomePageSettings.UserHomePath,
|
|
2753
|
-
title: `${I18N}.
|
|
2957
|
+
title: `${I18N}.experience.startup.home-page.title`,
|
|
2754
2958
|
scope: AXPPlatformScope.User,
|
|
2959
|
+
overridableAt: [],
|
|
2755
2960
|
isInherited: true,
|
|
2756
2961
|
defaultValue: this.defaultHomePageKey || list[0].id,
|
|
2757
2962
|
valueTransforms: objectKeyValueTransforms('id'),
|
|
@@ -2763,11 +2968,11 @@ class AXPHomePageSettingProvider {
|
|
|
2763
2968
|
dataSource: list,
|
|
2764
2969
|
},
|
|
2765
2970
|
},
|
|
2766
|
-
description: `${I18N}.
|
|
2971
|
+
description: `${I18N}.experience.startup.home-page.description`,
|
|
2767
2972
|
})
|
|
2768
|
-
// End the 'Startup' section
|
|
2769
2973
|
.endSection()
|
|
2770
|
-
|
|
2974
|
+
.addSection(AXP_EXPERIENCE_SETTINGS_SECTIONS.Widgets, `${I18N}.experience.widgets.title`, `${I18N}.experience.widgets.description`)
|
|
2975
|
+
.endSection()
|
|
2771
2976
|
.endGroup();
|
|
2772
2977
|
}
|
|
2773
2978
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPHomePageSettingProvider, deps: [{ token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
@@ -3687,11 +3892,11 @@ class AXPBackgroundOperationItemComponent {
|
|
|
3687
3892
|
return this.pendingAction() === action;
|
|
3688
3893
|
}
|
|
3689
3894
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3690
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationItemComponent, isStandalone: true, selector: "axp-background-operation-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionCompleted: "actionCompleted", itemClicked: "itemClicked" }, ngImport: i0, template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\"
|
|
3895
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationItemComponent, isStandalone: true, selector: "axp-background-operation-item", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { actionCompleted: "actionCompleted", itemClicked: "itemClicked" }, ngImport: i0, template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\">\n {{ data().statusText }}\n </p>\n }\n\n @if (data().currentStep) {\n <span class=\"operation-item__step\">\n {{\n '@general:background-operation.step' | translate | async\n }}\n {{ data().currentStep }}\n </span>\n }\n </div>\n\n @if (actions().length > 0) {\n <footer\n class=\"operation-item__actions\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (action of actions(); track action) {\n <ax-button\n class=\"ax-sm\"\n [look]=\"actionButtonLook(action)\"\n [color]=\"actionButtonColor(action)\"\n [text]=\"(actionLabelKey(action) | translate | async) ?? ''\"\n [disabled]=\"\n isActionDisabled(action) || isActionLoading(action)\n \"\n (onClick)=\"onAction(action)\"\n ></ax-button>\n }\n </footer>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <ax-progress-bar\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n }\n\n @if (showError()) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ data().error!.message }}\n </p>\n }\n </div>\n </div>\n </div>\n</article>\n", styles: ["@layer properties;axp-background-operation-item{display:block}.operation-item{position:relative;overflow:hidden;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s;border-color:rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item.--clickable{cursor:pointer}@media(hover:hover){.operation-item.--clickable:hover{border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}}.operation-item.--failed{border-color:rgb(var(--ax-sys-color-border-danger-surface))}.operation-item__body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.operation-item__header{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.operation-item__status-icon{margin-top:calc(var(--spacing, .25rem) * .5);flex-shrink:0;font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item__summary{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--spacing, .25rem)}.operation-item__title{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;text-align:start;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-on-surface))}.operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__meta-content{display:flex;min-width:0;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}.operation-item__status-text{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:start;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__error{margin:0;border-radius:var(--radius-md, .375rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);background:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.operation-item__actions{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--spacing, .25rem)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{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-duration: initial;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXProgressBarModule }, { kind: "component", type: i3.AXProgressBarComponent, selector: "ax-progress-bar", inputs: ["color", "mode", "progress", "height"], outputs: ["ValueChange", "sizeChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
3691
3896
|
}
|
|
3692
3897
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationItemComponent, decorators: [{
|
|
3693
3898
|
type: Component,
|
|
3694
|
-
args: [{ selector: 'axp-background-operation-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXButtonModule, AXDecoratorModule, AXProgressBarModule, AXTranslationModule], template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\"
|
|
3899
|
+
args: [{ selector: 'axp-background-operation-item', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXButtonModule, AXDecoratorModule, AXProgressBarModule, AXTranslationModule], template: "<article\n class=\"operation-item\"\n [class]=\"statusClass()\"\n [class.--clickable]=\"isClickable()\"\n (click)=\"onItemClick()\"\n>\n <div class=\"operation-item__body\">\n <div class=\"operation-item__header\">\n <ax-icon class=\"operation-item__status-icon\" [class]=\"statusClass()\">\n <i [class]=\"statusIcon()\"></i>\n </ax-icon>\n\n <div class=\"operation-item__summary\">\n <h3 class=\"operation-item__title\">{{ data().title }}</h3>\n\n @if (showMetaRow()) {\n <div class=\"operation-item__meta\">\n <div class=\"operation-item__meta-content\">\n @if (data().statusText) {\n <p class=\"operation-item__status-text\">\n {{ data().statusText }}\n </p>\n }\n\n @if (data().currentStep) {\n <span class=\"operation-item__step\">\n {{\n '@general:background-operation.step' | translate | async\n }}\n {{ data().currentStep }}\n </span>\n }\n </div>\n\n @if (actions().length > 0) {\n <footer\n class=\"operation-item__actions\"\n (click)=\"$event.stopPropagation()\"\n >\n @for (action of actions(); track action) {\n <ax-button\n class=\"ax-sm\"\n [look]=\"actionButtonLook(action)\"\n [color]=\"actionButtonColor(action)\"\n [text]=\"(actionLabelKey(action) | translate | async) ?? ''\"\n [disabled]=\"\n isActionDisabled(action) || isActionLoading(action)\n \"\n (onClick)=\"onAction(action)\"\n ></ax-button>\n }\n </footer>\n }\n </div>\n }\n\n @if (showProgressBar()) {\n <ax-progress-bar\n [progress]=\"progressValue()\"\n [mode]=\"progressMode()\"\n [color]=\"progressColor()\"\n [style.height.px]=\"4\"\n ></ax-progress-bar>\n }\n\n @if (showError()) {\n <p class=\"operation-item__error\" role=\"alert\">\n {{ data().error!.message }}\n </p>\n }\n </div>\n </div>\n </div>\n</article>\n", styles: ["@layer properties;axp-background-operation-item{display:block}.operation-item{position:relative;overflow:hidden;border-radius:var(--radius-md, .375rem);border-style:var(--tw-border-style);border-width:1px;transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease, var(--default-transition-timing-function, cubic-bezier(.4, 0, .2, 1)));transition-duration:var(--tw-duration, var(--default-transition-duration, .15s));--tw-duration: .2s;transition-duration:.2s;border-color:rgb(var(--ax-sys-color-border-lighter-surface));background:rgb(var(--ax-sys-color-lightest-surface))}.operation-item.--clickable{cursor:pointer}@media(hover:hover){.operation-item.--clickable:hover{border-color:rgb(var(--ax-sys-color-border-light-surface));background:rgb(var(--ax-sys-color-lighter-surface))}}.operation-item.--failed{border-color:rgb(var(--ax-sys-color-border-danger-surface))}.operation-item__body{display:flex;flex-direction:column;gap:calc(var(--spacing, .25rem) * 2);padding:calc(var(--spacing, .25rem) * 3)}.operation-item__header{display:flex;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.operation-item__status-icon{margin-top:calc(var(--spacing, .25rem) * .5);flex-shrink:0;font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__status-icon.--running{color:rgb(var(--ax-sys-color-primary-500))}.operation-item__status-icon.--paused{color:rgb(var(--ax-sys-color-warning-500))}.operation-item__status-icon.--completed{color:rgb(var(--ax-sys-color-success-500))}.operation-item__status-icon.--failed{color:rgb(var(--ax-sys-color-danger-500))}.operation-item__summary{display:flex;min-width:0;flex:1;flex-direction:column;gap:var(--spacing, .25rem)}.operation-item__title{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;text-align:start;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500);color:rgb(var(--ax-sys-color-on-surface))}.operation-item__meta{display:flex;align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 2)}.operation-item__meta-content{display:flex;min-width:0;flex:1;flex-direction:column;gap:calc(var(--spacing, .25rem) * .5)}.operation-item__status-text{margin:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;text-align:start;font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__step{display:inline-block;font-size:.6875rem;color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-item__error{margin:0;border-radius:var(--radius-md, .375rem);padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:var(--spacing, .25rem);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)));--tw-leading: var(--leading-relaxed, 1.625);line-height:var(--leading-relaxed, 1.625);background:rgb(var(--ax-sys-color-danger-lighter-surface));color:rgb(var(--ax-sys-color-on-danger-lighter-surface))}.operation-item__actions{display:flex;flex-shrink:0;flex-wrap:wrap;align-items:center;justify-content:flex-end;gap:var(--spacing, .25rem)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-duration{syntax: \"*\"; inherits: false;}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{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-duration: initial;--tw-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
|
|
3695
3900
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], actionCompleted: [{ type: i0.Output, args: ["actionCompleted"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }] } });
|
|
3696
3901
|
|
|
3697
3902
|
//#region ---- Imports ----
|
|
@@ -3728,11 +3933,11 @@ class AXPBackgroundOperationPanelComponent {
|
|
|
3728
3933
|
}), ...(ngDevMode ? [{ debugName: "visibleOperations" }] : /* istanbul ignore next */ []));
|
|
3729
3934
|
}
|
|
3730
3935
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3731
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationPanelComponent, isStandalone: true, selector: "axp-background-operation-panel", outputs: { onActiveCountChange: "onActiveCountChange", onClosePopover: "onClosePopover" }, ngImport: i0, template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"
|
|
3936
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationPanelComponent, isStandalone: true, selector: "axp-background-operation-panel", outputs: { onActiveCountChange: "onActiveCountChange", onClosePopover: "onClosePopover" }, ngImport: i0, template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"text-sm\">{{ '@general:background-operation.empty.all' | translate | async }}</span>\n </div>\n } @else {\n @for (operation of visibleOperations(); track operation.id) {\n <axp-background-operation-item\n [data]=\"operation\"\n (actionCompleted)=\"onActiveCountChange.emit(operationService.activeCount())\"\n (itemClicked)=\"onClosePopover.emit()\"\n ></axp-background-operation-item>\n }\n }\n </div>\n</div>\n", styles: ["@layer properties;axp-background-operation-panel{display:block}.operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.operation-panel__title{margin:0;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-on-surface))}.operation-panel__list{display:flex;max-height:50vh;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);overflow-y:auto;padding:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.operation-panel__list{width:32rem}}.operation-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 10);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-panel__empty i{font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));opacity:60%}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{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-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "component", type: AXPBackgroundOperationItemComponent, selector: "axp-background-operation-item", inputs: ["data"], outputs: ["actionCompleted", "itemClicked"] }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
3732
3937
|
}
|
|
3733
3938
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationPanelComponent, decorators: [{
|
|
3734
3939
|
type: Component,
|
|
3735
|
-
args: [{ selector: 'axp-background-operation-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXTranslationModule, AXPBackgroundOperationItemComponent], template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"
|
|
3940
|
+
args: [{ selector: 'axp-background-operation-panel', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXTranslationModule, AXPBackgroundOperationItemComponent], template: "<div class=\"operation-panel\">\n <header class=\"operation-panel__header\">\n <h2 class=\"operation-panel__title\">{{ '@general:background-operation.panel.title' | translate | async }}</h2>\n </header>\n\n <div class=\"operation-panel__list\">\n @if (visibleOperations().length === 0) {\n <div class=\"operation-panel__empty\">\n <i class=\"fa-regular fa-list-check\"></i>\n <span class=\"text-sm\">{{ '@general:background-operation.empty.all' | translate | async }}</span>\n </div>\n } @else {\n @for (operation of visibleOperations(); track operation.id) {\n <axp-background-operation-item\n [data]=\"operation\"\n (actionCompleted)=\"onActiveCountChange.emit(operationService.activeCount())\"\n (itemClicked)=\"onClosePopover.emit()\"\n ></axp-background-operation-item>\n }\n }\n </div>\n</div>\n", styles: ["@layer properties;axp-background-operation-panel{display:block}.operation-panel__header{display:flex;align-items:center;justify-content:space-between;border-bottom-style:var(--tw-border-style);border-bottom-width:1px;padding-inline:calc(var(--spacing, .25rem) * 4);padding-block:calc(var(--spacing, .25rem) * 3);border-color:rgb(var(--ax-sys-color-border-lightest-surface))}.operation-panel__title{margin:0;font-size:var(--text-base, 1rem);line-height:var(--tw-leading, var(--text-base--line-height, 1.5 ));--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgb(var(--ax-sys-color-on-surface))}.operation-panel__list{display:flex;max-height:50vh;flex-direction:column;gap:calc(var(--spacing, .25rem) * 3);overflow-y:auto;padding:calc(var(--spacing, .25rem) * 4)}@media(width>=48rem){.operation-panel__list{width:32rem}}.operation-panel__empty{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:calc(var(--spacing, .25rem) * 2);padding-inline:calc(var(--spacing, .25rem) * 6);padding-block:calc(var(--spacing, .25rem) * 10);color:rgb(var(--ax-sys-color-on-surface-variant))}.operation-panel__empty i{font-size:var(--text-2xl, 1.5rem);line-height:var(--tw-leading, var(--text-2xl--line-height, calc(2 / 1.5)));opacity:60%}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{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-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
|
|
3736
3941
|
}], propDecorators: { onActiveCountChange: [{ type: i0.Output, args: ["onActiveCountChange"] }], onClosePopover: [{ type: i0.Output, args: ["onClosePopover"] }] } });
|
|
3737
3942
|
|
|
3738
3943
|
//#region ---- Imports ----
|
|
@@ -3771,13 +3976,31 @@ class AXPBackgroundOperationSlotComponent {
|
|
|
3771
3976
|
this.popover()?.close();
|
|
3772
3977
|
}
|
|
3773
3978
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3774
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationSlotComponent, isStandalone: true, selector: "axp-background-operation-slot", viewQueries: [{ propertyName: "popover", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"
|
|
3979
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPBackgroundOperationSlotComponent, isStandalone: true, selector: "axp-background-operation-slot", viewQueries: [{ propertyName: "popover", first: true, predicate: AXPopoverComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"bg-lightest rounded-md w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:0;color:rgb(var(--ax-sys-color-primary-600))}@media(hover:hover){.operation-slot__trigger:hover{color:rgb(var(--ax-sys-color-primary-700))}}.operation-slot__icon{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.operation-slot__text{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{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-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "component", type: AXPBackgroundOperationPanelComponent, selector: "axp-background-operation-panel", outputs: ["onActiveCountChange", "onClosePopover"] }, { kind: "pipe", type: i4$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
3775
3980
|
}
|
|
3776
3981
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBackgroundOperationSlotComponent, decorators: [{
|
|
3777
3982
|
type: Component,
|
|
3778
|
-
args: [{ selector: 'axp-background-operation-slot', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXDecoratorModule, AXTranslationModule, AXPopoverModule, AXPBackgroundOperationPanelComponent], template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"
|
|
3983
|
+
args: [{ selector: 'axp-background-operation-slot', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, imports: [CommonModule, AXDecoratorModule, AXTranslationModule, AXPopoverModule, AXPBackgroundOperationPanelComponent], template: "@if (showSlot()) {\n <button type=\"button\" class=\"operation-slot__trigger\" #operationTrigger>\n <ax-icon class=\"operation-slot__icon\">\n @if (slotShowsFailureOnly()) {\n <i class=\"fa-light fa-circle-exclamation\"></i>\n } @else {\n <i class=\"fa-light fa-spinner fa-spin\"></i>\n }\n </ax-icon>\n <span class=\"operation-slot__text\">\n {{ slotLabelKey() | translate: { params: slotLabelParams() } | async }}\n </span>\n </button>\n\n <ax-popover [target]=\"operationTrigger\" [openOn]=\"'toggle'\" [closeOn]=\"'clickOut'\" [adaptivityEnabled]=\"true\">\n <div class=\"bg-lightest rounded-md w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["@layer properties;axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:calc(var(--spacing, .25rem) * 1.5);border-style:var(--tw-border-style);border-width:0px;background-color:transparent;padding:0;color:rgb(var(--ax-sys-color-primary-600))}@media(hover:hover){.operation-slot__trigger:hover{color:rgb(var(--ax-sys-color-primary-700))}}.operation-slot__icon{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)))}.operation-slot__text{font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-font-weight: var(--font-weight-medium, 500);font-weight:var(--font-weight-medium, 500)}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-font-weight{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-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
|
|
3779
3984
|
}], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPopoverComponent), { isSignal: true }] }] } });
|
|
3780
3985
|
|
|
3986
|
+
const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
|
|
3987
|
+
const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
|
|
3988
|
+
providedIn: 'root',
|
|
3989
|
+
factory: () => {
|
|
3990
|
+
return AXPPlatformDefaultConfigs;
|
|
3991
|
+
},
|
|
3992
|
+
});
|
|
3993
|
+
const AXPPlatformDefaultConfigs = {
|
|
3994
|
+
copyright: 'ACoreX @ 2026',
|
|
3995
|
+
title: 'ACoreX Platform',
|
|
3996
|
+
network: {
|
|
3997
|
+
timeOut: 5000,
|
|
3998
|
+
},
|
|
3999
|
+
};
|
|
4000
|
+
function configPlatform(config = AXPPlatformDefaultConfigs) {
|
|
4001
|
+
return merge(AXPPlatformDefaultConfigs, config);
|
|
4002
|
+
}
|
|
4003
|
+
|
|
3781
4004
|
//#endregion
|
|
3782
4005
|
//#region ---- App Path Navigation ----
|
|
3783
4006
|
/**
|
|
@@ -3841,17 +4064,20 @@ function axpReplaceEntityListRouteQueryParams(router, queryParams) {
|
|
|
3841
4064
|
if (!axpIsEntityListPath(url)) {
|
|
3842
4065
|
return;
|
|
3843
4066
|
}
|
|
4067
|
+
const parsed = router.parseUrl(url);
|
|
3844
4068
|
const pathOnly = url.split('?')[0].split('#')[0];
|
|
3845
4069
|
const { segments } = axpParseAppPath(pathOnly);
|
|
4070
|
+
const mergedQueryParams = { ...parsed.queryParams, ...queryParams };
|
|
3846
4071
|
void router.navigate(segments, {
|
|
3847
|
-
queryParams,
|
|
3848
|
-
queryParamsHandling: 'merge',
|
|
4072
|
+
queryParams: mergedQueryParams,
|
|
3849
4073
|
replaceUrl: true,
|
|
3850
4074
|
});
|
|
3851
4075
|
}
|
|
3852
4076
|
//#endregion
|
|
3853
4077
|
|
|
3854
4078
|
const DEFAULT_TRAILING_SEGMENTS = ['list', 'view', 'edit', 'create'];
|
|
4079
|
+
/** Query params managed by entity list UI; ignored when matching generic (no-query) menu paths. */
|
|
4080
|
+
const ENTITY_LIST_UI_QUERY_KEYS = new Set(['view']);
|
|
3855
4081
|
//#region ---- Entity Route Helpers ----
|
|
3856
4082
|
/**
|
|
3857
4083
|
* Parses `/{app}/m/{module}/e/{entity}/...` routes into a stable entity key.
|
|
@@ -3872,15 +4098,89 @@ function axpParseEntityRouteKey(segments) {
|
|
|
3872
4098
|
function axpEntityRouteKeysEqual(left, right) {
|
|
3873
4099
|
return left.app === right.app && left.module === right.module && left.entity === right.entity;
|
|
3874
4100
|
}
|
|
4101
|
+
function axpParseQueryString(queryString) {
|
|
4102
|
+
return new URLSearchParams(queryString);
|
|
4103
|
+
}
|
|
4104
|
+
function axpMenuDeclaredNavigationParams(queryString) {
|
|
4105
|
+
const params = axpParseQueryString(queryString);
|
|
4106
|
+
const navigationParams = new URLSearchParams();
|
|
4107
|
+
params.forEach((value, key) => {
|
|
4108
|
+
if (!ENTITY_LIST_UI_QUERY_KEYS.has(key)) {
|
|
4109
|
+
navigationParams.append(key, value);
|
|
4110
|
+
}
|
|
4111
|
+
});
|
|
4112
|
+
return navigationParams;
|
|
4113
|
+
}
|
|
4114
|
+
function axpMenuHasDeclaredNavigationParams(itemQueryString) {
|
|
4115
|
+
return axpMenuDeclaredNavigationParams(itemQueryString).toString().length > 0;
|
|
4116
|
+
}
|
|
4117
|
+
/**
|
|
4118
|
+
* True when every navigation query param declared on the menu path equals the current URL.
|
|
4119
|
+
*/
|
|
4120
|
+
function axpMenuDeclaredQueryParamsMatch(itemQueryString, currentQueryString) {
|
|
4121
|
+
const itemParams = axpMenuDeclaredNavigationParams(itemQueryString);
|
|
4122
|
+
const declaredPairs = [];
|
|
4123
|
+
itemParams.forEach((value, key) => {
|
|
4124
|
+
declaredPairs.push([key, value]);
|
|
4125
|
+
});
|
|
4126
|
+
if (declaredPairs.length === 0) {
|
|
4127
|
+
return axpGenericEntityListMenuQueryParamsMatch(currentQueryString);
|
|
4128
|
+
}
|
|
4129
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
4130
|
+
return declaredPairs.every(([key, value]) => currentParams.get(key) === value);
|
|
4131
|
+
}
|
|
4132
|
+
/**
|
|
4133
|
+
* Generic entity list menu items (no declared query params) match only when the URL has no
|
|
4134
|
+
* navigation query params beyond UI-managed keys such as `view`.
|
|
4135
|
+
*/
|
|
4136
|
+
function axpGenericEntityListMenuQueryParamsMatch(currentQueryString) {
|
|
4137
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
4138
|
+
let hasNavigationParam = false;
|
|
4139
|
+
currentParams.forEach((_value, key) => {
|
|
4140
|
+
if (!ENTITY_LIST_UI_QUERY_KEYS.has(key)) {
|
|
4141
|
+
hasNavigationParam = true;
|
|
4142
|
+
}
|
|
4143
|
+
});
|
|
4144
|
+
return !hasNavigationParam;
|
|
4145
|
+
}
|
|
4146
|
+
/**
|
|
4147
|
+
* Counts declared menu query params that match the current URL (for best-match selection).
|
|
4148
|
+
*/
|
|
4149
|
+
function axpMenuQueryParamSpecificity(itemPath, currentPath) {
|
|
4150
|
+
const itemQueryString = itemPath.split('#')[0].split('?')[1] ?? '';
|
|
4151
|
+
const currentQueryString = currentPath.split('#')[0].split('?')[1] ?? '';
|
|
4152
|
+
const itemParams = axpMenuDeclaredNavigationParams(itemQueryString);
|
|
4153
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
4154
|
+
let specificity = 0;
|
|
4155
|
+
itemParams.forEach((value, key) => {
|
|
4156
|
+
if (currentParams.get(key) === value) {
|
|
4157
|
+
specificity++;
|
|
4158
|
+
}
|
|
4159
|
+
});
|
|
4160
|
+
return specificity;
|
|
4161
|
+
}
|
|
3875
4162
|
/**
|
|
3876
4163
|
* Matches entity list menu entries against list/detail/create/edit routes for the same entity.
|
|
3877
4164
|
*/
|
|
3878
|
-
function axpTryMatchEntityMenuRoute(itemSegments, pathSegments, currentBase) {
|
|
4165
|
+
function axpTryMatchEntityMenuRoute(itemSegments, pathSegments, currentBase, itemQueryString, currentQueryString) {
|
|
3879
4166
|
const menuEntity = axpParseEntityRouteKey(itemSegments);
|
|
3880
4167
|
const currentEntity = axpParseEntityRouteKey(pathSegments);
|
|
3881
4168
|
if (!menuEntity || !currentEntity || !axpEntityRouteKeysEqual(menuEntity, currentEntity)) {
|
|
3882
4169
|
return null;
|
|
3883
4170
|
}
|
|
4171
|
+
const itemHasDeclaredParams = axpMenuHasDeclaredNavigationParams(itemQueryString);
|
|
4172
|
+
if (itemHasDeclaredParams) {
|
|
4173
|
+
if (!axpIsEntityListPath(currentBase)) {
|
|
4174
|
+
return { isMatch: false, isPartial: false };
|
|
4175
|
+
}
|
|
4176
|
+
if (!axpMenuDeclaredQueryParamsMatch(itemQueryString, currentQueryString)) {
|
|
4177
|
+
return { isMatch: false, isPartial: false };
|
|
4178
|
+
}
|
|
4179
|
+
return { isMatch: true, isPartial: false };
|
|
4180
|
+
}
|
|
4181
|
+
if (axpIsEntityListPath(currentBase) && !axpGenericEntityListMenuQueryParamsMatch(currentQueryString)) {
|
|
4182
|
+
return { isMatch: false, isPartial: false };
|
|
4183
|
+
}
|
|
3884
4184
|
const isPartial = pathSegments.length > menuEntity.entityEndIndex ||
|
|
3885
4185
|
axpIsEntityDetailsPath(currentBase) ||
|
|
3886
4186
|
!axpIsEntityListPath(currentBase);
|
|
@@ -3895,10 +4195,10 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
|
|
|
3895
4195
|
const itemNoHash = itemPath.split('#')[0];
|
|
3896
4196
|
const currentNoHash = currentPath.split('#')[0];
|
|
3897
4197
|
const [itemBase, itemQueryString = ''] = itemNoHash.split('?');
|
|
3898
|
-
const [currentBase] = currentNoHash.split('?');
|
|
4198
|
+
const [currentBase, currentQueryString = ''] = currentNoHash.split('?');
|
|
3899
4199
|
const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
|
|
3900
4200
|
const pathSegments = currentBase.split('/').filter((segment) => segment.length > 0);
|
|
3901
|
-
const entityMatch = axpTryMatchEntityMenuRoute(itemSegments, pathSegments, `/${currentBase}
|
|
4201
|
+
const entityMatch = axpTryMatchEntityMenuRoute(itemSegments, pathSegments, `/${currentBase}`, itemQueryString, currentQueryString);
|
|
3902
4202
|
if (entityMatch) {
|
|
3903
4203
|
return entityMatch;
|
|
3904
4204
|
}
|
|
@@ -3923,8 +4223,8 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
|
|
|
3923
4223
|
}
|
|
3924
4224
|
const isPartialMatch = effectiveMenuLength < pathLength;
|
|
3925
4225
|
const isExactMatch = effectiveMenuLength === pathLength;
|
|
3926
|
-
const itemParams =
|
|
3927
|
-
const currentParams =
|
|
4226
|
+
const itemParams = axpParseQueryString(itemQueryString);
|
|
4227
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
3928
4228
|
let queryMatches = true;
|
|
3929
4229
|
const itemParamPairs = [];
|
|
3930
4230
|
itemParams.forEach((value, key) => {
|
|
@@ -3949,6 +4249,7 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
|
|
|
3949
4249
|
function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = DEFAULT_TRAILING_SEGMENTS) {
|
|
3950
4250
|
let bestMatch = null;
|
|
3951
4251
|
let bestEffectiveLength = -1;
|
|
4252
|
+
let bestQuerySpecificity = -1;
|
|
3952
4253
|
const visit = (menuItems, ancestors) => {
|
|
3953
4254
|
for (const item of menuItems) {
|
|
3954
4255
|
if (item.children?.length) {
|
|
@@ -3973,8 +4274,11 @@ function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = D
|
|
|
3973
4274
|
if (menuEntity) {
|
|
3974
4275
|
effectiveMenuLength = menuEntity.entityEndIndex;
|
|
3975
4276
|
}
|
|
3976
|
-
|
|
4277
|
+
const querySpecificity = axpMenuQueryParamSpecificity(item.path, currentPath);
|
|
4278
|
+
if (effectiveMenuLength > bestEffectiveLength ||
|
|
4279
|
+
(effectiveMenuLength === bestEffectiveLength && querySpecificity > bestQuerySpecificity)) {
|
|
3977
4280
|
bestEffectiveLength = effectiveMenuLength;
|
|
4281
|
+
bestQuerySpecificity = querySpecificity;
|
|
3978
4282
|
bestMatch = { item, ancestors, isPartialMatch: matchResult.isPartial };
|
|
3979
4283
|
}
|
|
3980
4284
|
}
|
|
@@ -4334,6 +4638,8 @@ class AXPMenuProviderService {
|
|
|
4334
4638
|
*/
|
|
4335
4639
|
this.menuReloadSubject = new Subject();
|
|
4336
4640
|
this.menuReload$ = this.menuReloadSubject.asObservable();
|
|
4641
|
+
/** Serializes menu builds so pending queues are not corrupted by concurrent items() calls. */
|
|
4642
|
+
this.itemsBuildLock = Promise.resolve();
|
|
4337
4643
|
}
|
|
4338
4644
|
//#endregion
|
|
4339
4645
|
//#region ---- Public API ----
|
|
@@ -4341,22 +4647,37 @@ class AXPMenuProviderService {
|
|
|
4341
4647
|
* Get menu items with middlewares applied (for end-user display)
|
|
4342
4648
|
*/
|
|
4343
4649
|
async items() {
|
|
4344
|
-
// Return cached items if available
|
|
4345
4650
|
if (this.cache) {
|
|
4346
4651
|
return this.cache;
|
|
4347
4652
|
}
|
|
4653
|
+
let releaseLock;
|
|
4654
|
+
const previousBuild = this.itemsBuildLock;
|
|
4655
|
+
this.itemsBuildLock = new Promise((resolve) => {
|
|
4656
|
+
releaseLock = resolve;
|
|
4657
|
+
});
|
|
4658
|
+
await previousBuild;
|
|
4659
|
+
try {
|
|
4660
|
+
if (this.cache) {
|
|
4661
|
+
return this.cache;
|
|
4662
|
+
}
|
|
4663
|
+
return await this.buildItems();
|
|
4664
|
+
}
|
|
4665
|
+
finally {
|
|
4666
|
+
releaseLock();
|
|
4667
|
+
}
|
|
4668
|
+
}
|
|
4669
|
+
async buildItems() {
|
|
4670
|
+
this.resetPendingOperations();
|
|
4348
4671
|
const items = [];
|
|
4349
4672
|
const context = this.createMenuProviderContext(items);
|
|
4350
4673
|
// Load providers from DI tokens
|
|
4351
4674
|
if (Array.isArray(this.providers)) {
|
|
4352
4675
|
for (const provider of this.providers) {
|
|
4353
4676
|
if (provider instanceof Promise) {
|
|
4354
|
-
// If provider is a promise, resolve it
|
|
4355
4677
|
const resolvedProvider = await provider;
|
|
4356
4678
|
await resolvedProvider.provide(context);
|
|
4357
4679
|
}
|
|
4358
4680
|
else {
|
|
4359
|
-
// If provider is a direct instance, use it directly
|
|
4360
4681
|
await provider.provide(context);
|
|
4361
4682
|
}
|
|
4362
4683
|
// Apply pending operations after each provider so subsequent providers
|
|
@@ -4379,6 +4700,7 @@ class AXPMenuProviderService {
|
|
|
4379
4700
|
* Used by menu management pages to show original items before customization
|
|
4380
4701
|
*/
|
|
4381
4702
|
async rawItems() {
|
|
4703
|
+
this.resetPendingOperations();
|
|
4382
4704
|
const items = [];
|
|
4383
4705
|
const context = this.createMenuProviderContext(items);
|
|
4384
4706
|
// Load providers from DI tokens
|
|
@@ -4409,16 +4731,19 @@ class AXPMenuProviderService {
|
|
|
4409
4731
|
*/
|
|
4410
4732
|
clearCache() {
|
|
4411
4733
|
this.cache = null;
|
|
4734
|
+
this.resetPendingOperations();
|
|
4735
|
+
// Notify subscribers that menu should be reloaded
|
|
4736
|
+
this.menuReloadSubject.next();
|
|
4737
|
+
}
|
|
4738
|
+
//#endregion
|
|
4739
|
+
//#region ---- Private Methods ----
|
|
4740
|
+
resetPendingOperations() {
|
|
4412
4741
|
this.pendingInserts = [];
|
|
4413
4742
|
this.pendingRemovals = [];
|
|
4414
4743
|
this.pendingUpdates = [];
|
|
4415
4744
|
this.pendingAdditions = [];
|
|
4416
4745
|
this.pendingMoves = [];
|
|
4417
|
-
// Notify subscribers that menu should be reloaded
|
|
4418
|
-
this.menuReloadSubject.next();
|
|
4419
4746
|
}
|
|
4420
|
-
//#endregion
|
|
4421
|
-
//#region ---- Private Methods ----
|
|
4422
4747
|
/**
|
|
4423
4748
|
* Apply middlewares in priority order using the enhanced context API
|
|
4424
4749
|
*/
|
|
@@ -4562,17 +4887,29 @@ class AXPMenuProviderService {
|
|
|
4562
4887
|
Object.assign(foundItem, updatedItem);
|
|
4563
4888
|
}
|
|
4564
4889
|
}
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
|
|
4570
|
-
|
|
4571
|
-
|
|
4890
|
+
this.applyPendingAdditions(items);
|
|
4891
|
+
for (const move of this.pendingMoves) {
|
|
4892
|
+
this.applyPendingMove(items, move.source, move.destination, move.position);
|
|
4893
|
+
}
|
|
4894
|
+
this.resetPendingOperations();
|
|
4895
|
+
}
|
|
4896
|
+
/**
|
|
4897
|
+
* Applies queued child additions in multiple passes so a provider can create a parent shell
|
|
4898
|
+
* and attach children in the same provide() call (parent is created in an earlier pass).
|
|
4899
|
+
*/
|
|
4900
|
+
applyPendingAdditions(items) {
|
|
4901
|
+
const maxPasses = 32;
|
|
4902
|
+
for (let pass = 0; pass < maxPasses && this.pendingAdditions.length > 0; pass++) {
|
|
4903
|
+
const remaining = [];
|
|
4904
|
+
for (const { target, newItems } of this.pendingAdditions) {
|
|
4905
|
+
const foundItem = this.findItemWithParent(items, target).foundItem;
|
|
4906
|
+
if (!foundItem) {
|
|
4907
|
+
remaining.push({ target, newItems });
|
|
4908
|
+
continue;
|
|
4909
|
+
}
|
|
4572
4910
|
if (!foundItem.children) {
|
|
4573
4911
|
foundItem.children = [];
|
|
4574
4912
|
}
|
|
4575
|
-
// Check for duplicates by name and merge or add
|
|
4576
4913
|
for (const newItem of newItems) {
|
|
4577
4914
|
if (newItem.name) {
|
|
4578
4915
|
const existingChild = this.findItemByName(foundItem.children, newItem.name);
|
|
@@ -4588,16 +4925,14 @@ class AXPMenuProviderService {
|
|
|
4588
4925
|
}
|
|
4589
4926
|
}
|
|
4590
4927
|
}
|
|
4928
|
+
if (remaining.length === this.pendingAdditions.length) {
|
|
4929
|
+
for (const { target } of remaining) {
|
|
4930
|
+
console.warn(`Target "${target}" not found, nothing to add items to.`);
|
|
4931
|
+
}
|
|
4932
|
+
break;
|
|
4933
|
+
}
|
|
4934
|
+
this.pendingAdditions = remaining;
|
|
4591
4935
|
}
|
|
4592
|
-
for (const move of this.pendingMoves) {
|
|
4593
|
-
this.applyPendingMove(items, move.source, move.destination, move.position);
|
|
4594
|
-
}
|
|
4595
|
-
// Clear pending operations after applying them
|
|
4596
|
-
this.pendingInserts = [];
|
|
4597
|
-
this.pendingRemovals = [];
|
|
4598
|
-
this.pendingUpdates = [];
|
|
4599
|
-
this.pendingAdditions = [];
|
|
4600
|
-
this.pendingMoves = [];
|
|
4601
4936
|
}
|
|
4602
4937
|
findItemWithParent(items, target, parentItems = items) {
|
|
4603
4938
|
for (const item of items) {
|
|
@@ -4967,7 +5302,7 @@ withState((router = inject(Router)) => {
|
|
|
4967
5302
|
};
|
|
4968
5303
|
}),
|
|
4969
5304
|
// Methods for State Management
|
|
4970
|
-
withMethods((store, router = inject(Router),
|
|
5305
|
+
withMethods((store, router = inject(Router), commandService = inject(AXPCommandService)) => {
|
|
4971
5306
|
return {
|
|
4972
5307
|
setMenuItems(items) {
|
|
4973
5308
|
patchState(store, { items: items });
|
|
@@ -4983,19 +5318,13 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
|
|
|
4983
5318
|
},
|
|
4984
5319
|
executeCommand(item) {
|
|
4985
5320
|
if (item.path) {
|
|
4986
|
-
|
|
4987
|
-
type: 'router',
|
|
4988
|
-
options: { path: item.path },
|
|
4989
|
-
});
|
|
5321
|
+
void commandService.execute('navigate', { path: item.path });
|
|
4990
5322
|
patchState(store, { selectedMenuItem: { item, isFullMatch: true } });
|
|
4991
5323
|
}
|
|
4992
5324
|
if (item.command) {
|
|
4993
5325
|
const command = item.command;
|
|
4994
|
-
if (
|
|
4995
|
-
|
|
4996
|
-
}
|
|
4997
|
-
else {
|
|
4998
|
-
commandExecutor.execute(command.name, command.options);
|
|
5326
|
+
if (commandService.exists(command?.name)) {
|
|
5327
|
+
void commandService.execute(command.name, command.options ?? {});
|
|
4999
5328
|
}
|
|
5000
5329
|
}
|
|
5001
5330
|
},
|
|
@@ -5016,8 +5345,9 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
|
|
|
5016
5345
|
return findParent(item, selectedItem);
|
|
5017
5346
|
},
|
|
5018
5347
|
};
|
|
5019
|
-
}), withHooks((store, menuProviderService = inject(AXPMenuProviderService), menuKeyboardShortcuts = inject(AXPMenuKeyboardShortcutService), router = inject(Router)) => {
|
|
5348
|
+
}), withHooks((store, menuProviderService = inject(AXPMenuProviderService), menuKeyboardShortcuts = inject(AXPMenuKeyboardShortcutService), router = inject(Router), sessionService = inject(AXPSessionService)) => {
|
|
5020
5349
|
let reloadSubscription;
|
|
5350
|
+
let accessPolicySubscription;
|
|
5021
5351
|
const applyMenuItems = (items) => {
|
|
5022
5352
|
patchState(store, { items });
|
|
5023
5353
|
menuKeyboardShortcuts.sync(items);
|
|
@@ -5025,20 +5355,39 @@ withMethods((store, router = inject(Router), workflow = inject(AXPWorkflowServic
|
|
|
5025
5355
|
};
|
|
5026
5356
|
return {
|
|
5027
5357
|
onInit() {
|
|
5028
|
-
// Load initial menu items
|
|
5029
|
-
(async () => {
|
|
5030
|
-
applyMenuItems(await menuProviderService.items());
|
|
5031
|
-
})();
|
|
5032
5358
|
// Subscribe to menu reload events
|
|
5033
|
-
reloadSubscription = menuProviderService.menuReload$.subscribe(
|
|
5034
|
-
|
|
5359
|
+
reloadSubscription = menuProviderService.menuReload$.subscribe(() => {
|
|
5360
|
+
void (async () => {
|
|
5361
|
+
applyMenuItems(await menuProviderService.items());
|
|
5362
|
+
})();
|
|
5363
|
+
});
|
|
5364
|
+
// Rebuild menu only after the session is Authorized and access policy data is ready.
|
|
5365
|
+
// Permissions/features load while status is still Authenticated; rebuilding then caches a
|
|
5366
|
+
// tree without common menu shells and module providers fail with "Target ... not found".
|
|
5367
|
+
accessPolicySubscription = combineLatest([
|
|
5368
|
+
sessionService.isAuthorized$,
|
|
5369
|
+
sessionService.permissions$,
|
|
5370
|
+
sessionService.features$,
|
|
5371
|
+
])
|
|
5372
|
+
.pipe(filter(([isAuthorized]) => isAuthorized), map(([, permissions, features]) => {
|
|
5373
|
+
const applicationId = sessionService.application?.id ?? '';
|
|
5374
|
+
return `${applicationId}:${permissions.length}:${features.length}`;
|
|
5375
|
+
}), distinctUntilChanged())
|
|
5376
|
+
.subscribe(() => {
|
|
5377
|
+
menuProviderService.clearCache();
|
|
5035
5378
|
});
|
|
5379
|
+
// Initial load: clear cache once after session is ready; menuReload$ performs the build.
|
|
5380
|
+
void (async () => {
|
|
5381
|
+
const authorized = await firstValueFrom(sessionService.isAuthorizedWithLoading$);
|
|
5382
|
+
if (!authorized) {
|
|
5383
|
+
return;
|
|
5384
|
+
}
|
|
5385
|
+
menuProviderService.clearCache();
|
|
5386
|
+
})();
|
|
5036
5387
|
},
|
|
5037
5388
|
onDestroy() {
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
reloadSubscription.unsubscribe();
|
|
5041
|
-
}
|
|
5389
|
+
reloadSubscription?.unsubscribe();
|
|
5390
|
+
accessPolicySubscription?.unsubscribe();
|
|
5042
5391
|
},
|
|
5043
5392
|
};
|
|
5044
5393
|
}));
|
|
@@ -6140,6 +6489,7 @@ class AXPBrowserTitleService {
|
|
|
6140
6489
|
this.tabNavigation = inject(AXPTabNavigationService);
|
|
6141
6490
|
this.menuService = inject(AXPMenuService);
|
|
6142
6491
|
this.sessionService = inject(AXPSessionService);
|
|
6492
|
+
this.platformConfig = inject(AXP_PLATFORM_CONFIG_TOKEN);
|
|
6143
6493
|
this.router = inject(Router);
|
|
6144
6494
|
this.destroyRef = inject(DestroyRef);
|
|
6145
6495
|
//#endregion
|
|
@@ -6235,11 +6585,15 @@ class AXPBrowserTitleService {
|
|
|
6235
6585
|
}
|
|
6236
6586
|
async resolveApplicationTitle() {
|
|
6237
6587
|
const application = this.sessionService.application;
|
|
6238
|
-
const
|
|
6239
|
-
if (
|
|
6588
|
+
const sessionTitle = application?.title?.trim() || application?.name?.trim() || '';
|
|
6589
|
+
if (sessionTitle) {
|
|
6590
|
+
return (await this.resolveLocalizedText(sessionTitle)) ?? sessionTitle;
|
|
6591
|
+
}
|
|
6592
|
+
const platformTitle = this.platformConfig.title?.trim() || '';
|
|
6593
|
+
if (!platformTitle) {
|
|
6240
6594
|
return '';
|
|
6241
6595
|
}
|
|
6242
|
-
return (await this.resolveLocalizedText(
|
|
6596
|
+
return (await this.resolveLocalizedText(platformTitle)) ?? platformTitle;
|
|
6243
6597
|
}
|
|
6244
6598
|
async resolveLocalizedText(value) {
|
|
6245
6599
|
const trimmed = value.trim();
|
|
@@ -6257,7 +6611,7 @@ class AXPBrowserTitleService {
|
|
|
6257
6611
|
if (route && app) {
|
|
6258
6612
|
return `${route} | ${app}`;
|
|
6259
6613
|
}
|
|
6260
|
-
return route || app
|
|
6614
|
+
return route || app;
|
|
6261
6615
|
}
|
|
6262
6616
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBrowserTitleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6263
6617
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBrowserTitleService, providedIn: 'root' }); }
|
|
@@ -6333,6 +6687,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
6333
6687
|
type: Injectable
|
|
6334
6688
|
}] });
|
|
6335
6689
|
|
|
6690
|
+
/**
|
|
6691
|
+
* Best-effort plain string for thrown {@link Error} messages from command results (no i18n lookup).
|
|
6692
|
+
*/
|
|
6693
|
+
function commandMessageTextForError(value) {
|
|
6694
|
+
if (value == null) {
|
|
6695
|
+
return '';
|
|
6696
|
+
}
|
|
6697
|
+
if (typeof value === 'string') {
|
|
6698
|
+
return value;
|
|
6699
|
+
}
|
|
6700
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
6701
|
+
const values = Object.values(value);
|
|
6702
|
+
const first = values.find((v) => typeof v === 'string' && v.length > 0);
|
|
6703
|
+
return first ?? '';
|
|
6704
|
+
}
|
|
6705
|
+
return String(value);
|
|
6706
|
+
}
|
|
6707
|
+
|
|
6336
6708
|
class AXPErrorHandlerRegistryService {
|
|
6337
6709
|
constructor(injector) {
|
|
6338
6710
|
this.injector = injector;
|
|
@@ -6360,35 +6732,120 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
6360
6732
|
}]
|
|
6361
6733
|
}], ctorParameters: () => [{ type: i0.Injector }] });
|
|
6362
6734
|
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
this.injector = injector;
|
|
6367
|
-
this.registry = registry;
|
|
6735
|
+
function readBodyRecord(body) {
|
|
6736
|
+
if (body == null || typeof body !== 'object' || Array.isArray(body)) {
|
|
6737
|
+
return null;
|
|
6368
6738
|
}
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
});
|
|
6376
|
-
}
|
|
6377
|
-
else {
|
|
6378
|
-
super.handleError(error); // Fallback to default handler
|
|
6379
|
-
}
|
|
6380
|
-
};
|
|
6381
|
-
if (error.message?.startsWith('NG0100')) {
|
|
6382
|
-
//ignore it
|
|
6383
|
-
return;
|
|
6384
|
-
}
|
|
6385
|
-
handleErrorRecursively(0, error);
|
|
6739
|
+
return body;
|
|
6740
|
+
}
|
|
6741
|
+
function readPayload(body) {
|
|
6742
|
+
const record = readBodyRecord(body);
|
|
6743
|
+
if (!record) {
|
|
6744
|
+
return null;
|
|
6386
6745
|
}
|
|
6387
|
-
|
|
6388
|
-
|
|
6746
|
+
const message = record['message'];
|
|
6747
|
+
if (readBodyRecord(message)) {
|
|
6748
|
+
return readBodyRecord(message);
|
|
6749
|
+
}
|
|
6750
|
+
const nestedError = record['error'];
|
|
6751
|
+
if (readBodyRecord(nestedError)) {
|
|
6752
|
+
return readBodyRecord(nestedError);
|
|
6753
|
+
}
|
|
6754
|
+
return record;
|
|
6389
6755
|
}
|
|
6390
|
-
|
|
6391
|
-
|
|
6756
|
+
function readStringParam(value) {
|
|
6757
|
+
return typeof value === 'string' && value.trim() ? value : undefined;
|
|
6758
|
+
}
|
|
6759
|
+
function extractHttpErrorBodyMessage(error) {
|
|
6760
|
+
const payload = readPayload(error.error);
|
|
6761
|
+
if (!payload) {
|
|
6762
|
+
return '';
|
|
6763
|
+
}
|
|
6764
|
+
const message = payload['message'];
|
|
6765
|
+
if (typeof message === 'string') {
|
|
6766
|
+
return message;
|
|
6767
|
+
}
|
|
6768
|
+
if (Array.isArray(message)) {
|
|
6769
|
+
return message.map(String).join(', ');
|
|
6770
|
+
}
|
|
6771
|
+
return '';
|
|
6772
|
+
}
|
|
6773
|
+
/**
|
|
6774
|
+
* Extracts structured API error details from an HTTP failure.
|
|
6775
|
+
*/
|
|
6776
|
+
function extractHttpRequestErrorInfo(error) {
|
|
6777
|
+
if (!(error instanceof HttpErrorResponse)) {
|
|
6778
|
+
return null;
|
|
6779
|
+
}
|
|
6780
|
+
const payload = readPayload(error.error);
|
|
6781
|
+
if (!payload) {
|
|
6782
|
+
const fallbackMessage = error.message?.trim();
|
|
6783
|
+
return fallbackMessage ? { message: fallbackMessage } : null;
|
|
6784
|
+
}
|
|
6785
|
+
const code = readStringParam(payload['code']);
|
|
6786
|
+
const params = {};
|
|
6787
|
+
const jobId = readStringParam(payload['jobId']);
|
|
6788
|
+
const status = readStringParam(payload['status']);
|
|
6789
|
+
const scheduleId = readStringParam(payload['scheduleId']);
|
|
6790
|
+
if (jobId) {
|
|
6791
|
+
params['jobId'] = jobId;
|
|
6792
|
+
}
|
|
6793
|
+
if (status) {
|
|
6794
|
+
params['status'] = status;
|
|
6795
|
+
}
|
|
6796
|
+
if (scheduleId) {
|
|
6797
|
+
params['scheduleId'] = scheduleId;
|
|
6798
|
+
}
|
|
6799
|
+
const message = extractHttpErrorBodyMessage(error);
|
|
6800
|
+
if (!code && !message) {
|
|
6801
|
+
return null;
|
|
6802
|
+
}
|
|
6803
|
+
return {
|
|
6804
|
+
message,
|
|
6805
|
+
...(code ? { code } : {}),
|
|
6806
|
+
...(Object.keys(params).length > 0 ? { params } : {}),
|
|
6807
|
+
};
|
|
6808
|
+
}
|
|
6809
|
+
/**
|
|
6810
|
+
* Resolves a user-facing error string from HTTP failures and thrown errors.
|
|
6811
|
+
*/
|
|
6812
|
+
function formatRequestError(error, fallback) {
|
|
6813
|
+
const httpInfo = extractHttpRequestErrorInfo(error);
|
|
6814
|
+
if (httpInfo) {
|
|
6815
|
+
return httpInfo.message || fallback;
|
|
6816
|
+
}
|
|
6817
|
+
return error instanceof Error ? error.message : fallback;
|
|
6818
|
+
}
|
|
6819
|
+
|
|
6820
|
+
class AXPGlobalErrorHandler extends ErrorHandler {
|
|
6821
|
+
constructor(injector, registry) {
|
|
6822
|
+
super();
|
|
6823
|
+
this.injector = injector;
|
|
6824
|
+
this.registry = registry;
|
|
6825
|
+
}
|
|
6826
|
+
handleError(error) {
|
|
6827
|
+
const handleErrorRecursively = (index, error) => {
|
|
6828
|
+
const errorHandlers = this.registry.handlers;
|
|
6829
|
+
if (index < errorHandlers.length) {
|
|
6830
|
+
errorHandlers[index].handleError(error, (err) => {
|
|
6831
|
+
handleErrorRecursively(index + 1, err);
|
|
6832
|
+
});
|
|
6833
|
+
}
|
|
6834
|
+
else {
|
|
6835
|
+
super.handleError(error); // Fallback to default handler
|
|
6836
|
+
}
|
|
6837
|
+
};
|
|
6838
|
+
if (error.message?.startsWith('NG0100')) {
|
|
6839
|
+
//ignore it
|
|
6840
|
+
return;
|
|
6841
|
+
}
|
|
6842
|
+
handleErrorRecursively(0, error);
|
|
6843
|
+
}
|
|
6844
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, deps: [{ token: i0.Injector }, { token: AXPErrorHandlerRegistryService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6845
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, providedIn: 'root' }); }
|
|
6846
|
+
}
|
|
6847
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPGlobalErrorHandler, decorators: [{
|
|
6848
|
+
type: Injectable,
|
|
6392
6849
|
args: [{ providedIn: 'root' }]
|
|
6393
6850
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: AXPErrorHandlerRegistryService }] });
|
|
6394
6851
|
|
|
@@ -6571,6 +7028,165 @@ async function resolveStoredImageDisplayUrl(value, download) {
|
|
|
6571
7028
|
}
|
|
6572
7029
|
//#endregion
|
|
6573
7030
|
|
|
7031
|
+
//#region ---- Logo image src resolver (file storage) ----
|
|
7032
|
+
class AXPLogoImageSrcResolverService {
|
|
7033
|
+
constructor(fileStorage) {
|
|
7034
|
+
this.fileStorage = fileStorage;
|
|
7035
|
+
}
|
|
7036
|
+
async resolve(src) {
|
|
7037
|
+
const trimmed = src?.trim();
|
|
7038
|
+
if (!trimmed) {
|
|
7039
|
+
return undefined;
|
|
7040
|
+
}
|
|
7041
|
+
if (!isStoredImageFileId(trimmed)) {
|
|
7042
|
+
return trimmed;
|
|
7043
|
+
}
|
|
7044
|
+
try {
|
|
7045
|
+
const displayUrl = await resolveStoredImageDisplayUrl(trimmed, (fileId) => this.fileStorage.download(fileId));
|
|
7046
|
+
return displayUrl || undefined;
|
|
7047
|
+
}
|
|
7048
|
+
catch {
|
|
7049
|
+
return undefined;
|
|
7050
|
+
}
|
|
7051
|
+
}
|
|
7052
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoImageSrcResolverService, deps: [{ token: AXPFileStorageService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
7053
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoImageSrcResolverService, providedIn: 'root' }); }
|
|
7054
|
+
}
|
|
7055
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLogoImageSrcResolverService, decorators: [{
|
|
7056
|
+
type: Injectable,
|
|
7057
|
+
args: [{ providedIn: 'root' }]
|
|
7058
|
+
}], ctorParameters: () => [{ type: AXPFileStorageService }] });
|
|
7059
|
+
|
|
7060
|
+
//#region ---- Document → file list item ----
|
|
7061
|
+
function normalizeFileIdSource(value) {
|
|
7062
|
+
return {
|
|
7063
|
+
kind: 'fileId',
|
|
7064
|
+
value: normalizeStoredImageRef(value) ?? value,
|
|
7065
|
+
};
|
|
7066
|
+
}
|
|
7067
|
+
function resolveSourceFromRaw(raw) {
|
|
7068
|
+
if (raw == null) {
|
|
7069
|
+
return undefined;
|
|
7070
|
+
}
|
|
7071
|
+
if (typeof raw === 'string') {
|
|
7072
|
+
return normalizeFileIdSource(raw);
|
|
7073
|
+
}
|
|
7074
|
+
if (typeof raw !== 'object') {
|
|
7075
|
+
return undefined;
|
|
7076
|
+
}
|
|
7077
|
+
const item = raw;
|
|
7078
|
+
if (item.source?.kind === 'fileId' && typeof item.source.value === 'string') {
|
|
7079
|
+
return normalizeFileIdSource(item.source.value);
|
|
7080
|
+
}
|
|
7081
|
+
if (item.source?.kind === 'blob' || item.source?.kind === 'url') {
|
|
7082
|
+
return item.source;
|
|
7083
|
+
}
|
|
7084
|
+
if (typeof item.source?.value === 'string') {
|
|
7085
|
+
const value = item.source.value;
|
|
7086
|
+
if (value.startsWith('blob:') || value.startsWith('data:') || value.startsWith('http')) {
|
|
7087
|
+
return { kind: 'url', value };
|
|
7088
|
+
}
|
|
7089
|
+
return normalizeFileIdSource(value);
|
|
7090
|
+
}
|
|
7091
|
+
if (typeof item.id === 'string' && item.id) {
|
|
7092
|
+
return normalizeFileIdSource(item.id);
|
|
7093
|
+
}
|
|
7094
|
+
return undefined;
|
|
7095
|
+
}
|
|
7096
|
+
/**
|
|
7097
|
+
* Normalizes a drive document or explorer node into an {@link AXPFileListItem}
|
|
7098
|
+
* with a resolvable `source` for the gallery / media viewer.
|
|
7099
|
+
*/
|
|
7100
|
+
function normalizeDocumentToFileListItem(doc) {
|
|
7101
|
+
const raw = doc.fileInfo ?? doc.fileId;
|
|
7102
|
+
const source = resolveSourceFromRaw(raw);
|
|
7103
|
+
const rawItem = typeof raw === 'object' && raw != null ? raw : undefined;
|
|
7104
|
+
const rawItemId = typeof rawItem?.id === 'string' ? rawItem.id : undefined;
|
|
7105
|
+
const sourceFileId = source?.kind === 'fileId' && typeof source.value === 'string' ? source.value : undefined;
|
|
7106
|
+
return {
|
|
7107
|
+
id: doc.id ?? rawItemId ?? sourceFileId ?? '',
|
|
7108
|
+
name: doc.name,
|
|
7109
|
+
size: rawItem?.size ?? doc.size ?? 0,
|
|
7110
|
+
status: rawItem?.status ?? 'attached',
|
|
7111
|
+
source,
|
|
7112
|
+
title: rawItem?.title,
|
|
7113
|
+
description: rawItem?.description,
|
|
7114
|
+
readOnly: rawItem?.readOnly,
|
|
7115
|
+
meta: rawItem?.meta,
|
|
7116
|
+
};
|
|
7117
|
+
}
|
|
7118
|
+
//#endregion
|
|
7119
|
+
|
|
7120
|
+
//#region ---- Media viewer type resolution ----
|
|
7121
|
+
/** Extensions supported by {@link AXMediaViewerData} (`image` | `audio` | `pdf` | `video`). */
|
|
7122
|
+
const GALLERY_MEDIA_EXTENSIONS = [
|
|
7123
|
+
'jpg',
|
|
7124
|
+
'jpeg',
|
|
7125
|
+
'png',
|
|
7126
|
+
'gif',
|
|
7127
|
+
'bmp',
|
|
7128
|
+
'webp',
|
|
7129
|
+
'svg',
|
|
7130
|
+
'pdf',
|
|
7131
|
+
'mp4',
|
|
7132
|
+
'webm',
|
|
7133
|
+
'mov',
|
|
7134
|
+
'm4v',
|
|
7135
|
+
'avi',
|
|
7136
|
+
'mkv',
|
|
7137
|
+
'wmv',
|
|
7138
|
+
'mp3',
|
|
7139
|
+
'wav',
|
|
7140
|
+
'ogg',
|
|
7141
|
+
'oga',
|
|
7142
|
+
'm4a',
|
|
7143
|
+
'flac',
|
|
7144
|
+
'aac',
|
|
7145
|
+
'wma',
|
|
7146
|
+
'weba',
|
|
7147
|
+
];
|
|
7148
|
+
const IMAGE_EXTENSIONS = new Set(['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']);
|
|
7149
|
+
const PDF_EXTENSIONS = new Set(['pdf']);
|
|
7150
|
+
const VIDEO_EXTENSIONS = new Set(['mp4', 'webm', 'mov', 'm4v', 'avi', 'mkv', 'wmv']);
|
|
7151
|
+
const AUDIO_EXTENSIONS = new Set(['mp3', 'wav', 'ogg', 'oga', 'm4a', 'flac', 'aac', 'wma', 'weba']);
|
|
7152
|
+
const GALLERY_EXTENSION_SET = new Set(GALLERY_MEDIA_EXTENSIONS);
|
|
7153
|
+
/** Returns the lowercase extension from a file name, or `undefined` when missing. */
|
|
7154
|
+
function extractFileExtension(fileName) {
|
|
7155
|
+
if (!fileName) {
|
|
7156
|
+
return undefined;
|
|
7157
|
+
}
|
|
7158
|
+
const ext = fileName.split('.').pop()?.toLowerCase();
|
|
7159
|
+
return ext && ext !== fileName.toLowerCase() ? ext : undefined;
|
|
7160
|
+
}
|
|
7161
|
+
/** Maps a file name extension to the media-viewer `type` discriminator. */
|
|
7162
|
+
function resolveMediaViewerType(fileName) {
|
|
7163
|
+
const ext = extractFileExtension(fileName);
|
|
7164
|
+
if (!ext) {
|
|
7165
|
+
return 'image';
|
|
7166
|
+
}
|
|
7167
|
+
if (PDF_EXTENSIONS.has(ext)) {
|
|
7168
|
+
return 'pdf';
|
|
7169
|
+
}
|
|
7170
|
+
if (VIDEO_EXTENSIONS.has(ext)) {
|
|
7171
|
+
return 'video';
|
|
7172
|
+
}
|
|
7173
|
+
if (AUDIO_EXTENSIONS.has(ext)) {
|
|
7174
|
+
return 'audio';
|
|
7175
|
+
}
|
|
7176
|
+
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
7177
|
+
return 'image';
|
|
7178
|
+
}
|
|
7179
|
+
return 'image';
|
|
7180
|
+
}
|
|
7181
|
+
/** Whether the extension can be rendered in the gallery / media viewer. */
|
|
7182
|
+
function isGalleryMediaExtension(extension) {
|
|
7183
|
+
if (!extension) {
|
|
7184
|
+
return false;
|
|
7185
|
+
}
|
|
7186
|
+
return GALLERY_EXTENSION_SET.has(extension.toLowerCase());
|
|
7187
|
+
}
|
|
7188
|
+
//#endregion
|
|
7189
|
+
|
|
6574
7190
|
class AXPKeyboardShortcutsHelpComponent {
|
|
6575
7191
|
constructor() {
|
|
6576
7192
|
//#region ---- Services & Dependencies ----
|
|
@@ -6633,7 +7249,7 @@ class AXPKeyboardShortcutsHelpComponent {
|
|
|
6633
7249
|
}
|
|
6634
7250
|
</div>
|
|
6635
7251
|
</div>
|
|
6636
|
-
`, isInline: true, styles: ["
|
|
7252
|
+
`, isInline: true, styles: ["@layer properties;.axp-keyboard-shortcuts-help{display:flex;max-height:75vh;min-height:0;flex-direction:column;overflow-y:auto}.axp-keyboard-shortcuts-help .__body{min-height:0;flex:1;padding:calc(var(--spacing, .25rem) * 4)}.axp-keyboard-shortcuts-help .__empty{margin:0;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 8);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-500, oklch(55.6% 0 0))}.axp-keyboard-shortcuts-help .__section:not(:first-child){margin-top:calc(var(--spacing, .25rem) * 6)}.axp-keyboard-shortcuts-help .__heading{margin:0;margin-bottom:calc(var(--spacing, .25rem) * 2);padding-inline:var(--spacing, .25rem);font-size:.9375rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__list{display:flex;flex-direction:column}.axp-keyboard-shortcuts-help .__row{display:flex;min-height:calc(var(--spacing, .25rem) * 8);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 8);padding-inline:var(--spacing, .25rem);padding-block:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help .__action{min-width:0;flex:1;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__keys{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 2)}.axp-keyboard-shortcuts-help .__or{padding-inline:calc(var(--spacing, .25rem) * .5);font-size:.8125rem;--tw-font-weight: var(--font-weight-normal, 400);font-weight:var(--font-weight-normal, 400);color:var(--color-neutral-500, oklch(55.6% 0 0));-webkit-user-select:none;user-select:none}.axp-keyboard-shortcuts-help ax-kbd{gap:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help ax-kbd ax-kbd-item kbd.ax-solid{height:calc(var(--spacing, .25rem) * 6);min-width:calc(var(--spacing, .25rem) * 6);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{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-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "component", type: AXKBDComponent, selector: "ax-kbd", inputs: ["look"] }, { kind: "component", type: AXKBDItemComponent, selector: "ax-kbd-item", inputs: ["keys", "join", "look"], outputs: ["lookChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
6637
7253
|
}
|
|
6638
7254
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPKeyboardShortcutsHelpComponent, decorators: [{
|
|
6639
7255
|
type: Component,
|
|
@@ -6676,7 +7292,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
6676
7292
|
}
|
|
6677
7293
|
</div>
|
|
6678
7294
|
</div>
|
|
6679
|
-
`, styles: ["
|
|
7295
|
+
`, styles: ["@layer properties;.axp-keyboard-shortcuts-help{display:flex;max-height:75vh;min-height:0;flex-direction:column;overflow-y:auto}.axp-keyboard-shortcuts-help .__body{min-height:0;flex:1;padding:calc(var(--spacing, .25rem) * 4)}.axp-keyboard-shortcuts-help .__empty{margin:0;padding-inline:calc(var(--spacing, .25rem) * 2);padding-block:calc(var(--spacing, .25rem) * 8);text-align:center;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));color:var(--color-neutral-500, oklch(55.6% 0 0))}.axp-keyboard-shortcuts-help .__section:not(:first-child){margin-top:calc(var(--spacing, .25rem) * 6)}.axp-keyboard-shortcuts-help .__heading{margin:0;margin-bottom:calc(var(--spacing, .25rem) * 2);padding-inline:var(--spacing, .25rem);font-size:.9375rem;--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);--tw-font-weight: var(--font-weight-semibold, 600);font-weight:var(--font-weight-semibold, 600);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__list{display:flex;flex-direction:column}.axp-keyboard-shortcuts-help .__row{display:flex;min-height:calc(var(--spacing, .25rem) * 8);align-items:center;justify-content:space-between;gap:calc(var(--spacing, .25rem) * 8);padding-inline:var(--spacing, .25rem);padding-block:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help .__action{min-width:0;flex:1;font-size:var(--text-sm, .875rem);line-height:var(--tw-leading, var(--text-sm--line-height, calc(1.25 / .875)));--tw-leading: var(--leading-snug, 1.375);line-height:var(--leading-snug, 1.375);color:rgba(var(--ax-sys-color-on-surface))}.axp-keyboard-shortcuts-help .__keys{display:flex;flex-shrink:0;align-items:center;justify-content:flex-end;gap:calc(var(--spacing, .25rem) * 2)}.axp-keyboard-shortcuts-help .__or{padding-inline:calc(var(--spacing, .25rem) * .5);font-size:.8125rem;--tw-font-weight: var(--font-weight-normal, 400);font-weight:var(--font-weight-normal, 400);color:var(--color-neutral-500, oklch(55.6% 0 0));-webkit-user-select:none;user-select:none}.axp-keyboard-shortcuts-help ax-kbd{gap:var(--spacing, .25rem)}.axp-keyboard-shortcuts-help ax-kbd ax-kbd-item kbd.ax-solid{height:calc(var(--spacing, .25rem) * 6);min-width:calc(var(--spacing, .25rem) * 6);font-size:var(--text-xs, .75rem);line-height:var(--tw-leading, var(--text-xs--line-height, calc(1 / .75)))}@property --tw-leading{syntax: \"*\"; inherits: false;}@property --tw-font-weight{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-leading: initial;--tw-font-weight: initial}}}\n/*! tailwindcss v4.3.2 | MIT License | https://tailwindcss.com */\n"] }]
|
|
6680
7296
|
}] });
|
|
6681
7297
|
|
|
6682
7298
|
var keyboardShortcutsHelp_component = /*#__PURE__*/Object.freeze({
|
|
@@ -7850,14 +8466,14 @@ class AXPMenuSearchProvider {
|
|
|
7850
8466
|
class AXPFooterTextSlotComponent {
|
|
7851
8467
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFooterTextSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7852
8468
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.9", type: AXPFooterTextSlotComponent, isStandalone: true, selector: "ng-component", inputs: { text: "text" }, ngImport: i0, template: `
|
|
7853
|
-
<small class="
|
|
8469
|
+
<small class="text-sm" [innerHTML]="text"></small>
|
|
7854
8470
|
`, isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
7855
8471
|
}
|
|
7856
8472
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFooterTextSlotComponent, decorators: [{
|
|
7857
8473
|
type: Component,
|
|
7858
8474
|
args: [{
|
|
7859
8475
|
template: `
|
|
7860
|
-
<small class="
|
|
8476
|
+
<small class="text-sm" [innerHTML]="text"></small>
|
|
7861
8477
|
`,
|
|
7862
8478
|
standalone: true,
|
|
7863
8479
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
@@ -7873,7 +8489,7 @@ class AXPNavBarSlotComponent {
|
|
|
7873
8489
|
}
|
|
7874
8490
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavBarSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7875
8491
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPNavBarSlotComponent, isStandalone: true, selector: "ng-component", inputs: { items: "items" }, ngImport: i0, template: `
|
|
7876
|
-
<div class="
|
|
8492
|
+
<div class="flex items-center justify-between gap-5">
|
|
7877
8493
|
@for (link of items; track link) {
|
|
7878
8494
|
<a (click)="handleCommand(link.command)" >{{ link.text }}</a>
|
|
7879
8495
|
}
|
|
@@ -7884,7 +8500,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
7884
8500
|
type: Component,
|
|
7885
8501
|
args: [{
|
|
7886
8502
|
template: `
|
|
7887
|
-
<div class="
|
|
8503
|
+
<div class="flex items-center justify-between gap-5">
|
|
7888
8504
|
@for (link of items; track link) {
|
|
7889
8505
|
<a (click)="handleCommand(link.command)" >{{ link.text }}</a>
|
|
7890
8506
|
}
|
|
@@ -7986,153 +8602,26 @@ class AXPTokenEvaluatorScopeProvider {
|
|
|
7986
8602
|
}
|
|
7987
8603
|
}
|
|
7988
8604
|
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
8605
|
+
//#region ---- Query params expression scope ----
|
|
8606
|
+
/**
|
|
8607
|
+
* Exposes URL query parameters in expression strings, e.g.
|
|
8608
|
+
* `{{ queryParams.get('view') }}`.
|
|
8609
|
+
*/
|
|
8610
|
+
class AXPQueryParamsEvaluatorScopeProvider {
|
|
7994
8611
|
constructor() {
|
|
7995
|
-
super(...arguments);
|
|
7996
8612
|
this.router = inject(Router);
|
|
7997
|
-
this.tabNavigation = inject(AXPTabNavigationService);
|
|
7998
|
-
}
|
|
7999
|
-
async execute(context) {
|
|
8000
|
-
const payload = context.getVariable('payload');
|
|
8001
|
-
if (Array.isArray(payload.commands)) {
|
|
8002
|
-
await this.router.navigate(payload.commands, payload.extras);
|
|
8003
|
-
return;
|
|
8004
|
-
}
|
|
8005
|
-
const path = payload.commands;
|
|
8006
|
-
if (!path) {
|
|
8007
|
-
return;
|
|
8008
|
-
}
|
|
8009
|
-
if (path.toLowerCase().startsWith('http') || payload.target === 'blank') {
|
|
8010
|
-
window.open(path, '_blank');
|
|
8011
|
-
return;
|
|
8012
|
-
}
|
|
8013
|
-
await this.tabNavigation.navigate(path, payload.extras);
|
|
8014
|
-
}
|
|
8015
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8016
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction }); }
|
|
8017
|
-
}
|
|
8018
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowNavigateAction, decorators: [{
|
|
8019
|
-
type: Injectable
|
|
8020
|
-
}] });
|
|
8021
|
-
class AXPDialogConfirmAction extends AXPWorkflowAction {
|
|
8022
|
-
constructor() {
|
|
8023
|
-
super(...arguments);
|
|
8024
|
-
this.dialogService = inject(AXDialogService);
|
|
8025
|
-
this.translationService = inject(AXTranslationService);
|
|
8026
|
-
this.defaultAction = 'cancel';
|
|
8027
|
-
}
|
|
8028
|
-
async execute(context) {
|
|
8029
|
-
console.log('AXPDialogConfirmAction', this.title, this.message, this.type);
|
|
8030
|
-
context.setOutput('result', false);
|
|
8031
|
-
const dialogResult = await this.dialogService.confirm(await this.translationService.translateAsync(this.title), await this.translationService.translateAsync(this.message), (await this.translationService.translateAsync(this.type)), 'horizontal', false, 'cancel');
|
|
8032
|
-
context.setOutput('result', dialogResult.result);
|
|
8033
|
-
}
|
|
8034
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8035
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction }); }
|
|
8036
|
-
}
|
|
8037
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDialogConfirmAction, decorators: [{
|
|
8038
|
-
type: Injectable
|
|
8039
|
-
}] });
|
|
8040
|
-
class AXPToastAction extends AXPWorkflowAction {
|
|
8041
|
-
constructor() {
|
|
8042
|
-
super(...arguments);
|
|
8043
|
-
this.toastService = inject(AXToastService);
|
|
8044
|
-
this.translationService = inject(AXTranslationService);
|
|
8045
|
-
this.settingsService = inject(AXPSettingsService);
|
|
8046
|
-
}
|
|
8047
|
-
async execute(context) {
|
|
8048
|
-
const showResult = await this.settingsService.get(AXPCommonSettings.EnableOperationToasts);
|
|
8049
|
-
if (showResult) {
|
|
8050
|
-
this.toastService.show({
|
|
8051
|
-
color: this.color,
|
|
8052
|
-
title: await this.translationService.translateAsync(this.title),
|
|
8053
|
-
content: await this.translationService.translateAsync(this.content),
|
|
8054
|
-
closeButton: true,
|
|
8055
|
-
timeOut: 3000,
|
|
8056
|
-
timeOutProgress: true,
|
|
8057
|
-
});
|
|
8058
|
-
}
|
|
8059
8613
|
}
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
async execute(context) {
|
|
8068
|
-
this.dispatch(AXPReloadEvent({ entity: context.getVariable('entity'), meta: context.getVariable('meta') }));
|
|
8614
|
+
async provide(context) {
|
|
8615
|
+
context.addScope('queryParams', {
|
|
8616
|
+
get: (key) => {
|
|
8617
|
+
const value = this.router.parseUrl(this.router.url).queryParamMap.get(key);
|
|
8618
|
+
return value ?? undefined;
|
|
8619
|
+
},
|
|
8620
|
+
});
|
|
8069
8621
|
}
|
|
8070
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8071
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction }); }
|
|
8072
8622
|
}
|
|
8073
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPReloadAction, decorators: [{
|
|
8074
|
-
type: Injectable
|
|
8075
|
-
}] });
|
|
8076
|
-
|
|
8077
|
-
//#region ---- Entity Workflow Events ----
|
|
8078
|
-
/** Workflow event type dispatched after a successful entity delete. */
|
|
8079
|
-
const AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE = '[Entity] Deleted';
|
|
8080
8623
|
//#endregion
|
|
8081
8624
|
|
|
8082
|
-
class AXPWorkflowRouterNavigateAction extends AXPWorkflowAction {
|
|
8083
|
-
constructor() {
|
|
8084
|
-
super(...arguments);
|
|
8085
|
-
this.tabNavigation = inject(AXPTabNavigationService);
|
|
8086
|
-
}
|
|
8087
|
-
async execute(context) {
|
|
8088
|
-
const command = context.getVariable();
|
|
8089
|
-
const path = command.options.path;
|
|
8090
|
-
if (!path) {
|
|
8091
|
-
console.error('Path is required for navigate workflow');
|
|
8092
|
-
return;
|
|
8093
|
-
}
|
|
8094
|
-
if (path?.toLowerCase()?.startsWith('http') || command.options?.extras?.target === 'blank') {
|
|
8095
|
-
window.open(path, '_blank');
|
|
8096
|
-
}
|
|
8097
|
-
else {
|
|
8098
|
-
await this.tabNavigation.navigate(path, command.options.extras);
|
|
8099
|
-
}
|
|
8100
|
-
}
|
|
8101
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8102
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction }); }
|
|
8103
|
-
}
|
|
8104
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPWorkflowRouterNavigateAction, decorators: [{
|
|
8105
|
-
type: Injectable
|
|
8106
|
-
}] });
|
|
8107
|
-
const AXPNavigateWorkflow = {
|
|
8108
|
-
startStepId: 'start',
|
|
8109
|
-
steps: {
|
|
8110
|
-
start: {
|
|
8111
|
-
action: 'navigate-router',
|
|
8112
|
-
},
|
|
8113
|
-
},
|
|
8114
|
-
};
|
|
8115
|
-
|
|
8116
|
-
class AXMWorkflowErrorHandler {
|
|
8117
|
-
constructor() {
|
|
8118
|
-
this.dialog = inject(AXDialogService);
|
|
8119
|
-
}
|
|
8120
|
-
handleError(error, next) {
|
|
8121
|
-
if (error instanceof AXPWorkflowError) {
|
|
8122
|
-
this.dialog.alert("Somthing is wrong!", error.inner ? error.inner.message : error.message, 'danger');
|
|
8123
|
-
next(error);
|
|
8124
|
-
}
|
|
8125
|
-
else {
|
|
8126
|
-
next(error);
|
|
8127
|
-
}
|
|
8128
|
-
}
|
|
8129
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8130
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler }); }
|
|
8131
|
-
}
|
|
8132
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMWorkflowErrorHandler, decorators: [{
|
|
8133
|
-
type: Injectable
|
|
8134
|
-
}] });
|
|
8135
|
-
|
|
8136
8625
|
class AXPCommonModule {
|
|
8137
8626
|
static forRoot(configs) {
|
|
8138
8627
|
return {
|
|
@@ -8176,7 +8665,7 @@ class AXPCommonModule {
|
|
|
8176
8665
|
});
|
|
8177
8666
|
}
|
|
8178
8667
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, deps: [{ token: 'AXPCommonModuleFactory' }, { token: AXPKeyboardShortcutsHelpService }, { token: i2$1.AXFormatterRegistryService }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
8179
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, imports: [i3$1.AXPComponentSlotModule,
|
|
8668
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPCommonModule, imports: [i3$1.AXPComponentSlotModule, AXPopupModule,
|
|
8180
8669
|
AXDateTimeModule,
|
|
8181
8670
|
AXToastModule,
|
|
8182
8671
|
AXPModuleManifestModule], exports: [RouterModule] }); }
|
|
@@ -8219,10 +8708,19 @@ class AXPCommonModule {
|
|
|
8219
8708
|
useClass: AXPFileStorageEvaluatorScopeProvider,
|
|
8220
8709
|
multi: true,
|
|
8221
8710
|
},
|
|
8711
|
+
{
|
|
8712
|
+
provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
|
|
8713
|
+
useClass: AXPQueryParamsEvaluatorScopeProvider,
|
|
8714
|
+
multi: true,
|
|
8715
|
+
},
|
|
8222
8716
|
{
|
|
8223
8717
|
provide: AXP_SETTINGS_CACHE_SYNC,
|
|
8224
8718
|
useExisting: AXPSettingsService,
|
|
8225
8719
|
},
|
|
8720
|
+
{
|
|
8721
|
+
provide: AXP_LOGO_IMAGE_SRC_RESOLVER,
|
|
8722
|
+
useExisting: AXPLogoImageSrcResolverService,
|
|
8723
|
+
},
|
|
8226
8724
|
{
|
|
8227
8725
|
provide: AXP_SETTING_VALUE_PROVIDER,
|
|
8228
8726
|
useFactory: createIndexedDbSettingValueProviders,
|
|
@@ -8232,11 +8730,17 @@ class AXPCommonModule {
|
|
|
8232
8730
|
provide: AXP_SETTING_DEFINITION_PROVIDER,
|
|
8233
8731
|
useFactory: async () => {
|
|
8234
8732
|
const injector = inject(Injector);
|
|
8235
|
-
const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-
|
|
8733
|
+
const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs')).AXPCommonSettingProvider;
|
|
8236
8734
|
return new provider(injector);
|
|
8237
8735
|
},
|
|
8238
8736
|
multi: true,
|
|
8239
8737
|
},
|
|
8738
|
+
provideCommandSetups([
|
|
8739
|
+
{
|
|
8740
|
+
key: 'navigate',
|
|
8741
|
+
command: () => Promise.resolve().then(function () { return navigate_command; }).then((c) => c.AXPNavigateCommand),
|
|
8742
|
+
},
|
|
8743
|
+
]),
|
|
8240
8744
|
], imports: [AXPComponentSlotModule.forChild({
|
|
8241
8745
|
'root-footer-end': [
|
|
8242
8746
|
{
|
|
@@ -8245,17 +8749,6 @@ class AXPCommonModule {
|
|
|
8245
8749
|
},
|
|
8246
8750
|
],
|
|
8247
8751
|
}),
|
|
8248
|
-
AXPWorkflowModule.forChild({
|
|
8249
|
-
actions: {
|
|
8250
|
-
'navigate-router': AXPWorkflowRouterNavigateAction,
|
|
8251
|
-
'show-prompt-dialog': AXPDialogConfirmAction,
|
|
8252
|
-
'show-toast': AXPToastAction,
|
|
8253
|
-
reload: AXPReloadAction,
|
|
8254
|
-
},
|
|
8255
|
-
workflows: {
|
|
8256
|
-
navigate: AXPNavigateWorkflow,
|
|
8257
|
-
},
|
|
8258
|
-
}),
|
|
8259
8752
|
AXPopupModule,
|
|
8260
8753
|
AXDateTimeModule,
|
|
8261
8754
|
AXToastModule,
|
|
@@ -8273,17 +8766,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8273
8766
|
},
|
|
8274
8767
|
],
|
|
8275
8768
|
}),
|
|
8276
|
-
AXPWorkflowModule.forChild({
|
|
8277
|
-
actions: {
|
|
8278
|
-
'navigate-router': AXPWorkflowRouterNavigateAction,
|
|
8279
|
-
'show-prompt-dialog': AXPDialogConfirmAction,
|
|
8280
|
-
'show-toast': AXPToastAction,
|
|
8281
|
-
reload: AXPReloadAction,
|
|
8282
|
-
},
|
|
8283
|
-
workflows: {
|
|
8284
|
-
navigate: AXPNavigateWorkflow,
|
|
8285
|
-
},
|
|
8286
|
-
}),
|
|
8287
8769
|
AXPopupModule,
|
|
8288
8770
|
AXDateTimeModule,
|
|
8289
8771
|
AXToastModule,
|
|
@@ -8329,10 +8811,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8329
8811
|
useClass: AXPFileStorageEvaluatorScopeProvider,
|
|
8330
8812
|
multi: true,
|
|
8331
8813
|
},
|
|
8814
|
+
{
|
|
8815
|
+
provide: AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER,
|
|
8816
|
+
useClass: AXPQueryParamsEvaluatorScopeProvider,
|
|
8817
|
+
multi: true,
|
|
8818
|
+
},
|
|
8332
8819
|
{
|
|
8333
8820
|
provide: AXP_SETTINGS_CACHE_SYNC,
|
|
8334
8821
|
useExisting: AXPSettingsService,
|
|
8335
8822
|
},
|
|
8823
|
+
{
|
|
8824
|
+
provide: AXP_LOGO_IMAGE_SRC_RESOLVER,
|
|
8825
|
+
useExisting: AXPLogoImageSrcResolverService,
|
|
8826
|
+
},
|
|
8336
8827
|
{
|
|
8337
8828
|
provide: AXP_SETTING_VALUE_PROVIDER,
|
|
8338
8829
|
useFactory: createIndexedDbSettingValueProviders,
|
|
@@ -8342,11 +8833,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8342
8833
|
provide: AXP_SETTING_DEFINITION_PROVIDER,
|
|
8343
8834
|
useFactory: async () => {
|
|
8344
8835
|
const injector = inject(Injector);
|
|
8345
|
-
const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-
|
|
8836
|
+
const provider = (await import('./acorex-platform-framework-client-common-common-settings.provider-Euotv9l0.mjs')).AXPCommonSettingProvider;
|
|
8346
8837
|
return new provider(injector);
|
|
8347
8838
|
},
|
|
8348
8839
|
multi: true,
|
|
8349
8840
|
},
|
|
8841
|
+
provideCommandSetups([
|
|
8842
|
+
{
|
|
8843
|
+
key: 'navigate',
|
|
8844
|
+
command: () => Promise.resolve().then(function () { return navigate_command; }).then((c) => c.AXPNavigateCommand),
|
|
8845
|
+
},
|
|
8846
|
+
]),
|
|
8350
8847
|
],
|
|
8351
8848
|
}]
|
|
8352
8849
|
}], ctorParameters: () => [{ type: undefined, decorators: [{
|
|
@@ -8354,24 +8851,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8354
8851
|
args: ['AXPCommonModuleFactory']
|
|
8355
8852
|
}] }, { type: AXPKeyboardShortcutsHelpService }, { type: i2$1.AXFormatterRegistryService }] });
|
|
8356
8853
|
|
|
8357
|
-
const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
|
|
8358
|
-
const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
|
|
8359
|
-
providedIn: 'root',
|
|
8360
|
-
factory: () => {
|
|
8361
|
-
return AXPPlatformDefaultConfigs;
|
|
8362
|
-
},
|
|
8363
|
-
});
|
|
8364
|
-
const AXPPlatformDefaultConfigs = {
|
|
8365
|
-
copyright: 'ACoreX @ 2026',
|
|
8366
|
-
title: 'ACoreX Platform',
|
|
8367
|
-
network: {
|
|
8368
|
-
timeOut: 5000,
|
|
8369
|
-
},
|
|
8370
|
-
};
|
|
8371
|
-
function configPlatform(config = AXPPlatformDefaultConfigs) {
|
|
8372
|
-
return merge(AXPPlatformDefaultConfigs, config);
|
|
8373
|
-
}
|
|
8374
|
-
|
|
8375
8854
|
/**
|
|
8376
8855
|
* Resolves post-create list behavior from user settings and optional action overrides.
|
|
8377
8856
|
*/
|
|
@@ -8387,6 +8866,49 @@ async function resolveEntityCreateListBehavior(settingsService, options) {
|
|
|
8387
8866
|
|
|
8388
8867
|
const AXP_ROOT_CONFIG_TOKEN = new InjectionToken('AXP_ROOT_CONFIG_TOKEN');
|
|
8389
8868
|
|
|
8869
|
+
/**
|
|
8870
|
+
* Opens the native file picker and always settles — including when the user cancels.
|
|
8871
|
+
* `AXFileService.choose()` can hang on cancel because no `change` event fires.
|
|
8872
|
+
*/
|
|
8873
|
+
function chooseSystemFiles(options = {}) {
|
|
8874
|
+
const document = inject(DOCUMENT);
|
|
8875
|
+
const accept = options.accept ?? '';
|
|
8876
|
+
const multiple = options.multiple ?? false;
|
|
8877
|
+
return new Promise((resolve) => {
|
|
8878
|
+
const input = document.createElement('input');
|
|
8879
|
+
input.type = 'file';
|
|
8880
|
+
input.accept = accept;
|
|
8881
|
+
input.multiple = multiple;
|
|
8882
|
+
input.style.display = 'none';
|
|
8883
|
+
document.body.appendChild(input);
|
|
8884
|
+
let settled = false;
|
|
8885
|
+
const settle = (files) => {
|
|
8886
|
+
if (settled) {
|
|
8887
|
+
return;
|
|
8888
|
+
}
|
|
8889
|
+
settled = true;
|
|
8890
|
+
cleanup();
|
|
8891
|
+
resolve(files);
|
|
8892
|
+
};
|
|
8893
|
+
const cleanup = () => {
|
|
8894
|
+
input.removeEventListener('change', onChange);
|
|
8895
|
+
window.removeEventListener('focus', onWindowFocus);
|
|
8896
|
+
input.remove();
|
|
8897
|
+
};
|
|
8898
|
+
const onChange = () => {
|
|
8899
|
+
settle(Array.from(input.files ?? []));
|
|
8900
|
+
};
|
|
8901
|
+
const onWindowFocus = () => {
|
|
8902
|
+
// Allow `change` to fire first when the user confirms a selection.
|
|
8903
|
+
window.setTimeout(() => settle([]), 300);
|
|
8904
|
+
};
|
|
8905
|
+
input.addEventListener('change', onChange);
|
|
8906
|
+
window.addEventListener('focus', onWindowFocus, { once: true });
|
|
8907
|
+
input.click();
|
|
8908
|
+
});
|
|
8909
|
+
}
|
|
8910
|
+
//#endregion
|
|
8911
|
+
|
|
8390
8912
|
//#endregion
|
|
8391
8913
|
//#region ---- Injection Token ----
|
|
8392
8914
|
/**
|
|
@@ -8507,7 +9029,6 @@ const UploadFromComputerActionProvider = {
|
|
|
8507
9029
|
key: 'file-uploader.actions',
|
|
8508
9030
|
priority: 1, // Higher priority than upload-from-drive to show first
|
|
8509
9031
|
execute: (payload) => {
|
|
8510
|
-
const fileService = inject(AXFileService);
|
|
8511
9032
|
// Capture widget options for use in the action
|
|
8512
9033
|
const widgetOptions = payload.options;
|
|
8513
9034
|
payload.actions = [
|
|
@@ -8519,7 +9040,7 @@ const UploadFromComputerActionProvider = {
|
|
|
8519
9040
|
icon: 'fa-light fa-file-arrow-up',
|
|
8520
9041
|
run: async (capabilities) => {
|
|
8521
9042
|
// Open file picker with widget options
|
|
8522
|
-
const files = await
|
|
9043
|
+
const files = await chooseSystemFiles({
|
|
8523
9044
|
multiple: widgetOptions?.multiple ?? true,
|
|
8524
9045
|
accept: widgetOptions?.accept,
|
|
8525
9046
|
});
|
|
@@ -8552,17 +9073,17 @@ class AXPFileTypeProviderService {
|
|
|
8552
9073
|
constructor() {
|
|
8553
9074
|
this.providers = inject(AXP_FILE_TYPE_INFO_PROVIDER, { optional: true });
|
|
8554
9075
|
}
|
|
8555
|
-
async items() {
|
|
9076
|
+
async items(purpose) {
|
|
8556
9077
|
const items = [];
|
|
8557
9078
|
if (Array.isArray(this.providers)) {
|
|
8558
9079
|
for (const provider of this.providers) {
|
|
8559
|
-
items.push(...(await provider.items()));
|
|
9080
|
+
items.push(...(await provider.items(purpose)));
|
|
8560
9081
|
}
|
|
8561
9082
|
}
|
|
8562
9083
|
return items;
|
|
8563
9084
|
}
|
|
8564
|
-
async get(name) {
|
|
8565
|
-
return (await this.items()).find((c) => c.name == name);
|
|
9085
|
+
async get(name, purpose) {
|
|
9086
|
+
return (await this.items(purpose)).find((c) => c.name == name);
|
|
8566
9087
|
}
|
|
8567
9088
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8568
9089
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileTypeProviderService, providedIn: 'root' }); }
|
|
@@ -8572,27 +9093,437 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8572
9093
|
args: [{ providedIn: 'root' }]
|
|
8573
9094
|
}] });
|
|
8574
9095
|
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
}
|
|
8583
|
-
//#endregion
|
|
9096
|
+
/** Default catalog purposes for document-management (excludes conversation). */
|
|
9097
|
+
const AXP_DOCUMENT_FILE_TYPE_PURPOSES = ['system', 'document'];
|
|
9098
|
+
function normalizeDocumentFileTypePurposes(purpose) {
|
|
9099
|
+
if (!purpose) {
|
|
9100
|
+
return [...AXP_DOCUMENT_FILE_TYPE_PURPOSES];
|
|
9101
|
+
}
|
|
9102
|
+
return Array.isArray(purpose) ? purpose : [purpose];
|
|
9103
|
+
}
|
|
8584
9104
|
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
9105
|
+
const DEFAULT_ICON = 'fa-solid fa-file';
|
|
9106
|
+
const DEFAULT_TYPE_NAME = 'file';
|
|
9107
|
+
/**
|
|
9108
|
+
* Picks the best file name for extension-based icon lookup in the explorer.
|
|
9109
|
+
* Document display names may omit the extension while `fileId.name` retains it.
|
|
9110
|
+
*/
|
|
9111
|
+
function resolveExplorerFileDisplayName(nodeName, fileId) {
|
|
9112
|
+
if (nodeName.includes('.')) {
|
|
9113
|
+
return nodeName;
|
|
8591
9114
|
}
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
9115
|
+
if (fileId != null && typeof fileId === 'object' && fileId.name?.includes('.')) {
|
|
9116
|
+
return fileId.name;
|
|
9117
|
+
}
|
|
9118
|
+
return nodeName;
|
|
9119
|
+
}
|
|
9120
|
+
/**
|
|
9121
|
+
* Resolves explorer / list icon and logical file type from the ACoreX file-type catalog.
|
|
9122
|
+
* Matches the file name extension against each catalog entry's `extensions`, then falls back
|
|
9123
|
+
* to the parent type icon (`video`, `audio`, `file`, …).
|
|
9124
|
+
*/
|
|
9125
|
+
function resolveFileTypeDisplay(fileName, catalog) {
|
|
9126
|
+
const extension = (getFileExtension(fileName) ?? '').toLowerCase();
|
|
9127
|
+
if (!extension || catalog.length === 0) {
|
|
9128
|
+
return { icon: DEFAULT_ICON, typeName: DEFAULT_TYPE_NAME, extension };
|
|
9129
|
+
}
|
|
9130
|
+
for (const type of catalog) {
|
|
9131
|
+
const match = (type.extensions ?? []).find((ext) => ext.name?.toLowerCase() === extension);
|
|
9132
|
+
if (match) {
|
|
9133
|
+
return {
|
|
9134
|
+
icon: match.icon || type.icon || DEFAULT_ICON,
|
|
9135
|
+
typeName: type.name,
|
|
9136
|
+
extension,
|
|
9137
|
+
};
|
|
9138
|
+
}
|
|
9139
|
+
}
|
|
9140
|
+
return { icon: DEFAULT_ICON, typeName: DEFAULT_TYPE_NAME, extension };
|
|
9141
|
+
}
|
|
9142
|
+
//#endregion
|
|
9143
|
+
|
|
9144
|
+
//#region ---- File type open (catalog → AX registry) ----
|
|
9145
|
+
function createFileTypeOpenContext(injector, platformId) {
|
|
9146
|
+
return {
|
|
9147
|
+
injector,
|
|
9148
|
+
platformId,
|
|
9149
|
+
readAsDataUrl: (file) => new Promise((resolve, reject) => {
|
|
9150
|
+
const reader = new FileReader();
|
|
9151
|
+
reader.onload = () => resolve(reader.result);
|
|
9152
|
+
reader.onerror = () => reject(reader.error);
|
|
9153
|
+
reader.readAsDataURL(file);
|
|
9154
|
+
}),
|
|
9155
|
+
};
|
|
9156
|
+
}
|
|
9157
|
+
function buildFileTypeExtensionHint(fileName, payload) {
|
|
9158
|
+
if (payload instanceof File) {
|
|
9159
|
+
return {
|
|
9160
|
+
file: payload,
|
|
9161
|
+
extensionName: getFileExtension(payload.name) || getFileExtension(fileName) || undefined,
|
|
9162
|
+
};
|
|
9163
|
+
}
|
|
9164
|
+
const extensionName = getFileExtension(fileName) || undefined;
|
|
9165
|
+
if (!payload || typeof payload !== 'object') {
|
|
9166
|
+
return { extensionName };
|
|
9167
|
+
}
|
|
9168
|
+
const record = payload;
|
|
9169
|
+
const itemName = typeof record['name'] === 'string' ? record['name'] : fileName;
|
|
9170
|
+
const resolvedExtension = getFileExtension(itemName) || extensionName;
|
|
9171
|
+
const source = record['source'];
|
|
9172
|
+
if (source?.kind === 'blob' && source.value instanceof Blob) {
|
|
9173
|
+
return {
|
|
9174
|
+
extensionName: resolvedExtension,
|
|
9175
|
+
mimeType: source.value.type || undefined,
|
|
9176
|
+
};
|
|
9177
|
+
}
|
|
9178
|
+
return { extensionName: resolvedExtension };
|
|
9179
|
+
}
|
|
9180
|
+
/**
|
|
9181
|
+
* Returns whether the catalog-resolved file type has an `open` handler on the matched
|
|
9182
|
+
* extension or its parent type (extension-first, per {@link resolveFileTypeOpen}).
|
|
9183
|
+
*/
|
|
9184
|
+
async function hasFileTypeOpenHandler(options) {
|
|
9185
|
+
const display = resolveFileTypeDisplay(options.fileName, options.catalog);
|
|
9186
|
+
const fileType = await options.fileService.getFileType(display.typeName);
|
|
9187
|
+
if (!fileType) {
|
|
9188
|
+
return false;
|
|
9189
|
+
}
|
|
9190
|
+
const extension = resolveFileTypeExtension(fileType, buildFileTypeExtensionHint(options.fileName, options.payload));
|
|
9191
|
+
return typeof resolveFileTypeOpen(fileType, extension) === 'function';
|
|
9192
|
+
}
|
|
9193
|
+
/**
|
|
9194
|
+
* Resolves extension → parent `open` and runs it when present.
|
|
9195
|
+
* Returns `true` when a handler ran; `false` when none exists (caller should download).
|
|
9196
|
+
*/
|
|
9197
|
+
async function tryOpenFileByCatalogType(options) {
|
|
9198
|
+
const display = resolveFileTypeDisplay(options.fileName, options.catalog);
|
|
9199
|
+
const fileType = await options.fileService.getFileType(display.typeName);
|
|
9200
|
+
if (!fileType) {
|
|
9201
|
+
return false;
|
|
9202
|
+
}
|
|
9203
|
+
const extension = resolveFileTypeExtension(fileType, buildFileTypeExtensionHint(options.fileName, options.payload));
|
|
9204
|
+
if (!resolveFileTypeOpen(fileType, extension)) {
|
|
9205
|
+
return false;
|
|
9206
|
+
}
|
|
9207
|
+
const result = await runFileTypeOpen(fileType, options.openContext, options.payload, extension);
|
|
9208
|
+
return result !== false;
|
|
9209
|
+
}
|
|
9210
|
+
//#endregion
|
|
9211
|
+
|
|
9212
|
+
//#region ---- ACoreX file type bridge ----
|
|
9213
|
+
function mapExtension(ext) {
|
|
9214
|
+
return {
|
|
9215
|
+
name: ext.name,
|
|
9216
|
+
title: ext.title ?? ext.name,
|
|
9217
|
+
icon: ext.icon,
|
|
9218
|
+
};
|
|
9219
|
+
}
|
|
9220
|
+
function mapFileType(type) {
|
|
9221
|
+
return {
|
|
9222
|
+
name: type.name,
|
|
9223
|
+
title: type.title ?? type.name,
|
|
9224
|
+
icon: type.icon,
|
|
9225
|
+
metadata: type.metadata ?? { [AX_FILE_TYPE_METADATA_PURPOSE]: getFileTypePurposes(type) },
|
|
9226
|
+
extensions: (type.extensions ?? []).map(mapExtension),
|
|
9227
|
+
};
|
|
9228
|
+
}
|
|
9229
|
+
/**
|
|
9230
|
+
* Bridges {@link AXFileTypeRegistryService} into the platform {@link AXPFileTypeInfoProvider} token.
|
|
9231
|
+
* Excludes conversation-purpose types by default.
|
|
9232
|
+
*/
|
|
9233
|
+
class AXPAcorexFileTypeBridgeProvider {
|
|
9234
|
+
constructor() {
|
|
9235
|
+
this.registry = inject(AXFileTypeRegistryService);
|
|
9236
|
+
}
|
|
9237
|
+
async items(purpose) {
|
|
9238
|
+
const types = await this.registry.getTypes({
|
|
9239
|
+
purpose: normalizeDocumentFileTypePurposes(purpose),
|
|
9240
|
+
});
|
|
9241
|
+
return types.map(mapFileType);
|
|
9242
|
+
}
|
|
9243
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeBridgeProvider, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
9244
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeBridgeProvider }); }
|
|
9245
|
+
}
|
|
9246
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeBridgeProvider, decorators: [{
|
|
9247
|
+
type: Injectable
|
|
9248
|
+
}] });
|
|
9249
|
+
|
|
9250
|
+
//#region ---- ACoreX file type module ----
|
|
9251
|
+
/**
|
|
9252
|
+
* Registers ACoreX built-in file types (image, video, audio, file, document) and exposes them
|
|
9253
|
+
* through the platform {@link AXP_FILE_TYPE_INFO_PROVIDER} token.
|
|
9254
|
+
*/
|
|
9255
|
+
class AXPAcorexFileTypeModule {
|
|
9256
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
9257
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, imports: [i1$1.AXFileModule] }); }
|
|
9258
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, providers: [
|
|
9259
|
+
{
|
|
9260
|
+
provide: AXP_FILE_TYPE_INFO_PROVIDER,
|
|
9261
|
+
useClass: AXPAcorexFileTypeBridgeProvider,
|
|
9262
|
+
multi: true,
|
|
9263
|
+
},
|
|
9264
|
+
], imports: [AXFileModule.forRoot()] }); }
|
|
9265
|
+
}
|
|
9266
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPAcorexFileTypeModule, decorators: [{
|
|
9267
|
+
type: NgModule,
|
|
9268
|
+
args: [{
|
|
9269
|
+
imports: [AXFileModule.forRoot()],
|
|
9270
|
+
providers: [
|
|
9271
|
+
{
|
|
9272
|
+
provide: AXP_FILE_TYPE_INFO_PROVIDER,
|
|
9273
|
+
useClass: AXPAcorexFileTypeBridgeProvider,
|
|
9274
|
+
multi: true,
|
|
9275
|
+
},
|
|
9276
|
+
],
|
|
9277
|
+
}]
|
|
9278
|
+
}] });
|
|
9279
|
+
|
|
9280
|
+
//#region ---- Shared in-app inbox types ----
|
|
9281
|
+
//#endregion
|
|
9282
|
+
|
|
9283
|
+
//#region ---- Shared in-app inbox helpers ----
|
|
9284
|
+
function isInAppInboxUnread(readAt) {
|
|
9285
|
+
return readAt == null;
|
|
9286
|
+
}
|
|
9287
|
+
function isInAppInboxUnseen(seenAt) {
|
|
9288
|
+
return seenAt == null;
|
|
9289
|
+
}
|
|
9290
|
+
function getInAppInboxPriorityClass(priority) {
|
|
9291
|
+
return priority ?? 'Notice';
|
|
9292
|
+
}
|
|
9293
|
+
function normalizeInAppInboxItem(item) {
|
|
9294
|
+
return {
|
|
9295
|
+
id: String(item.id),
|
|
9296
|
+
title: item.title ?? '',
|
|
9297
|
+
body: item.body ?? '',
|
|
9298
|
+
createdAt: item.createdAt ? new Date(item.createdAt) : new Date(),
|
|
9299
|
+
seenAt: item.seenAt ? new Date(item.seenAt) : item.seenAt ?? null,
|
|
9300
|
+
readAt: item.readAt ? new Date(item.readAt) : item.readAt ?? null,
|
|
9301
|
+
sender: item.sender,
|
|
9302
|
+
priority: item.priority ?? 'Notice',
|
|
9303
|
+
isPinned: item.isPinned ?? false,
|
|
9304
|
+
category: item.category,
|
|
9305
|
+
};
|
|
9306
|
+
}
|
|
9307
|
+
//#endregion
|
|
9308
|
+
|
|
9309
|
+
//#region ---- In-app inbox data port ----
|
|
9310
|
+
const AXP_IN_APP_INBOX_PORT = new InjectionToken('AXP_IN_APP_INBOX_PORT');
|
|
9311
|
+
//#endregion
|
|
9312
|
+
|
|
9313
|
+
//#region ---- In-app inbox configuration tokens ----
|
|
9314
|
+
const AXP_IN_APP_INBOX_CONFIG = new InjectionToken('AXP_IN_APP_INBOX_CONFIG');
|
|
9315
|
+
const AXP_IN_APP_INBOX_I18N = new InjectionToken('AXP_IN_APP_INBOX_I18N');
|
|
9316
|
+
//#endregion
|
|
9317
|
+
|
|
9318
|
+
//#region ---- In-app inbox realtime events ----
|
|
9319
|
+
class AXPInAppInboxRealtimeService {
|
|
9320
|
+
constructor() {
|
|
9321
|
+
this.changedSubject = new Subject();
|
|
9322
|
+
this.changed$ = this.changedSubject.asObservable();
|
|
9323
|
+
}
|
|
9324
|
+
notifyChanged(event) {
|
|
9325
|
+
this.changedSubject.next(event);
|
|
9326
|
+
}
|
|
9327
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxRealtimeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
9328
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxRealtimeService, providedIn: 'root' }); }
|
|
9329
|
+
}
|
|
9330
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxRealtimeService, decorators: [{
|
|
9331
|
+
type: Injectable,
|
|
9332
|
+
args: [{
|
|
9333
|
+
providedIn: 'root',
|
|
9334
|
+
}]
|
|
9335
|
+
}] });
|
|
9336
|
+
|
|
9337
|
+
//#region ---- Shared in-app inbox connector ----
|
|
9338
|
+
class AXPInAppInboxConnectorService {
|
|
9339
|
+
constructor() {
|
|
9340
|
+
this.port = inject(AXP_IN_APP_INBOX_PORT);
|
|
9341
|
+
this.realtime = inject(AXPInAppInboxRealtimeService);
|
|
9342
|
+
this.destroyRef = inject(DestroyRef);
|
|
9343
|
+
this.isLoading = signal(false, ...(ngDevMode ? [{ debugName: "isLoading" }] : /* istanbul ignore next */ []));
|
|
9344
|
+
this.pageLoading = signal(false, ...(ngDevMode ? [{ debugName: "pageLoading" }] : /* istanbul ignore next */ []));
|
|
9345
|
+
this.error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
9346
|
+
this.items = signal([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
9347
|
+
this.totalCount = signal(0, ...(ngDevMode ? [{ debugName: "totalCount" }] : /* istanbul ignore next */ []));
|
|
9348
|
+
this.pageItems = signal([], ...(ngDevMode ? [{ debugName: "pageItems" }] : /* istanbul ignore next */ []));
|
|
9349
|
+
this.pageTotalCount = signal(0, ...(ngDevMode ? [{ debugName: "pageTotalCount" }] : /* istanbul ignore next */ []));
|
|
9350
|
+
this.capabilities = this.port.capabilities;
|
|
9351
|
+
this.loading = computed(() => this.isLoading(), ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
9352
|
+
this.pageLoadingState = computed(() => this.pageLoading(), ...(ngDevMode ? [{ debugName: "pageLoadingState" }] : /* istanbul ignore next */ []));
|
|
9353
|
+
this.errorMessage = computed(() => this.error(), ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
9354
|
+
this.inboxList = computed(() => this.items(), ...(ngDevMode ? [{ debugName: "inboxList" }] : /* istanbul ignore next */ []));
|
|
9355
|
+
this.total = computed(() => this.totalCount(), ...(ngDevMode ? [{ debugName: "total" }] : /* istanbul ignore next */ []));
|
|
9356
|
+
this.pagedInboxList = computed(() => this.pageItems(), ...(ngDevMode ? [{ debugName: "pagedInboxList" }] : /* istanbul ignore next */ []));
|
|
9357
|
+
this.pagedTotal = computed(() => this.pageTotalCount(), ...(ngDevMode ? [{ debugName: "pagedTotal" }] : /* istanbul ignore next */ []));
|
|
9358
|
+
this.unreadCount = computed(() => this.items().filter((item) => isInAppInboxUnread(item.readAt)).length, ...(ngDevMode ? [{ debugName: "unreadCount" }] : /* istanbul ignore next */ []));
|
|
9359
|
+
void this.refresh();
|
|
9360
|
+
this.realtime.changed$
|
|
9361
|
+
.pipe(filter((event) => event.type !== 'seen' && event.type !== 'read'), debounceTime(100), takeUntilDestroyed(this.destroyRef))
|
|
9362
|
+
.subscribe(() => {
|
|
9363
|
+
if (!this.isLoading()) {
|
|
9364
|
+
void this.refresh();
|
|
9365
|
+
}
|
|
9366
|
+
});
|
|
9367
|
+
this.realtime.changed$
|
|
9368
|
+
.pipe(filter((event) => event.type === 'seen' || event.type === 'read'), takeUntilDestroyed(this.destroyRef))
|
|
9369
|
+
.subscribe((event) => this.syncEngagement(event.ids, event.type));
|
|
9370
|
+
}
|
|
9371
|
+
async refresh() {
|
|
9372
|
+
try {
|
|
9373
|
+
this.isLoading.set(true);
|
|
9374
|
+
this.error.set(null);
|
|
9375
|
+
const response = await this.port.loadInbox({ skip: 0, take: 1000 });
|
|
9376
|
+
const items = response.items.map((item) => normalizeInAppInboxItem(item));
|
|
9377
|
+
this.items.set(items);
|
|
9378
|
+
this.totalCount.set(response.total);
|
|
9379
|
+
return { items, total: response.total };
|
|
9380
|
+
}
|
|
9381
|
+
catch (err) {
|
|
9382
|
+
this.error.set(err instanceof Error ? err.message : 'Failed to load inbox');
|
|
9383
|
+
this.items.set([]);
|
|
9384
|
+
this.totalCount.set(0);
|
|
9385
|
+
return { items: [], total: 0 };
|
|
9386
|
+
}
|
|
9387
|
+
finally {
|
|
9388
|
+
this.isLoading.set(false);
|
|
9389
|
+
}
|
|
9390
|
+
}
|
|
9391
|
+
async loadPage(skip, take) {
|
|
9392
|
+
try {
|
|
9393
|
+
this.pageLoading.set(true);
|
|
9394
|
+
this.error.set(null);
|
|
9395
|
+
const result = await this.port.loadInbox({ skip, take });
|
|
9396
|
+
const items = result.items.map((item) => normalizeInAppInboxItem(item));
|
|
9397
|
+
this.pageItems.set(items);
|
|
9398
|
+
this.pageTotalCount.set(result.total);
|
|
9399
|
+
return { items, total: result.total };
|
|
9400
|
+
}
|
|
9401
|
+
catch (err) {
|
|
9402
|
+
this.error.set(err instanceof Error ? err.message : 'Failed to load inbox page');
|
|
9403
|
+
this.pageItems.set([]);
|
|
9404
|
+
this.pageTotalCount.set(0);
|
|
9405
|
+
return { items: [], total: 0 };
|
|
9406
|
+
}
|
|
9407
|
+
finally {
|
|
9408
|
+
this.pageLoading.set(false);
|
|
9409
|
+
}
|
|
9410
|
+
}
|
|
9411
|
+
async markUnseenAsSeen() {
|
|
9412
|
+
if (!this.port.capabilities.seenTracking) {
|
|
9413
|
+
return;
|
|
9414
|
+
}
|
|
9415
|
+
const unseenIds = this.items()
|
|
9416
|
+
.filter((item) => isInAppInboxUnseen(item.seenAt))
|
|
9417
|
+
.map((item) => item.id);
|
|
9418
|
+
if (unseenIds.length === 0) {
|
|
9419
|
+
return;
|
|
9420
|
+
}
|
|
9421
|
+
await this.port.markSeen(unseenIds);
|
|
9422
|
+
this.realtime.notifyChanged({ type: 'seen', ids: unseenIds });
|
|
9423
|
+
}
|
|
9424
|
+
async markAsRead(ids) {
|
|
9425
|
+
if (ids.length === 0 || !this.port.capabilities.readTracking) {
|
|
9426
|
+
return;
|
|
9427
|
+
}
|
|
9428
|
+
await this.port.markRead(ids);
|
|
9429
|
+
this.realtime.notifyChanged({ type: 'read', ids });
|
|
9430
|
+
}
|
|
9431
|
+
async markAllAsRead() {
|
|
9432
|
+
if (!this.port.capabilities.readTracking) {
|
|
9433
|
+
return;
|
|
9434
|
+
}
|
|
9435
|
+
await this.port.markAllRead();
|
|
9436
|
+
const readAt = new Date();
|
|
9437
|
+
const patchAll = (list) => list.map((item) => isInAppInboxUnread(item.readAt)
|
|
9438
|
+
? { ...item, readAt, seenAt: item.seenAt ?? readAt }
|
|
9439
|
+
: item);
|
|
9440
|
+
this.items.update(patchAll);
|
|
9441
|
+
this.pageItems.update(patchAll);
|
|
9442
|
+
}
|
|
9443
|
+
async togglePin(id) {
|
|
9444
|
+
if (!this.port.capabilities.pinSupport || !this.port.togglePin) {
|
|
9445
|
+
return;
|
|
9446
|
+
}
|
|
9447
|
+
await this.port.togglePin(id);
|
|
9448
|
+
await this.refresh();
|
|
9449
|
+
}
|
|
9450
|
+
syncEngagement(ids, kind) {
|
|
9451
|
+
if (!ids?.length) {
|
|
9452
|
+
return;
|
|
9453
|
+
}
|
|
9454
|
+
const idSet = new Set(ids);
|
|
9455
|
+
const now = new Date();
|
|
9456
|
+
const patch = (list) => list.map((item) => {
|
|
9457
|
+
if (!idSet.has(item.id)) {
|
|
9458
|
+
return item;
|
|
9459
|
+
}
|
|
9460
|
+
if (kind === 'seen') {
|
|
9461
|
+
return item.seenAt ? item : { ...item, seenAt: now };
|
|
9462
|
+
}
|
|
9463
|
+
return {
|
|
9464
|
+
...item,
|
|
9465
|
+
seenAt: item.seenAt ?? now,
|
|
9466
|
+
readAt: item.readAt ?? now,
|
|
9467
|
+
};
|
|
9468
|
+
});
|
|
9469
|
+
this.items.update(patch);
|
|
9470
|
+
this.pageItems.update(patch);
|
|
9471
|
+
}
|
|
9472
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
9473
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxConnectorService, providedIn: 'root' }); }
|
|
9474
|
+
}
|
|
9475
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPInAppInboxConnectorService, decorators: [{
|
|
9476
|
+
type: Injectable,
|
|
9477
|
+
args: [{
|
|
9478
|
+
providedIn: 'root',
|
|
9479
|
+
}]
|
|
9480
|
+
}], ctorParameters: () => [] });
|
|
9481
|
+
|
|
9482
|
+
const AXP_INTEGRATION_PROVIDER = new InjectionToken('AXP_INTEGRATION_PROVIDER', {
|
|
9483
|
+
providedIn: 'root',
|
|
9484
|
+
factory: () => [],
|
|
9485
|
+
});
|
|
9486
|
+
const AXP_INTEGRATION_RUNTIME_PROVIDER = new InjectionToken('AXP_INTEGRATION_RUNTIME_PROVIDER', {
|
|
9487
|
+
providedIn: 'root',
|
|
9488
|
+
factory: () => [],
|
|
9489
|
+
});
|
|
9490
|
+
//#endregion
|
|
9491
|
+
|
|
9492
|
+
const AXP_INTEGRATION_DOMAIN_PROVIDER = new InjectionToken('AXP_INTEGRATION_DOMAIN_PROVIDER', {
|
|
9493
|
+
providedIn: 'root',
|
|
9494
|
+
factory: () => [],
|
|
9495
|
+
});
|
|
9496
|
+
//#endregion
|
|
9497
|
+
|
|
9498
|
+
//#region ---- Integration domain context ----
|
|
9499
|
+
class AXPIntegrationDomainProviderContext {
|
|
9500
|
+
constructor() {
|
|
9501
|
+
this.definitions = new Map();
|
|
9502
|
+
}
|
|
9503
|
+
register(definition) {
|
|
9504
|
+
// Idempotent: multiple extensions (e.g. Telegram + WhatsApp) may register the same domain.
|
|
9505
|
+
if (this.definitions.has(definition.id)) {
|
|
9506
|
+
return;
|
|
9507
|
+
}
|
|
9508
|
+
this.definitions.set(definition.id, definition);
|
|
9509
|
+
}
|
|
9510
|
+
getDefinitions() {
|
|
9511
|
+
return this.definitions;
|
|
9512
|
+
}
|
|
9513
|
+
}
|
|
9514
|
+
//#endregion
|
|
9515
|
+
|
|
9516
|
+
//#region ---- Integration provider context ----
|
|
9517
|
+
class AXPIntegrationProviderContext {
|
|
9518
|
+
constructor() {
|
|
9519
|
+
//#region ---- State ----
|
|
9520
|
+
this.definitions = new Map();
|
|
9521
|
+
//#endregion
|
|
9522
|
+
}
|
|
9523
|
+
//#endregion
|
|
9524
|
+
//#region ---- Builder API ----
|
|
9525
|
+
/**
|
|
9526
|
+
* Registers a provider definition. Throws when duplicate ids are registered.
|
|
8596
9527
|
*/
|
|
8597
9528
|
register(definition) {
|
|
8598
9529
|
if (this.definitions.has(definition.id)) {
|
|
@@ -8608,49 +9539,125 @@ class AXPIntegrationProviderContext {
|
|
|
8608
9539
|
}
|
|
8609
9540
|
//#endregion
|
|
8610
9541
|
|
|
8611
|
-
//#region ---- Integration
|
|
8612
|
-
class
|
|
9542
|
+
//#region ---- Integration domain registry ----
|
|
9543
|
+
class AXPIntegrationDomainRegistryService {
|
|
8613
9544
|
constructor() {
|
|
8614
|
-
|
|
8615
|
-
this.
|
|
8616
|
-
|
|
8617
|
-
|
|
8618
|
-
this.cache = null;
|
|
9545
|
+
this.domainProviders = inject(AXP_INTEGRATION_DOMAIN_PROVIDER, { optional: true });
|
|
9546
|
+
this.integrationProviders = inject(AXP_INTEGRATION_PROVIDER, { optional: true });
|
|
9547
|
+
this.domainCache = null;
|
|
9548
|
+
this.providerCache = null;
|
|
8619
9549
|
}
|
|
8620
|
-
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
9550
|
+
async listDomains() {
|
|
9551
|
+
const map = await this.loadDomains();
|
|
9552
|
+
return Array.from(map.values()).sort((a, b) => defaultTo(a.sortOrder, 100) - defaultTo(b.sortOrder, 100));
|
|
9553
|
+
}
|
|
9554
|
+
async getDomain(id) {
|
|
9555
|
+
const map = await this.loadDomains();
|
|
9556
|
+
return map.get(id) ?? null;
|
|
9557
|
+
}
|
|
9558
|
+
async getDomainOrThrow(id) {
|
|
9559
|
+
const domain = await this.getDomain(id);
|
|
9560
|
+
if (!domain) {
|
|
9561
|
+
throw new Error(`[AXPIntegrationDomainRegistry] Unknown integration domain '${id}'.`);
|
|
9562
|
+
}
|
|
9563
|
+
return domain;
|
|
9564
|
+
}
|
|
9565
|
+
async listProviders() {
|
|
9566
|
+
const map = await this.loadProviders();
|
|
8624
9567
|
return Array.from(map.values());
|
|
8625
9568
|
}
|
|
8626
|
-
async
|
|
8627
|
-
const
|
|
9569
|
+
async listProvidersByDomain(domainId) {
|
|
9570
|
+
const providers = await this.listProviders();
|
|
9571
|
+
return providers.filter((provider) => provider.domainId === domainId);
|
|
9572
|
+
}
|
|
9573
|
+
async getProvider(id) {
|
|
9574
|
+
const map = await this.loadProviders();
|
|
8628
9575
|
return map.get(id) ?? null;
|
|
8629
9576
|
}
|
|
8630
|
-
async
|
|
8631
|
-
const
|
|
8632
|
-
if (!
|
|
8633
|
-
throw new Error(`[
|
|
9577
|
+
async getProviderOrThrow(id) {
|
|
9578
|
+
const provider = await this.getProvider(id);
|
|
9579
|
+
if (!provider) {
|
|
9580
|
+
throw new Error(`[AXPIntegrationDomainRegistry] Unknown integration provider '${id}'.`);
|
|
8634
9581
|
}
|
|
8635
|
-
return
|
|
9582
|
+
return provider;
|
|
8636
9583
|
}
|
|
8637
9584
|
clearCache() {
|
|
8638
|
-
this.
|
|
9585
|
+
this.domainCache = null;
|
|
9586
|
+
this.providerCache = null;
|
|
8639
9587
|
}
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
9588
|
+
normalizeProviders(providers) {
|
|
9589
|
+
if (!providers) {
|
|
9590
|
+
return [];
|
|
9591
|
+
}
|
|
9592
|
+
return Array.isArray(providers) ? providers : [providers];
|
|
9593
|
+
}
|
|
9594
|
+
async loadDomains() {
|
|
9595
|
+
if (this.domainCache) {
|
|
9596
|
+
return this.domainCache;
|
|
9597
|
+
}
|
|
9598
|
+
const context = new AXPIntegrationDomainProviderContext();
|
|
9599
|
+
for (const provider of this.normalizeProviders(this.domainProviders)) {
|
|
9600
|
+
const resolved = provider instanceof Promise ? await provider : provider;
|
|
9601
|
+
await resolved.provide(context);
|
|
8645
9602
|
}
|
|
9603
|
+
this.domainCache = new Map(context.getDefinitions());
|
|
9604
|
+
return this.domainCache;
|
|
9605
|
+
}
|
|
9606
|
+
async loadProviders() {
|
|
9607
|
+
if (this.providerCache) {
|
|
9608
|
+
return this.providerCache;
|
|
9609
|
+
}
|
|
9610
|
+
const domains = await this.loadDomains();
|
|
8646
9611
|
const context = new AXPIntegrationProviderContext();
|
|
8647
|
-
const
|
|
8648
|
-
for (const provider of providerList) {
|
|
9612
|
+
for (const provider of this.normalizeProviders(this.integrationProviders)) {
|
|
8649
9613
|
const resolved = provider instanceof Promise ? await provider : provider;
|
|
8650
9614
|
await resolved.provide(context);
|
|
8651
9615
|
}
|
|
8652
|
-
|
|
8653
|
-
|
|
9616
|
+
const resolvedProviders = new Map();
|
|
9617
|
+
for (const definition of context.getDefinitions().values()) {
|
|
9618
|
+
resolvedProviders.set(definition.id, this.resolveProviderDefinition(definition, domains));
|
|
9619
|
+
}
|
|
9620
|
+
this.providerCache = resolvedProviders;
|
|
9621
|
+
return this.providerCache;
|
|
9622
|
+
}
|
|
9623
|
+
resolveProviderDefinition(definition, domains) {
|
|
9624
|
+
const domain = domains.get(definition.domainId);
|
|
9625
|
+
if (!domain) {
|
|
9626
|
+
throw new Error(`[AXPIntegrationDomainRegistry] Provider '${definition.id}' references unknown domain '${definition.domainId}'.`);
|
|
9627
|
+
}
|
|
9628
|
+
const domainCapabilities = defaultTo(domain.capabilities, []);
|
|
9629
|
+
const providerCapabilities = defaultTo(definition.capabilities, []);
|
|
9630
|
+
return {
|
|
9631
|
+
...definition,
|
|
9632
|
+
category: domain.category,
|
|
9633
|
+
capabilities: uniq([...domainCapabilities, ...providerCapabilities]),
|
|
9634
|
+
};
|
|
9635
|
+
}
|
|
9636
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
9637
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryService, providedIn: 'root' }); }
|
|
9638
|
+
}
|
|
9639
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryService, decorators: [{
|
|
9640
|
+
type: Injectable,
|
|
9641
|
+
args: [{ providedIn: 'root' }]
|
|
9642
|
+
}] });
|
|
9643
|
+
|
|
9644
|
+
//#region ---- Integration provider registry ----
|
|
9645
|
+
/** @deprecated Use {@link AXPIntegrationDomainRegistryService} for domain-aware provider access. */
|
|
9646
|
+
class AXPIntegrationProviderRegistryService {
|
|
9647
|
+
constructor() {
|
|
9648
|
+
this.domainRegistry = inject(AXPIntegrationDomainRegistryService);
|
|
9649
|
+
}
|
|
9650
|
+
async list() {
|
|
9651
|
+
return this.domainRegistry.listProviders();
|
|
9652
|
+
}
|
|
9653
|
+
async get(id) {
|
|
9654
|
+
return this.domainRegistry.getProvider(id);
|
|
9655
|
+
}
|
|
9656
|
+
async getOrThrow(id) {
|
|
9657
|
+
return this.domainRegistry.getProviderOrThrow(id);
|
|
9658
|
+
}
|
|
9659
|
+
clearCache() {
|
|
9660
|
+
this.domainRegistry.clearCache();
|
|
8654
9661
|
}
|
|
8655
9662
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationProviderRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8656
9663
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationProviderRegistryService, providedIn: 'root' }); }
|
|
@@ -8659,6 +9666,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8659
9666
|
type: Injectable,
|
|
8660
9667
|
args: [{ providedIn: 'root' }]
|
|
8661
9668
|
}] });
|
|
9669
|
+
/** Convenience alias for domain listing. */
|
|
9670
|
+
class AXPIntegrationDomainRegistryFacade {
|
|
9671
|
+
constructor() {
|
|
9672
|
+
this.domainRegistry = inject(AXPIntegrationDomainRegistryService);
|
|
9673
|
+
}
|
|
9674
|
+
listDomains() {
|
|
9675
|
+
return this.domainRegistry.listDomains();
|
|
9676
|
+
}
|
|
9677
|
+
listProvidersByDomain(domainId) {
|
|
9678
|
+
return this.domainRegistry.listProvidersByDomain(domainId);
|
|
9679
|
+
}
|
|
9680
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryFacade, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
9681
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryFacade, providedIn: 'root' }); }
|
|
9682
|
+
}
|
|
9683
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIntegrationDomainRegistryFacade, decorators: [{
|
|
9684
|
+
type: Injectable,
|
|
9685
|
+
args: [{ providedIn: 'root' }]
|
|
9686
|
+
}] });
|
|
8662
9687
|
|
|
8663
9688
|
const AXP_INTEGRATION_SECRET_STORE = new InjectionToken('AXP_INTEGRATION_SECRET_STORE');
|
|
8664
9689
|
class AXPIntegrationRuntimeService {
|
|
@@ -8860,7 +9885,7 @@ class AXPStatusDefinitionProviderService {
|
|
|
8860
9885
|
// Execute the command
|
|
8861
9886
|
const result = await this.commandService.execute(commandName, commandOptions);
|
|
8862
9887
|
if (!result?.success) {
|
|
8863
|
-
const text =
|
|
9888
|
+
const text = commandMessageTextForError(result?.message?.text);
|
|
8864
9889
|
throw new Error(text || 'Failed to execute status transition command');
|
|
8865
9890
|
}
|
|
8866
9891
|
}
|
|
@@ -8871,23 +9896,6 @@ class AXPStatusDefinitionProviderService {
|
|
|
8871
9896
|
isValidTransition(provider, from, to) {
|
|
8872
9897
|
return provider.transitions.some((transition) => transition.from === from && transition.to === to);
|
|
8873
9898
|
}
|
|
8874
|
-
/**
|
|
8875
|
-
* Best-effort plain string for {@link Error} messages (no i18n lookup).
|
|
8876
|
-
*/
|
|
8877
|
-
commandMessageTextForError(value) {
|
|
8878
|
-
if (value == null) {
|
|
8879
|
-
return '';
|
|
8880
|
-
}
|
|
8881
|
-
if (typeof value === 'string') {
|
|
8882
|
-
return value;
|
|
8883
|
-
}
|
|
8884
|
-
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
8885
|
-
const values = Object.values(value);
|
|
8886
|
-
const first = values.find((v) => typeof v === 'string' && v.length > 0);
|
|
8887
|
-
return first ?? '';
|
|
8888
|
-
}
|
|
8889
|
-
return String(value);
|
|
8890
|
-
}
|
|
8891
9899
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
8892
9900
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPStatusDefinitionProviderService, providedIn: 'root' }); }
|
|
8893
9901
|
}
|
|
@@ -8899,6 +9907,76 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
8899
9907
|
//#region ---- Types ----
|
|
8900
9908
|
//#endregion
|
|
8901
9909
|
|
|
9910
|
+
//#endregion
|
|
9911
|
+
//#region ---- Constants ----
|
|
9912
|
+
const SESSION_KEY_PREFIX = 'axp-entity-list-return:';
|
|
9913
|
+
//#endregion
|
|
9914
|
+
//#region ---- Route Parsing ----
|
|
9915
|
+
/** Parses an entity master list route (`.../m/{module}/e/{entity}/list`). */
|
|
9916
|
+
function axpParseEntityListRoute(url) {
|
|
9917
|
+
const path = url.split('?')[0].split('#')[0];
|
|
9918
|
+
const match = path.match(/\/m\/([^/]+)\/e\/([^/]+)\/list$/);
|
|
9919
|
+
if (!match) {
|
|
9920
|
+
return null;
|
|
9921
|
+
}
|
|
9922
|
+
return {
|
|
9923
|
+
module: decodeURIComponent(match[1]),
|
|
9924
|
+
entity: decodeURIComponent(match[2]),
|
|
9925
|
+
};
|
|
9926
|
+
}
|
|
9927
|
+
/** Parses an entity details route (`.../m/{module}/e/{entity}/{id}/view`). */
|
|
9928
|
+
function axpParseEntityDetailsRoute(url) {
|
|
9929
|
+
const path = url.split('?')[0].split('#')[0];
|
|
9930
|
+
const match = path.match(/\/m\/([^/]+)\/e\/([^/]+)\/([^/]+)\/view$/);
|
|
9931
|
+
if (!match) {
|
|
9932
|
+
return null;
|
|
9933
|
+
}
|
|
9934
|
+
return {
|
|
9935
|
+
module: decodeURIComponent(match[1]),
|
|
9936
|
+
entity: decodeURIComponent(match[2]),
|
|
9937
|
+
id: decodeURIComponent(match[3]),
|
|
9938
|
+
};
|
|
9939
|
+
}
|
|
9940
|
+
//#endregion
|
|
9941
|
+
//#region ---- Session Storage ----
|
|
9942
|
+
function buildStorageKey(module, entity) {
|
|
9943
|
+
return `${SESSION_KEY_PREFIX}${module}.${entity}`;
|
|
9944
|
+
}
|
|
9945
|
+
/** Persists the last list URL (including query params) used before opening entity details. */
|
|
9946
|
+
function axpSaveEntityListReturnUrl(module, entity, url) {
|
|
9947
|
+
if (!axpIsEntityListPath(url)) {
|
|
9948
|
+
return;
|
|
9949
|
+
}
|
|
9950
|
+
const parsed = axpParseEntityListRoute(url);
|
|
9951
|
+
if (!parsed || parsed.module !== module || parsed.entity !== entity) {
|
|
9952
|
+
return;
|
|
9953
|
+
}
|
|
9954
|
+
try {
|
|
9955
|
+
sessionStorage.setItem(buildStorageKey(module, entity), normalizeRouterUrl(url));
|
|
9956
|
+
}
|
|
9957
|
+
catch {
|
|
9958
|
+
// sessionStorage may be unavailable
|
|
9959
|
+
}
|
|
9960
|
+
}
|
|
9961
|
+
/** Returns the stored list URL for the entity, or the provided fallback path. */
|
|
9962
|
+
function axpGetEntityListReturnUrl(module, entity, fallbackPath) {
|
|
9963
|
+
try {
|
|
9964
|
+
const stored = sessionStorage.getItem(buildStorageKey(module, entity));
|
|
9965
|
+
if (!stored || !axpIsEntityListPath(stored)) {
|
|
9966
|
+
return fallbackPath;
|
|
9967
|
+
}
|
|
9968
|
+
const parsed = axpParseEntityListRoute(stored);
|
|
9969
|
+
if (parsed?.module === module && parsed.entity === entity) {
|
|
9970
|
+
return stored;
|
|
9971
|
+
}
|
|
9972
|
+
}
|
|
9973
|
+
catch {
|
|
9974
|
+
// sessionStorage may be unavailable
|
|
9975
|
+
}
|
|
9976
|
+
return fallbackPath;
|
|
9977
|
+
}
|
|
9978
|
+
//#endregion
|
|
9979
|
+
|
|
8902
9980
|
class AXPClipBoardService {
|
|
8903
9981
|
constructor() {
|
|
8904
9982
|
//#region ---- Services & Dependencies ----
|
|
@@ -9252,9 +10330,9 @@ class AXMOrgChartPrintPage extends AXBasePageComponent {
|
|
|
9252
10330
|
});
|
|
9253
10331
|
}
|
|
9254
10332
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMOrgChartPrintPage, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
9255
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AXMOrgChartPrintPage, isStandalone: true, selector: "ng-component", inputs: { bgcolor: { classPropertyName: "bgcolor", publicName: "bgcolor", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bgcolor: "bgcolorChange", width: "widthChange", height: "heightChange", quality: "qualityChange", scale: "scaleChange" }, usesInheritance: true, ngImport: i0, template: ` <div class="
|
|
10333
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: AXMOrgChartPrintPage, isStandalone: true, selector: "ng-component", inputs: { bgcolor: { classPropertyName: "bgcolor", publicName: "bgcolor", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null }, scale: { classPropertyName: "scale", publicName: "scale", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { bgcolor: "bgcolorChange", width: "widthChange", height: "heightChange", quality: "qualityChange", scale: "scaleChange" }, usesInheritance: true, ngImport: i0, template: ` <div class="grid grid-cols-[auto_18rem] gap-4 justify-center p-4 items-center">
|
|
9256
10334
|
<ax-label>Resolution (px)</ax-label>
|
|
9257
|
-
<div class="
|
|
10335
|
+
<div class="flex gap-2 items-center">
|
|
9258
10336
|
<ax-number-box
|
|
9259
10337
|
[changeOnScroll]="true"
|
|
9260
10338
|
[decimals]="4"
|
|
@@ -9301,14 +10379,14 @@ class AXMOrgChartPrintPage extends AXBasePageComponent {
|
|
|
9301
10379
|
<ax-icon class="fa-solid fa-print"> </ax-icon>
|
|
9302
10380
|
</ax-button>
|
|
9303
10381
|
</ax-suffix>
|
|
9304
|
-
</ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$
|
|
10382
|
+
</ax-footer>`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "ngmodule", type: AXNumberBoxModule }, { kind: "component", type: i2$2.AXNumberBoxComponent, selector: "ax-number-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "minValue", "maxValue", "showSpinButtons", "thousandsSeparator", "decimals", "changeOnScroll", "step"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "thousandsSeparatorChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3$2.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i4.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i4.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: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXColorBoxModule }, { kind: "component", type: i6.AXColorBoxComponent, selector: "ax-color-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "showBadge", "showValue", "showClearButton", "showIcon"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed"] }] }); }
|
|
9305
10383
|
}
|
|
9306
10384
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMOrgChartPrintPage, decorators: [{
|
|
9307
10385
|
type: Component,
|
|
9308
10386
|
args: [{
|
|
9309
|
-
template: ` <div class="
|
|
10387
|
+
template: ` <div class="grid grid-cols-[auto_18rem] gap-4 justify-center p-4 items-center">
|
|
9310
10388
|
<ax-label>Resolution (px)</ax-label>
|
|
9311
|
-
<div class="
|
|
10389
|
+
<div class="flex gap-2 items-center">
|
|
9312
10390
|
<ax-number-box
|
|
9313
10391
|
[changeOnScroll]="true"
|
|
9314
10392
|
[decimals]="4"
|
|
@@ -9459,9 +10537,99 @@ class AXPVersioningService {
|
|
|
9459
10537
|
}
|
|
9460
10538
|
//#endregion
|
|
9461
10539
|
|
|
10540
|
+
//#endregion
|
|
10541
|
+
//#region ---- Helpers ----
|
|
10542
|
+
function axpResolveNavigatePath(input) {
|
|
10543
|
+
if (!input) {
|
|
10544
|
+
return undefined;
|
|
10545
|
+
}
|
|
10546
|
+
if (typeof input.options?.path === 'string') {
|
|
10547
|
+
return input.options.path;
|
|
10548
|
+
}
|
|
10549
|
+
if (typeof input.path === 'string') {
|
|
10550
|
+
return input.path;
|
|
10551
|
+
}
|
|
10552
|
+
return undefined;
|
|
10553
|
+
}
|
|
10554
|
+
function axpResolveNavigateExtras(input) {
|
|
10555
|
+
return input?.options?.extras;
|
|
10556
|
+
}
|
|
10557
|
+
//#endregion
|
|
10558
|
+
//#region ---- Navigate Command ----
|
|
10559
|
+
class AXPNavigateCommand {
|
|
10560
|
+
constructor() {
|
|
10561
|
+
this.tabNavigation = inject(AXPTabNavigationService);
|
|
10562
|
+
}
|
|
10563
|
+
async execute(input = {}) {
|
|
10564
|
+
const path = axpResolveNavigatePath(input);
|
|
10565
|
+
if (!path) {
|
|
10566
|
+
console.error('Path is required for navigate command');
|
|
10567
|
+
return {
|
|
10568
|
+
success: false,
|
|
10569
|
+
message: {
|
|
10570
|
+
text: 'Path is required for navigate command',
|
|
10571
|
+
},
|
|
10572
|
+
};
|
|
10573
|
+
}
|
|
10574
|
+
const extras = axpResolveNavigateExtras(input);
|
|
10575
|
+
if (path.toLowerCase().startsWith('http') || extras?.target === 'blank') {
|
|
10576
|
+
window.open(path, '_blank');
|
|
10577
|
+
}
|
|
10578
|
+
else {
|
|
10579
|
+
await this.tabNavigation.navigate(path, extras);
|
|
10580
|
+
}
|
|
10581
|
+
return { success: true };
|
|
10582
|
+
}
|
|
10583
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavigateCommand, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
10584
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavigateCommand, providedIn: 'root' }); }
|
|
10585
|
+
}
|
|
10586
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPNavigateCommand, decorators: [{
|
|
10587
|
+
type: Injectable,
|
|
10588
|
+
args: [{ providedIn: 'root' }]
|
|
10589
|
+
}] });
|
|
10590
|
+
|
|
10591
|
+
var navigate_command = /*#__PURE__*/Object.freeze({
|
|
10592
|
+
__proto__: null,
|
|
10593
|
+
AXPNavigateCommand: AXPNavigateCommand,
|
|
10594
|
+
axpResolveNavigatePath: axpResolveNavigatePath
|
|
10595
|
+
});
|
|
10596
|
+
|
|
10597
|
+
/**
|
|
10598
|
+
* Build-time only. Do not import from Angular modules.
|
|
10599
|
+
*/
|
|
10600
|
+
const axpNavigateCommandDefinition = defineCommand({
|
|
10601
|
+
key: 'navigate',
|
|
10602
|
+
title: 'Navigate',
|
|
10603
|
+
description: 'AXPNavigateCommand resolves a router path from input.path or input.options.path, opens external URLs in a new tab, otherwise navigates via AXPTabNavigationService.',
|
|
10604
|
+
executionMode: 'frontend',
|
|
10605
|
+
inputs: [
|
|
10606
|
+
{
|
|
10607
|
+
name: 'path',
|
|
10608
|
+
title: 'Path',
|
|
10609
|
+
description: 'Router path or absolute URL (AXPNavigateCommandInput.path or input.options.path).',
|
|
10610
|
+
interface: { name: 'text-editor' },
|
|
10611
|
+
validations: [{ rule: 'required' }],
|
|
10612
|
+
},
|
|
10613
|
+
],
|
|
10614
|
+
outcomes: {
|
|
10615
|
+
mode: 'static',
|
|
10616
|
+
values: ['success', 'failure'],
|
|
10617
|
+
},
|
|
10618
|
+
ai: {
|
|
10619
|
+
tags: ['navigation', 'router'],
|
|
10620
|
+
},
|
|
10621
|
+
categories: [AXP_COMMAND_DEFINITION_CATEGORY_PLATFORM],
|
|
10622
|
+
});
|
|
10623
|
+
|
|
10624
|
+
const AXP_ENTITY_DELETED_EVENT_TYPE = '[Entity] Deleted';
|
|
10625
|
+
|
|
10626
|
+
const AXPRedirectEvent = createWorkFlowEvent('Redirect Event Fired');
|
|
10627
|
+
const AXPRefreshEvent = createWorkFlowEvent('Refresh Event Fired');
|
|
10628
|
+
const AXPReloadEvent = createWorkFlowEvent('Reload Event Fired');
|
|
10629
|
+
|
|
9462
10630
|
/**
|
|
9463
10631
|
* Generated bundle index. Do not edit.
|
|
9464
10632
|
*/
|
|
9465
10633
|
|
|
9466
|
-
export { ALL_DEFAULT_OPERATORS,
|
|
10634
|
+
export { ALL_DEFAULT_OPERATORS, AXPAcorexFileTypeBridgeProvider, AXPAcorexFileTypeModule, AXPAppVersionService, AXPBackgroundOperationCompletionService, AXPBackgroundOperationEntityStoreService, AXPBackgroundOperationHandler, AXPBackgroundOperationNotificationService, AXPBackgroundOperationProvider, AXPBackgroundOperationRootConfig, AXPBackgroundOperationService, AXPBackgroundOperationSlotComponent, AXPBrowserTitleService, AXPCleanNestedFilters, AXPClipBoardService, AXPCommonModule, AXPCommonSettings, AXPCustomOperatorService, AXPCustomOperatorServiceImpl, AXPDataProvider, AXPDefaultMultiLanguageConfigService, AXPErrorHandlerRegistryService, AXPExportService, AXPFileActionsService, AXPFileStorageEvaluatorScopeProvider, AXPFileStorageService, AXPFileTypeProviderService, AXPFilterOperatorMiddlewareService, AXPFilterOperatorMiddlewareServiceImpl, AXPFooterTextSlotComponent, AXPGlobalErrorHandler, AXPHomePageModule, AXPHomePageService, AXPInAppInboxConnectorService, AXPInAppInboxRealtimeService, AXPIndexedDbSettingValueProvider, AXPIntegrationDomainProviderContext, AXPIntegrationDomainRegistryFacade, AXPIntegrationDomainRegistryService, AXPIntegrationOAuthService, AXPIntegrationProviderContext, AXPIntegrationProviderRegistryService, AXPIntegrationRuntimeService, AXPKeyboardShortcutsHelpComponent, AXPKeyboardShortcutsHelpService, AXPLockService, AXPLogoImageSrcResolverService, AXPMenuItemsDataSourceDefinition, AXPMenuKeyboardShortcutService, AXPMenuMiddlewareRegistry, AXPMenuProviderService, AXPMenuRouteAccessService, AXPMenuRouteGuard, AXPMenuSearchDefinitionProvider, AXPMenuSearchProvider, AXPMenuService, AXPMenuVisibilityService, AXPNavBarSlotComponent, AXPNavigateCommand, AXPNotFoundCatchAllRoute, AXPNotFoundError, AXPOutputContractTranscriptSegmentService, AXPPlatformCommonDataSourceKeys, AXPPlatformDefaultConfigs, AXPQueryParamsEvaluatorScopeProvider, AXPRedirectEvent, AXPRefreshEvent, AXPRegionalCalendarService, AXPReloadEvent, AXPSearchCommandProvider, AXPSearchDefinitionActionBuilder, AXPSearchDefinitionBuilder, AXPSearchDefinitionProviderContext, AXPSearchDefinitionProviderService, AXPSearchService, AXPSettingDefaultValuesAggregatorService, AXPSettingDefinitionGroupBuilder, AXPSettingDefinitionProviderContext, AXPSettingDefinitionProviderService, AXPSettingDefinitionSectionBuilder, AXPSettingsBulkSyncService, AXPSettingsEvaluatorScopeProvider, AXPSettingsIndexedDb, AXPSettingsService, AXPStatusDefinitionProviderService, AXPStickyDirective, AXPTabNavigationService, AXPTabPreviewService, AXPTabRouteCacheRegistry, AXPTokenDefinitionService, AXPTokenEvaluatorScopeProvider, AXPTranslateFormatter, AXPUnsavedChangesConfirmService, AXPUnsavedChangesPopstateService, AXPVersioningService, AXP_AGENT_OUTPUT_CONTRACT_DEFAULT_STRUCTURED_RETRIES, AXP_APP_VERSION_PROVIDER, AXP_BACKGROUND_OPERATION_ENTITY_STORAGE, AXP_BACKGROUND_OPERATION_HANDLERS, AXP_BACKGROUND_OPERATION_PROVIDERS, AXP_DOCUMENT_FILE_TYPE_PURPOSES, AXP_ENTITY_DELETED_EVENT_TYPE, AXP_EXPERIENCE_SETTINGS_GROUP, AXP_EXPERIENCE_SETTINGS_SECTIONS, AXP_FILE_ACTION_PROVIDER, AXP_FILE_TYPE_INFO_PROVIDER, AXP_HOME_PAGES, AXP_HOME_PAGE_DEFAULT_KEY, AXP_HOME_TAB_KEY, AXP_INTEGRATION_CONNECTION_ESTABLISHED, AXP_INTEGRATION_DOMAIN_PROVIDER, AXP_INTEGRATION_OAUTH_SERVICE, AXP_INTEGRATION_PROVIDER, AXP_INTEGRATION_RUNTIME_PROVIDER, AXP_INTEGRATION_SECRET_STORE, AXP_IN_APP_INBOX_CONFIG, AXP_IN_APP_INBOX_I18N, AXP_IN_APP_INBOX_PORT, AXP_IN_APP_NOTIFICATION_SERVICE, AXP_LOCALE_MANAGEMENT_PORT, AXP_MENU_MIDDLEWARE, AXP_MENU_PROVIDER, AXP_NOT_FOUND_CATCH_ALL_ROUTE, AXP_NOT_FOUND_ROUTE, AXP_OUTPUT_CONTRACT_TRANSCRIPT_SEGMENT_PROVIDER, AXP_PLATFORM_CONFIG_TOKEN, AXP_PROTECTED_ROUTE_GUARDS, AXP_ROOT_CONFIG_TOKEN, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_PROVIDER, AXP_SETTINGS_CACHE_SYNC, AXP_SETTINGS_SYNC_DEBOUNCE_MS, AXP_SETTINGS_SYNC_KEYS, AXP_SETTINGS_SYNC_RETRY_BACKOFF_MS, AXP_SETTINGS_SYNC_TTL_MS, AXP_SETTING_DEFAULT_VALUES_PROVIDERS, AXP_SETTING_DEFINITION_PROVIDER, AXP_SETTING_SCOPE_DESCENDANTS, AXP_SETTING_VALUE_PROVIDER, AXP_STATUS_PROVIDERS, AXP_TAB_BREADCRUMB_JOIN_SEPARATOR, AXP_TAB_ROUTE_DATA_KEY, AXP_TOKEN_DEFINITION_PROVIDER, AXP_UNAUTHORIZED_ROUTE, AXVChangeType, BETWEEN_OPER, BOOLEAN_OPERATORS, CONTAINS_OPER, DATE_OPERATORS, DEFAULT_DATE_FILTER_PRESETS, DEFAULT_MULTILANGUAGE_FIELD_NAMES, ENDS_WITH_OPER, ENVIRONMENT, EQ_OPER, GALLERY_MEDIA_EXTENSIONS, GTE_OPER, GT_OPER, IN_OPER, IS_EMPTY_OPER, IS_NOT_EMPTY_OPER, LTE_OPER, LT_OPER, MULTILANGUAGE_CAPABLE_WIDGET_TYPES, NOT_CONTAINS_OPER, NOT_EQ_OPER, NUMBER_OPERATORS, SETTINGS_TRACE_NS, SETTINGS_TRACE_TITLE, STARTS_WITH_OPER, STRING_OPERATORS, UploadFromComputerActionProvider, applyDateFilterPreset, axpBackgroundOperationCapabilities, axpBackgroundOperationDisplayTime, axpBackgroundOperationEntityName, axpBackgroundOperationEstimateEndDate, axpBackgroundOperationFailurePolicy, axpBackgroundOperationFromEntityModel, axpBackgroundOperationRemainingMs, axpBackgroundOperationToEntityModel, axpBuildBackgroundOperation, axpBuildTabKey, axpCoerceBackgroundOperationDate, axpCreateBackgroundOperationId, axpFallbackTabTitle, axpFindMenuItemByRoute, axpGetEntityListReturnUrl, axpGetLeafRouteSnapshot, axpHasTabScope, axpIsActiveBackgroundOperationStatus, axpIsCompletedBackgroundOperationStatus, axpIsEntityDetailsPath, axpIsEntityDetailsViewRoute, axpIsEntityListPath, axpIsEntityListRoute, axpIsEntityRecordNotFound, axpIsTabEligibleUrl, axpJoinTabTitleSegments, axpMenuPathsMatch, axpNavigateAppPath, axpNavigateCommandDefinition, axpParseAppPath, axpParseEntityDetailsRoute, axpParseEntityListRoute, axpPathFromSnapshot, axpRedirectToNotFound, axpRedirectToUnauthorized, axpReplaceEntityListRouteQueryParams, axpResolveNavigatePath, axpResolveTabKey, axpResolveTabKeyFromRouteConfig, axpResolveTabKeyFromSnapshot, axpResolveTabTitleParts, axpSaveEntityListReturnUrl, axpSettingsIndexedDb, backgroundOperationEntityFactory, buildScopedSettingsSnapshotId, chooseSystemFiles, coerceAXPSettingRawValue, coerceAXPSettingRawValueByKind, commandMessageTextForError, configPlatform, createBackgroundOperationStore, createDefaultSettingValueProviders, createEmptyScopedSettingsSnapshot, createEntityCommandOptions, createEntityRowExpressionScope, createEntitySearchCommand, createFileTypeOpenContext, createIndexedDbSettingValueProviders, createMenuContext, createMenuMiddleware, createUnsavedChangesCanDeactivateGuard, downloadGraphicFromElement, evaluateEntityDisplayTemplate, extractFileExtension, extractHttpRequestErrorInfo, findManualPresetIdByOperation, formatEntityRowDisplayTitle, formatRequestError, getInAppInboxPriorityClass, hasFileTypeOpenHandler, inferSettingCoercionKind, isGalleryMediaExtension, isInAppInboxUnread, isInAppInboxUnseen, isSettingVisibleOnScope, isStoredImageFileId, normalizeDocumentFileTypePurposes, normalizeDocumentToFileListItem, normalizeInAppInboxItem, normalizeOverridableAt, normalizePositiveNumberOption, normalizeRouterUrl, normalizeStoredImageRef, peelSettingValueKey, printGraphicFromElement, provideDynamicHomePage, provideMenuMiddleware, purgeNonUserScopedSettingsSnapshots, resolveDateFilterPresets, resolveEntityCreateListBehavior, resolveEntityModifyPopupTitle, resolveEntityRowDisplayText, resolveEntityRowDisplayTitle, resolveEntityRowDisplayTitleFromColumnContext, resolveEntitySearchTitleFallback, resolveExplorerFileDisplayName, resolveFileTypeDisplay, resolveGraphicElementSize, resolveGraphicPrintContent, resolveMediaViewerType, resolveQueryMatchingDisplayText, resolveSearchDisplayTemplate, resolveSearchableText, resolveStoredImageDisplayUrl, searchInRecordValues, searchInSearchableValue, serializeSvgElement, shouldApplyDefaultMultiLanguageToEntityProperty, shouldApplyDefaultMultiLanguageToWidgetNode, shouldApplyDefaultMultiLanguageToWidgetProperty, shouldPersistSettingsInIndexedDb, traceSettingsAppStartupLoadComplete, traceSettingsAppStartupLoadStarted, traceSettingsClientTool, traceSettingsFlush, traceSettingsLocalPersist, traceSettingsPageLoadComplete, traceSettingsPageLoadStarted, traceSettingsPageRouteLoad, traceSettingsRetryScheduled, traceSettingsRevalidateFailed, traceSettingsServerApiCall, traceSettingsServiceLoadComplete, traceSettingsServiceLoadFailed, traceSettingsServiceLoadStarted, traceSettingsServiceReload, traceSettingsSyncFailed, triggerBrowserDownload, tryOpenFileByCatalogType, withDefaultMultiLanguageOnWidgetNodeTree, withDefaultMultiLanguageOnWidgetProperty };
|
|
9467
10635
|
//# sourceMappingURL=acorex-platform-framework-client-common.mjs.map
|