@acorex/platform 20.9.11 → 20.9.13
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-common.mjs +113 -28
- package/fesm2022/acorex-platform-common.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-entity.mjs +54 -0
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-themes-default.mjs +12 -3
- package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
- package/package.json +1 -1
- package/types/acorex-platform-common.d.ts +1 -0
- package/types/acorex-platform-layout-entity.d.ts +16 -1
|
@@ -2908,6 +2908,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
2908
2908
|
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=\"ax-bg-lightest ax-rounded-md ax-w-full\">\n <axp-background-operation-panel (onClosePopover)=\"closePopover()\"></axp-background-operation-panel>\n </div>\n </ax-popover>\n}\n", styles: ["axp-background-operation-slot{display:inline-flex}.operation-slot__trigger{display:inline-flex;cursor:pointer;align-items:center;gap:.375rem;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:.875rem;line-height:1.25rem}.operation-slot__text{font-size:.875rem;line-height:1.25rem;font-weight:500}\n"] }]
|
|
2909
2909
|
}], propDecorators: { popover: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPopoverComponent), { isSignal: true }] }] } });
|
|
2910
2910
|
|
|
2911
|
+
const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
|
|
2912
|
+
const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
|
|
2913
|
+
providedIn: 'root',
|
|
2914
|
+
factory: () => {
|
|
2915
|
+
return AXPPlatformDefaultConfigs;
|
|
2916
|
+
},
|
|
2917
|
+
});
|
|
2918
|
+
const AXPPlatformDefaultConfigs = {
|
|
2919
|
+
copyright: 'ACoreX @ 2024',
|
|
2920
|
+
title: 'ACoreX Platform',
|
|
2921
|
+
network: {
|
|
2922
|
+
timeOut: 5000,
|
|
2923
|
+
},
|
|
2924
|
+
};
|
|
2925
|
+
function configPlatform(config = AXPPlatformDefaultConfigs) {
|
|
2926
|
+
return merge(AXPPlatformDefaultConfigs, config);
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2911
2929
|
//#endregion
|
|
2912
2930
|
//#region ---- App Path Navigation ----
|
|
2913
2931
|
/**
|
|
@@ -2983,6 +3001,8 @@ function axpReplaceEntityListRouteQueryParams(router, queryParams) {
|
|
|
2983
3001
|
//#endregion
|
|
2984
3002
|
|
|
2985
3003
|
const DEFAULT_TRAILING_SEGMENTS = ['list', 'view', 'edit', 'create'];
|
|
3004
|
+
/** Query params managed by entity list UI; ignored when matching generic (no-query) menu paths. */
|
|
3005
|
+
const ENTITY_LIST_UI_QUERY_KEYS = new Set(['view']);
|
|
2986
3006
|
//#region ---- Entity Route Helpers ----
|
|
2987
3007
|
/**
|
|
2988
3008
|
* Parses `/{app}/m/{module}/e/{entity}/...` routes into a stable entity key.
|
|
@@ -3003,15 +3023,89 @@ function axpParseEntityRouteKey(segments) {
|
|
|
3003
3023
|
function axpEntityRouteKeysEqual(left, right) {
|
|
3004
3024
|
return left.app === right.app && left.module === right.module && left.entity === right.entity;
|
|
3005
3025
|
}
|
|
3026
|
+
function axpParseQueryString(queryString) {
|
|
3027
|
+
return new URLSearchParams(queryString);
|
|
3028
|
+
}
|
|
3029
|
+
function axpMenuDeclaredNavigationParams(queryString) {
|
|
3030
|
+
const params = axpParseQueryString(queryString);
|
|
3031
|
+
const navigationParams = new URLSearchParams();
|
|
3032
|
+
params.forEach((value, key) => {
|
|
3033
|
+
if (!ENTITY_LIST_UI_QUERY_KEYS.has(key)) {
|
|
3034
|
+
navigationParams.append(key, value);
|
|
3035
|
+
}
|
|
3036
|
+
});
|
|
3037
|
+
return navigationParams;
|
|
3038
|
+
}
|
|
3039
|
+
function axpMenuHasDeclaredNavigationParams(itemQueryString) {
|
|
3040
|
+
return axpMenuDeclaredNavigationParams(itemQueryString).toString().length > 0;
|
|
3041
|
+
}
|
|
3042
|
+
/**
|
|
3043
|
+
* True when every navigation query param declared on the menu path equals the current URL.
|
|
3044
|
+
*/
|
|
3045
|
+
function axpMenuDeclaredQueryParamsMatch(itemQueryString, currentQueryString) {
|
|
3046
|
+
const itemParams = axpMenuDeclaredNavigationParams(itemQueryString);
|
|
3047
|
+
const declaredPairs = [];
|
|
3048
|
+
itemParams.forEach((value, key) => {
|
|
3049
|
+
declaredPairs.push([key, value]);
|
|
3050
|
+
});
|
|
3051
|
+
if (declaredPairs.length === 0) {
|
|
3052
|
+
return axpGenericEntityListMenuQueryParamsMatch(currentQueryString);
|
|
3053
|
+
}
|
|
3054
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
3055
|
+
return declaredPairs.every(([key, value]) => currentParams.get(key) === value);
|
|
3056
|
+
}
|
|
3057
|
+
/**
|
|
3058
|
+
* Generic entity list menu items (no declared query params) match only when the URL has no
|
|
3059
|
+
* navigation query params beyond UI-managed keys such as `view`.
|
|
3060
|
+
*/
|
|
3061
|
+
function axpGenericEntityListMenuQueryParamsMatch(currentQueryString) {
|
|
3062
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
3063
|
+
let hasNavigationParam = false;
|
|
3064
|
+
currentParams.forEach((_value, key) => {
|
|
3065
|
+
if (!ENTITY_LIST_UI_QUERY_KEYS.has(key)) {
|
|
3066
|
+
hasNavigationParam = true;
|
|
3067
|
+
}
|
|
3068
|
+
});
|
|
3069
|
+
return !hasNavigationParam;
|
|
3070
|
+
}
|
|
3071
|
+
/**
|
|
3072
|
+
* Counts declared menu query params that match the current URL (for best-match selection).
|
|
3073
|
+
*/
|
|
3074
|
+
function axpMenuQueryParamSpecificity(itemPath, currentPath) {
|
|
3075
|
+
const itemQueryString = itemPath.split('#')[0].split('?')[1] ?? '';
|
|
3076
|
+
const currentQueryString = currentPath.split('#')[0].split('?')[1] ?? '';
|
|
3077
|
+
const itemParams = axpMenuDeclaredNavigationParams(itemQueryString);
|
|
3078
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
3079
|
+
let specificity = 0;
|
|
3080
|
+
itemParams.forEach((value, key) => {
|
|
3081
|
+
if (currentParams.get(key) === value) {
|
|
3082
|
+
specificity++;
|
|
3083
|
+
}
|
|
3084
|
+
});
|
|
3085
|
+
return specificity;
|
|
3086
|
+
}
|
|
3006
3087
|
/**
|
|
3007
3088
|
* Matches entity list menu entries against list/detail/create/edit routes for the same entity.
|
|
3008
3089
|
*/
|
|
3009
|
-
function axpTryMatchEntityMenuRoute(itemSegments, pathSegments, currentBase) {
|
|
3090
|
+
function axpTryMatchEntityMenuRoute(itemSegments, pathSegments, currentBase, itemQueryString, currentQueryString) {
|
|
3010
3091
|
const menuEntity = axpParseEntityRouteKey(itemSegments);
|
|
3011
3092
|
const currentEntity = axpParseEntityRouteKey(pathSegments);
|
|
3012
3093
|
if (!menuEntity || !currentEntity || !axpEntityRouteKeysEqual(menuEntity, currentEntity)) {
|
|
3013
3094
|
return null;
|
|
3014
3095
|
}
|
|
3096
|
+
const itemHasDeclaredParams = axpMenuHasDeclaredNavigationParams(itemQueryString);
|
|
3097
|
+
if (itemHasDeclaredParams) {
|
|
3098
|
+
if (!axpIsEntityListPath(currentBase)) {
|
|
3099
|
+
return { isMatch: false, isPartial: false };
|
|
3100
|
+
}
|
|
3101
|
+
if (!axpMenuDeclaredQueryParamsMatch(itemQueryString, currentQueryString)) {
|
|
3102
|
+
return { isMatch: false, isPartial: false };
|
|
3103
|
+
}
|
|
3104
|
+
return { isMatch: true, isPartial: false };
|
|
3105
|
+
}
|
|
3106
|
+
if (axpIsEntityListPath(currentBase) && !axpGenericEntityListMenuQueryParamsMatch(currentQueryString)) {
|
|
3107
|
+
return { isMatch: false, isPartial: false };
|
|
3108
|
+
}
|
|
3015
3109
|
const isPartial = pathSegments.length > menuEntity.entityEndIndex ||
|
|
3016
3110
|
axpIsEntityDetailsPath(currentBase) ||
|
|
3017
3111
|
!axpIsEntityListPath(currentBase);
|
|
@@ -3026,10 +3120,10 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
|
|
|
3026
3120
|
const itemNoHash = itemPath.split('#')[0];
|
|
3027
3121
|
const currentNoHash = currentPath.split('#')[0];
|
|
3028
3122
|
const [itemBase, itemQueryString = ''] = itemNoHash.split('?');
|
|
3029
|
-
const [currentBase] = currentNoHash.split('?');
|
|
3123
|
+
const [currentBase, currentQueryString = ''] = currentNoHash.split('?');
|
|
3030
3124
|
const itemSegments = itemBase.split('/').filter((segment) => segment.length > 0);
|
|
3031
3125
|
const pathSegments = currentBase.split('/').filter((segment) => segment.length > 0);
|
|
3032
|
-
const entityMatch = axpTryMatchEntityMenuRoute(itemSegments, pathSegments, `/${currentBase}
|
|
3126
|
+
const entityMatch = axpTryMatchEntityMenuRoute(itemSegments, pathSegments, `/${currentBase}`, itemQueryString, currentQueryString);
|
|
3033
3127
|
if (entityMatch) {
|
|
3034
3128
|
return entityMatch;
|
|
3035
3129
|
}
|
|
@@ -3054,8 +3148,8 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
|
|
|
3054
3148
|
}
|
|
3055
3149
|
const isPartialMatch = effectiveMenuLength < pathLength;
|
|
3056
3150
|
const isExactMatch = effectiveMenuLength === pathLength;
|
|
3057
|
-
const itemParams =
|
|
3058
|
-
const currentParams =
|
|
3151
|
+
const itemParams = axpParseQueryString(itemQueryString);
|
|
3152
|
+
const currentParams = axpParseQueryString(currentQueryString);
|
|
3059
3153
|
let queryMatches = true;
|
|
3060
3154
|
const itemParamPairs = [];
|
|
3061
3155
|
itemParams.forEach((value, key) => {
|
|
@@ -3080,6 +3174,7 @@ function axpMenuPathsMatch(itemPath, currentPath, trailingSegmentsToIgnore = DEF
|
|
|
3080
3174
|
function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = DEFAULT_TRAILING_SEGMENTS) {
|
|
3081
3175
|
let bestMatch = null;
|
|
3082
3176
|
let bestEffectiveLength = -1;
|
|
3177
|
+
let bestQuerySpecificity = -1;
|
|
3083
3178
|
const visit = (menuItems, ancestors) => {
|
|
3084
3179
|
for (const item of menuItems) {
|
|
3085
3180
|
if (item.children?.length) {
|
|
@@ -3104,8 +3199,11 @@ function axpFindMenuItemByRoute(items, currentPath, trailingSegmentsToIgnore = D
|
|
|
3104
3199
|
if (menuEntity) {
|
|
3105
3200
|
effectiveMenuLength = menuEntity.entityEndIndex;
|
|
3106
3201
|
}
|
|
3107
|
-
|
|
3202
|
+
const querySpecificity = axpMenuQueryParamSpecificity(item.path, currentPath);
|
|
3203
|
+
if (effectiveMenuLength > bestEffectiveLength ||
|
|
3204
|
+
(effectiveMenuLength === bestEffectiveLength && querySpecificity > bestQuerySpecificity)) {
|
|
3108
3205
|
bestEffectiveLength = effectiveMenuLength;
|
|
3206
|
+
bestQuerySpecificity = querySpecificity;
|
|
3109
3207
|
bestMatch = { item, ancestors, isPartialMatch: matchResult.isPartial };
|
|
3110
3208
|
}
|
|
3111
3209
|
}
|
|
@@ -5271,6 +5369,7 @@ class AXPBrowserTitleService {
|
|
|
5271
5369
|
this.tabNavigation = inject(AXPTabNavigationService);
|
|
5272
5370
|
this.menuService = inject(AXPMenuService);
|
|
5273
5371
|
this.sessionService = inject(AXPSessionService);
|
|
5372
|
+
this.platformConfig = inject(AXP_PLATFORM_CONFIG_TOKEN);
|
|
5274
5373
|
this.router = inject(Router);
|
|
5275
5374
|
this.destroyRef = inject(DestroyRef);
|
|
5276
5375
|
//#endregion
|
|
@@ -5366,11 +5465,15 @@ class AXPBrowserTitleService {
|
|
|
5366
5465
|
}
|
|
5367
5466
|
async resolveApplicationTitle() {
|
|
5368
5467
|
const application = this.sessionService.application;
|
|
5369
|
-
const
|
|
5370
|
-
if (
|
|
5468
|
+
const sessionTitle = application?.title?.trim() || application?.name?.trim() || '';
|
|
5469
|
+
if (sessionTitle) {
|
|
5470
|
+
return (await this.resolveLocalizedText(sessionTitle)) ?? sessionTitle;
|
|
5471
|
+
}
|
|
5472
|
+
const platformTitle = this.platformConfig.title?.trim() || '';
|
|
5473
|
+
if (!platformTitle) {
|
|
5371
5474
|
return '';
|
|
5372
5475
|
}
|
|
5373
|
-
return (await this.resolveLocalizedText(
|
|
5476
|
+
return (await this.resolveLocalizedText(platformTitle)) ?? platformTitle;
|
|
5374
5477
|
}
|
|
5375
5478
|
async resolveLocalizedText(value) {
|
|
5376
5479
|
const trimmed = value.trim();
|
|
@@ -5388,7 +5491,7 @@ class AXPBrowserTitleService {
|
|
|
5388
5491
|
if (route && app) {
|
|
5389
5492
|
return `${route} | ${app}`;
|
|
5390
5493
|
}
|
|
5391
|
-
return route || app
|
|
5494
|
+
return route || app;
|
|
5392
5495
|
}
|
|
5393
5496
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBrowserTitleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5394
5497
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPBrowserTitleService, providedIn: 'root' }); }
|
|
@@ -7466,24 +7569,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
7466
7569
|
args: ['AXPCommonModuleFactory']
|
|
7467
7570
|
}] }, { type: AXPKeyboardShortcutsHelpService }, { type: i2$1.AXFormatterRegistryService }] });
|
|
7468
7571
|
|
|
7469
|
-
const ENVIRONMENT = new InjectionToken('ENVIRONMENT');
|
|
7470
|
-
const AXP_PLATFORM_CONFIG_TOKEN = new InjectionToken('AXP_PLATFORM_CONFIG_TOKEN', {
|
|
7471
|
-
providedIn: 'root',
|
|
7472
|
-
factory: () => {
|
|
7473
|
-
return AXPPlatformDefaultConfigs;
|
|
7474
|
-
},
|
|
7475
|
-
});
|
|
7476
|
-
const AXPPlatformDefaultConfigs = {
|
|
7477
|
-
copyright: 'ACoreX @ 2024',
|
|
7478
|
-
title: 'ACoreX Platform',
|
|
7479
|
-
network: {
|
|
7480
|
-
timeOut: 5000,
|
|
7481
|
-
},
|
|
7482
|
-
};
|
|
7483
|
-
function configPlatform(config = AXPPlatformDefaultConfigs) {
|
|
7484
|
-
return merge(AXPPlatformDefaultConfigs, config);
|
|
7485
|
-
}
|
|
7486
|
-
|
|
7487
7572
|
/**
|
|
7488
7573
|
* Resolves post-create list behavior from user settings and optional action overrides.
|
|
7489
7574
|
*/
|