@acorex/platform 21.0.0-next.67 → 21.0.0-next.70
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.map +1 -1
- package/fesm2022/acorex-platform-layout-builder.mjs +14 -2
- package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
- package/fesm2022/{acorex-platform-layout-entity-attachments-page.component-BaTS183I.mjs → acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs} +7 -19
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs.map +1 -0
- package/fesm2022/acorex-platform-layout-entity.mjs +881 -414
- package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-views.mjs +26 -2
- package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widget-core.mjs +1 -0
- package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
- package/fesm2022/acorex-platform-layout-widgets.mjs +12 -12
- package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
- package/package.json +1 -1
- package/types/acorex-platform-common.d.ts +10 -0
- package/types/acorex-platform-layout-entity.d.ts +518 -518
- package/types/acorex-platform-layout-views.d.ts +34 -1
- package/types/acorex-platform-layout-widget-core.d.ts +1 -0
- package/types/acorex-platform-layout-widgets.d.ts +4 -10
- package/fesm2022/acorex-platform-layout-entity-attachments-page.component-BaTS183I.mjs.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { AXToastService } from '@acorex/components/toast';
|
|
2
2
|
import * as i6 from '@acorex/core/translation';
|
|
3
3
|
import { AXTranslationService, AXTranslationModule, resolveMultiLanguageString, translateSync } from '@acorex/core/translation';
|
|
4
|
-
import * as i4$
|
|
4
|
+
import * as i4$3 from '@acorex/platform/common';
|
|
5
5
|
import { AXPEntityCommandScope, AXPSettingsService, AXPCommonSettings, AXPFilterOperatorMiddlewareService, isCardFieldBadgeDisplay, resolveCardFieldBadgeColor, getEntityInfo, resolveEnabledMasterListLayouts, resolveDefaultMasterListLayout, AXPRefreshEvent, AXPReloadEvent, AXPCleanNestedFilters, AXPFileTypeProviderService, AXPFileStorageService, AXPFileActionsService, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPEntityQueryType, AXPWorkflowNavigateAction, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
|
|
6
6
|
import * as i0 from '@angular/core';
|
|
7
7
|
import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, input, viewChild, signal, computed, ElementRef, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, NgModule, ChangeDetectorRef, effect, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, makeEnvironmentProviders } from '@angular/core';
|
|
8
8
|
import { Subject, takeUntil } from 'rxjs';
|
|
9
9
|
import { AXPLayoutBuilderService, LayoutBuilderModule } from '@acorex/platform/layout/builder';
|
|
10
10
|
import * as i3 from '@acorex/platform/layout/widget-core';
|
|
11
|
-
import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, createBooleanProperty, AXPWidgetRendererDirective, createStringProperty, createNumberProperty, AXP_WIDGETS_ADVANCE_SUB_MEDIA, AXP_WIDGETS_ADVANCE_CATEGORY, createSelectProperty, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
11
|
+
import { AXPWidgetsCatalog, AXPWidgetCoreModule, AXPPageStatus, AXPWidgetRegistryService, AXPColumnWidgetComponent, AXPValueWidgetComponent, AXPWidgetGroupEnum, createBooleanProperty, AXPWidgetRendererDirective, AXPBaseWidgetComponent, AXPWidgetStatus, createStringProperty, createNumberProperty, AXP_WIDGETS_ADVANCE_SUB_MEDIA, AXP_WIDGETS_ADVANCE_CATEGORY, createSelectProperty, AXP_WIDGETS_EDITOR_CATEGORY, AXP_WIDGET_DEFINITION_PROVIDER } from '@acorex/platform/layout/widget-core';
|
|
12
12
|
import { AXPSystemActionType, AXPDeviceService, AXPExpressionEvaluatorService, AXPBroadcastEventService, applyFilterArray, applySortArray, resolveActionLook, AXPDistributedEventListenerService, AXPPlatformScope, AXHighlightService, extractValue, setSmart, getChangedPaths, objectKeyValueTransforms, AXPHookService, AXPDataGenerator, AXPComponentSlotModule, AXPColumnWidthService, AXPModuleManifestRegistry, defaultColumnWidthProvider, AXP_COLUMN_WIDTH_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXPModuleManifestsDataSourceDefinition } from '@acorex/platform/core';
|
|
13
13
|
import { cloneDeep, merge, get, castArray, set, orderBy, omit, isNil, isEmpty, isEqual as isEqual$1, isArray, isString } from 'lodash-es';
|
|
14
14
|
import { transform, isEqual } from 'lodash';
|
|
@@ -25,8 +25,10 @@ import { AXFormatService } from '@acorex/core/format';
|
|
|
25
25
|
import * as i5 from '@angular/common';
|
|
26
26
|
import { CommonModule, AsyncPipe } from '@angular/common';
|
|
27
27
|
import { AXPThemeLayoutBlockComponent, AXPPreloadFiltersComponent, AXP_PAGE_COMPONENT_PROVIDER, AXPStateMessageComponent, AXPColumnItemListComponent, AXPDataSelectorService, AXPPageComponentRegistryService } from '@acorex/platform/layout/components';
|
|
28
|
-
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageComponentInstanceRegistryService } from '@acorex/platform/layout/views';
|
|
28
|
+
import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageComponentRendererDirective, AXPPageComponentInstanceRegistryService } from '@acorex/platform/layout/views';
|
|
29
29
|
import { AXDataSource } from '@acorex/cdk/common';
|
|
30
|
+
import { AXP_ENTITY_CRUD_SETUP } from '@acorex/platform/domain';
|
|
31
|
+
export { AXP_ENTITY_DEFINITION_CRUD_SERVICE } from '@acorex/platform/domain';
|
|
30
32
|
import * as i1$3 from '@acorex/platform/workflow';
|
|
31
33
|
import { AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowEventService, AXPWorkflowModule } from '@acorex/platform/workflow';
|
|
32
34
|
import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
|
|
@@ -35,8 +37,6 @@ import { AXDialogService } from '@acorex/components/dialog';
|
|
|
35
37
|
import { AXLoadingDialogService } from '@acorex/components/loading-dialog';
|
|
36
38
|
import { AXPopupService } from '@acorex/components/popup';
|
|
37
39
|
import { AXPlatform } from '@acorex/core/platform';
|
|
38
|
-
import { AXP_ENTITY_CRUD_SETUP } from '@acorex/platform/domain';
|
|
39
|
-
export { AXP_ENTITY_DEFINITION_CRUD_SERVICE } from '@acorex/platform/domain';
|
|
40
40
|
import * as i2$1 from '@acorex/components/badge';
|
|
41
41
|
import { AXBadgeModule } from '@acorex/components/badge';
|
|
42
42
|
import { AXCheckBoxModule } from '@acorex/components/check-box';
|
|
@@ -60,7 +60,7 @@ import { AXValidationModule } from '@acorex/core/validation';
|
|
|
60
60
|
import { AXP_DISABLED_PROPERTY, AXP_ALLOW_CLEAR_PROPERTY, AXP_DATA_PATH_PROPERTY, AXP_DATA_PROPERTY_GROUP, AXP_ALLOW_MULTIPLE_PROPERTY, AXP_NAME_PROPERTY, AXP_READONLY_PROPERTY, AXP_PLACEHOLDER_PROPERTY, AXP_BEHAVIOR_PROPERTY_GROUP, AXPProviderSelectWidgetEditBase, AXP_ROW_EXPR_PREFIX, AXP_DOWNLOADABLE_PROPERTY, AXP_DESCRIPTION_PROPERTY } from '@acorex/platform/layout/widgets';
|
|
61
61
|
import * as i2$2 from '@acorex/components/select-box';
|
|
62
62
|
import { AXSelectBoxModule } from '@acorex/components/select-box';
|
|
63
|
-
import * as
|
|
63
|
+
import * as i3$3 from '@acorex/components/dropdown';
|
|
64
64
|
import { AXDropdownModule } from '@acorex/components/dropdown';
|
|
65
65
|
import * as i2$3 from '@acorex/components/tabs';
|
|
66
66
|
import { AXTabsModule } from '@acorex/components/tabs';
|
|
@@ -71,7 +71,7 @@ import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
|
71
71
|
import { AXFileService } from '@acorex/core/file';
|
|
72
72
|
import { AXUploaderZoneDirective } from '@acorex/cdk/uploader';
|
|
73
73
|
import { AXUploaderModule } from '@acorex/components/uploader';
|
|
74
|
-
import * as i4$
|
|
74
|
+
import * as i4$2 from '@acorex/components/collapse';
|
|
75
75
|
import { AXCollapseModule } from '@acorex/components/collapse';
|
|
76
76
|
|
|
77
77
|
function ensureListActions(ctx) {
|
|
@@ -1248,6 +1248,8 @@ const ENTITY_FORM_STEP_WIZARD_NAME = 'entityFormStepWizard';
|
|
|
1248
1248
|
const ENTITY_FORM_ACTION_FIRST_STEP_CONTINUE = 'entity-form-first-step-continue';
|
|
1249
1249
|
/** Footer command: close dialog (data already saved per step). */
|
|
1250
1250
|
const ENTITY_FORM_ACTION_DONE = 'entity-form-done';
|
|
1251
|
+
/** Footer command: sync page widgets then advance wizard. */
|
|
1252
|
+
const ENTITY_FORM_ACTION_NEXT_STEP = 'entity-form-next-step';
|
|
1251
1253
|
//#endregion
|
|
1252
1254
|
class AXPEntityFormBuilderService {
|
|
1253
1255
|
constructor() {
|
|
@@ -1637,20 +1639,41 @@ class PropertyFilter {
|
|
|
1637
1639
|
const sectionScaleFactors = normalizeLayoutFillRowGaps(renderedSections, (s) => s.layout, (s) => s.id);
|
|
1638
1640
|
const filterEvalRoot = merge({}, this.initialContext, modelForRelatedEval);
|
|
1639
1641
|
const listRelatedEntities = collectListRelatedEntitiesForFormWizard(entity, this.kind);
|
|
1640
|
-
const
|
|
1641
|
-
const
|
|
1642
|
+
const pageWizardPages = collectPagesForFormWizard(entity, this.kind);
|
|
1643
|
+
const useFormWizard = (listRelatedEntities.length > 0 || pageWizardPages.length > 0) &&
|
|
1644
|
+
(this.kind === 'create' || this.kind === 'update');
|
|
1645
|
+
const wizardExtraSteps = [];
|
|
1642
1646
|
for (const re of listRelatedEntities) {
|
|
1643
1647
|
const [rm, en] = re.entity.split('.');
|
|
1644
1648
|
const relDef = await this.entityRegistry.resolve(rm, en);
|
|
1645
|
-
|
|
1649
|
+
wizardExtraSteps.push({
|
|
1650
|
+
kind: 'related-list',
|
|
1651
|
+
order: re.layout?.order ?? 0,
|
|
1646
1652
|
stepId: buildEntityFormRelatedStepId(re),
|
|
1647
1653
|
title: (re.title ?? relDef?.title ?? re.entity),
|
|
1648
1654
|
rel: re,
|
|
1649
1655
|
});
|
|
1650
1656
|
}
|
|
1651
|
-
const
|
|
1652
|
-
|
|
1657
|
+
for (const page of pageWizardPages) {
|
|
1658
|
+
wizardExtraSteps.push({
|
|
1659
|
+
kind: 'page',
|
|
1660
|
+
order: page.layout?.order ?? 0,
|
|
1661
|
+
stepId: buildEntityFormPageStepId(page),
|
|
1662
|
+
title: (page.title ?? page.componentKey),
|
|
1663
|
+
page,
|
|
1664
|
+
componentKey: page.componentKey,
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
wizardExtraSteps.sort((a, b) => a.order - b.order);
|
|
1668
|
+
const pageWizardWidgetNames = wizardExtraSteps
|
|
1669
|
+
.filter((s) => s.kind === 'page')
|
|
1670
|
+
.map((s) => buildPageComponentWidgetName(s.page));
|
|
1671
|
+
const prebuiltRelatedListConfigs = useFormWizard
|
|
1672
|
+
? await Promise.all(wizardExtraSteps
|
|
1673
|
+
.filter((s) => s.kind === 'related-list')
|
|
1674
|
+
.map((s) => this.buildRelatedEntityListWidgetOptions(s.rel, filterEvalRoot)))
|
|
1653
1675
|
: [];
|
|
1676
|
+
let relatedListConfigIndex = 0;
|
|
1654
1677
|
const mainFormGridArgs = {
|
|
1655
1678
|
entity,
|
|
1656
1679
|
finalSections,
|
|
@@ -1661,15 +1684,15 @@ class PropertyFilter {
|
|
|
1661
1684
|
};
|
|
1662
1685
|
const dialog = this.layoutBuilder.create().dialog((d) => {
|
|
1663
1686
|
d.setTitle(title);
|
|
1664
|
-
d.setSize(this.externalSize ?? (
|
|
1687
|
+
d.setSize(this.externalSize ?? (useFormWizard ? 'lg' : calculatedSize));
|
|
1665
1688
|
d.setCloseButton(true);
|
|
1666
1689
|
d.content((layout) => {
|
|
1667
1690
|
const defaultMode = this.kind === 'single' ? 'view' : 'edit';
|
|
1668
1691
|
layout.mode(this.externalMode ?? defaultMode);
|
|
1669
|
-
if (
|
|
1692
|
+
if (useFormWizard) {
|
|
1670
1693
|
layout.stepWizard((w) => {
|
|
1671
1694
|
w.name(ENTITY_FORM_STEP_WIZARD_NAME);
|
|
1672
|
-
w.setLook('
|
|
1695
|
+
w.setLook('arrow-minimal');
|
|
1673
1696
|
w.setShowActions(false);
|
|
1674
1697
|
const mainStepTitle = (entity.formats?.individual ||
|
|
1675
1698
|
entity.title ||
|
|
@@ -1679,33 +1702,55 @@ class PropertyFilter {
|
|
|
1679
1702
|
inner.grid((grid) => this.fillMainEntityFormGrid(grid, mainFormGridArgs));
|
|
1680
1703
|
});
|
|
1681
1704
|
});
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
iw.
|
|
1692
|
-
|
|
1693
|
-
|
|
1705
|
+
for (const wizardStep of wizardExtraSteps) {
|
|
1706
|
+
if (wizardStep.kind === 'related-list') {
|
|
1707
|
+
const built = prebuiltRelatedListConfigs[relatedListConfigIndex++];
|
|
1708
|
+
w.step(wizardStep.stepId, wizardStep.title, (st) => {
|
|
1709
|
+
st.content((inner) => {
|
|
1710
|
+
inner.flex((flex) => {
|
|
1711
|
+
flex.setDirection('column');
|
|
1712
|
+
flex.setAlignItems('stretch');
|
|
1713
|
+
flex.customWidget(AXPWidgetsCatalog.entityList, (iw) => {
|
|
1714
|
+
iw.name(built.name);
|
|
1715
|
+
if (built.defaultValue) {
|
|
1716
|
+
iw.defaultValue(built.defaultValue);
|
|
1717
|
+
}
|
|
1718
|
+
iw.options(built.options);
|
|
1719
|
+
});
|
|
1694
1720
|
});
|
|
1695
1721
|
});
|
|
1696
1722
|
});
|
|
1697
|
-
}
|
|
1698
|
-
|
|
1723
|
+
}
|
|
1724
|
+
else {
|
|
1725
|
+
w.step(wizardStep.stepId, wizardStep.title, (st) => {
|
|
1726
|
+
st.content((inner) => {
|
|
1727
|
+
inner.flex((flex) => {
|
|
1728
|
+
flex.setDirection('column');
|
|
1729
|
+
flex.setAlignItems('stretch');
|
|
1730
|
+
flex.customWidget(AXPWidgetsCatalog.pageComponent, (iw) => {
|
|
1731
|
+
iw.name(buildPageComponentWidgetName(wizardStep.page));
|
|
1732
|
+
iw.options({
|
|
1733
|
+
componentKey: wizardStep.page.componentKey,
|
|
1734
|
+
field: wizardStep.page.field,
|
|
1735
|
+
pageOptions: wizardStep.page.options ?? {},
|
|
1736
|
+
showPageActions: true,
|
|
1737
|
+
});
|
|
1738
|
+
});
|
|
1739
|
+
});
|
|
1740
|
+
});
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1699
1744
|
});
|
|
1700
1745
|
}
|
|
1701
1746
|
else {
|
|
1702
1747
|
layout.grid((grid) => this.fillMainEntityFormGrid(grid, mainFormGridArgs));
|
|
1703
1748
|
}
|
|
1704
1749
|
});
|
|
1705
|
-
if (this.externalActionsDelegate && !
|
|
1750
|
+
if (this.externalActionsDelegate && !useFormWizard) {
|
|
1706
1751
|
d.setActions(this.externalActionsDelegate);
|
|
1707
1752
|
}
|
|
1708
|
-
else if (
|
|
1753
|
+
else if (useFormWizard) {
|
|
1709
1754
|
d.setActions((ab) => configureEntityFormWizardFooterActions(ab, ENTITY_FORM_STEP_WIZARD_NAME, this.kind === 'create'
|
|
1710
1755
|
? '{{ ((typeof context.id === "string" && context.id.length > 0) || (typeof context.id === "number" && !isNaN(context.id)) || (typeof context._id === "string" && context._id.length > 0) || (typeof context._id === "number" && !isNaN(context._id))) ? "@general:entity-form.update-and-continue.title" : "@general:entity-form.create-and-continue.title" }}'
|
|
1711
1756
|
: '@general:entity-form.save-and-continue.title'));
|
|
@@ -1718,8 +1763,8 @@ class PropertyFilter {
|
|
|
1718
1763
|
.cancel('@general:actions.cancel.title')
|
|
1719
1764
|
.submit(this.kind === 'create' ? '@general:actions.create.title' : '@general:actions.apply.title'));
|
|
1720
1765
|
}
|
|
1721
|
-
if (
|
|
1722
|
-
d.onAction(this.createWizardOnActionWrapper(this.onActionHandler));
|
|
1766
|
+
if (useFormWizard && this.onActionHandler) {
|
|
1767
|
+
d.onAction(this.createWizardOnActionWrapper(this.onActionHandler, pageWizardWidgetNames));
|
|
1723
1768
|
}
|
|
1724
1769
|
else if (this.onActionHandler) {
|
|
1725
1770
|
d.onAction(this.onActionHandler);
|
|
@@ -1883,12 +1928,25 @@ class PropertyFilter {
|
|
|
1883
1928
|
return (await this.expressionEvaluator.evaluate(action, scope));
|
|
1884
1929
|
}));
|
|
1885
1930
|
}
|
|
1886
|
-
createWizardOnActionWrapper(userHandler) {
|
|
1931
|
+
createWizardOnActionWrapper(userHandler, pageWizardWidgetNames = []) {
|
|
1887
1932
|
return async (ref) => {
|
|
1888
1933
|
const action = ref.action();
|
|
1889
1934
|
if (action === ENTITY_FORM_ACTION_DONE) {
|
|
1935
|
+
await syncAllPageComponentWidgets(ref, pageWizardWidgetNames);
|
|
1936
|
+
if (hasPersistedRootId$1(ref.context())) {
|
|
1937
|
+
const out = (await userHandler(ref));
|
|
1938
|
+
if (out?.success === false) {
|
|
1939
|
+
return out;
|
|
1940
|
+
}
|
|
1941
|
+
return { success: true, data: out?.data ?? ref.context(), skipValidate: true };
|
|
1942
|
+
}
|
|
1890
1943
|
return { success: true, data: ref.context(), skipValidate: true };
|
|
1891
1944
|
}
|
|
1945
|
+
if (action === ENTITY_FORM_ACTION_NEXT_STEP) {
|
|
1946
|
+
await syncAllPageComponentWidgets(ref, pageWizardWidgetNames);
|
|
1947
|
+
await ref.invokeWidget?.(ENTITY_FORM_STEP_WIZARD_NAME, 'next', { setLoading: ref.setLoading });
|
|
1948
|
+
return { keepDialogOpen: true };
|
|
1949
|
+
}
|
|
1892
1950
|
if (action === ENTITY_FORM_ACTION_FIRST_STEP_CONTINUE) {
|
|
1893
1951
|
const out = (await userHandler(ref));
|
|
1894
1952
|
if (out?.success === false) {
|
|
@@ -2201,6 +2259,37 @@ function collectListRelatedEntitiesForFormWizard(entity, kind) {
|
|
|
2201
2259
|
isRelatedEntityIncludedOnMasterForm(re, kind, 'list'))
|
|
2202
2260
|
.sort((a, b) => (a.layout?.order ?? 0) - (b.layout?.order ?? 0));
|
|
2203
2261
|
}
|
|
2262
|
+
function isEntityPageIncludedOnMasterForm(page, kind) {
|
|
2263
|
+
if (kind !== 'create' && kind !== 'update') {
|
|
2264
|
+
return true;
|
|
2265
|
+
}
|
|
2266
|
+
if (kind === 'create') {
|
|
2267
|
+
return page.appearOn?.create === true;
|
|
2268
|
+
}
|
|
2269
|
+
return page.appearOn?.update === true;
|
|
2270
|
+
}
|
|
2271
|
+
function collectPagesForFormWizard(entity, kind) {
|
|
2272
|
+
return (entity.pages ?? [])
|
|
2273
|
+
.filter((page) => !page.hidden && isEntityPageIncludedOnMasterForm(page, kind))
|
|
2274
|
+
.sort((a, b) => (a.layout?.order ?? 0) - (b.layout?.order ?? 0));
|
|
2275
|
+
}
|
|
2276
|
+
function buildEntityFormPageStepId(page) {
|
|
2277
|
+
const safeKey = page.componentKey.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
2278
|
+
const fieldSuffix = page.field ? `-${page.field.replace(/[^a-zA-Z0-9._-]/g, '_')}` : '';
|
|
2279
|
+
return `page-${safeKey}${fieldSuffix}`;
|
|
2280
|
+
}
|
|
2281
|
+
function buildPageComponentWidgetName(page) {
|
|
2282
|
+
return `pageComponent_${buildEntityFormPageStepId(page)}`;
|
|
2283
|
+
}
|
|
2284
|
+
function hasPersistedRootId$1(context) {
|
|
2285
|
+
const raw = context?.id ?? context?._id;
|
|
2286
|
+
return (typeof raw === 'string' && raw.length > 0) || (typeof raw === 'number' && !Number.isNaN(raw));
|
|
2287
|
+
}
|
|
2288
|
+
async function syncAllPageComponentWidgets(ref, widgetNames) {
|
|
2289
|
+
for (const name of widgetNames) {
|
|
2290
|
+
await ref.invokeWidget?.(name, 'syncContext', {});
|
|
2291
|
+
}
|
|
2292
|
+
}
|
|
2204
2293
|
function buildEntityFormRelatedStepId(re) {
|
|
2205
2294
|
const safe = re.entity.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
2206
2295
|
return `related-${safe}-${re.layout?.order ?? 0}`;
|
|
@@ -2224,9 +2313,10 @@ function configureEntityFormWizardFooterActions(ab, wizardName, firstStepContinu
|
|
|
2224
2313
|
});
|
|
2225
2314
|
ab.custom({
|
|
2226
2315
|
title: '@general:actions.next.title',
|
|
2227
|
-
command:
|
|
2316
|
+
command: { name: ENTITY_FORM_ACTION_NEXT_STEP },
|
|
2228
2317
|
color: 'primary',
|
|
2229
2318
|
position: 'suffix',
|
|
2319
|
+
predicateApiWidgetName: wizardName,
|
|
2230
2320
|
hidden: '{{api.getStatus().isFirst || api.getStatus().isLast}}',
|
|
2231
2321
|
});
|
|
2232
2322
|
ab.custom({
|
|
@@ -3975,43 +4065,6 @@ var entityPreloadFiltersContainer_component = /*#__PURE__*/Object.freeze({
|
|
|
3975
4065
|
AXPEntityPreloadFiltersContainerComponent: AXPEntityPreloadFiltersContainerComponent
|
|
3976
4066
|
});
|
|
3977
4067
|
|
|
3978
|
-
const AXP_DATA_SEEDER_TOKEN = new InjectionToken('AXP_DATA_SEEDER_TOKEN');
|
|
3979
|
-
class AXPDataSeederService {
|
|
3980
|
-
constructor() {
|
|
3981
|
-
this.loaders = inject(AXP_DATA_SEEDER_TOKEN, { optional: true });
|
|
3982
|
-
}
|
|
3983
|
-
async seed() {
|
|
3984
|
-
for (const loader of castArray(this.loaders)) {
|
|
3985
|
-
if (!loader)
|
|
3986
|
-
continue;
|
|
3987
|
-
const seederName = loader.constructor?.name || 'UnknownSeeder';
|
|
3988
|
-
const startTime = performance.now();
|
|
3989
|
-
try {
|
|
3990
|
-
await loader.seed();
|
|
3991
|
-
}
|
|
3992
|
-
catch (err) {
|
|
3993
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
3994
|
-
console.error(`[AXPDataSeeder] Seeder "${seederName}" failed (continuing with next):`, message);
|
|
3995
|
-
if (err instanceof Error && err.stack) {
|
|
3996
|
-
console.error(err.stack);
|
|
3997
|
-
}
|
|
3998
|
-
// Optionally log to your system-log / app-log entity here if you have one (inject a writer and persist).
|
|
3999
|
-
continue;
|
|
4000
|
-
}
|
|
4001
|
-
const duration = performance.now() - startTime;
|
|
4002
|
-
if (duration > 3000) {
|
|
4003
|
-
console.warn(`[AXPDataSeeder] Seeder "${seederName}" took ${duration.toFixed(2)}ms (>3000ms threshold)`);
|
|
4004
|
-
}
|
|
4005
|
-
}
|
|
4006
|
-
}
|
|
4007
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSeederService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4008
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSeederService, providedIn: 'root' }); }
|
|
4009
|
-
}
|
|
4010
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSeederService, decorators: [{
|
|
4011
|
-
type: Injectable,
|
|
4012
|
-
args: [{ providedIn: 'root' }]
|
|
4013
|
-
}] });
|
|
4014
|
-
|
|
4015
4068
|
/**
|
|
4016
4069
|
* Data source definition provider that returns all entity names
|
|
4017
4070
|
* from entity loaders' list() (const.ts in each module).
|
|
@@ -4101,6 +4154,139 @@ class AXPEntitiesListDataSourceDefinition {
|
|
|
4101
4154
|
}
|
|
4102
4155
|
}
|
|
4103
4156
|
|
|
4157
|
+
//#region ---- Imports ----
|
|
4158
|
+
//#endregion
|
|
4159
|
+
//#region ---- Constants ----
|
|
4160
|
+
const DEFAULT_RELATED_ORDER_STEP = 10;
|
|
4161
|
+
const DEFAULT_PLUGIN_ZONE_FLOOR = 100_000;
|
|
4162
|
+
/** Space per plugin slot so multiple fields in one slot do not cross into the next. */
|
|
4163
|
+
const PLUGIN_SLOT_SPAN = 10_000;
|
|
4164
|
+
const SUB_ORDER_STEP = 10;
|
|
4165
|
+
const PLUGIN_SLOT_INDEX = {
|
|
4166
|
+
'meta-data-builder': 0,
|
|
4167
|
+
attachments: 1,
|
|
4168
|
+
documents: 2,
|
|
4169
|
+
comments: 3,
|
|
4170
|
+
history: 4,
|
|
4171
|
+
};
|
|
4172
|
+
//#endregion
|
|
4173
|
+
//#region ---- Helpers ----
|
|
4174
|
+
function shouldSkipPageForMax(page, skip) {
|
|
4175
|
+
if (!skip) {
|
|
4176
|
+
return false;
|
|
4177
|
+
}
|
|
4178
|
+
if (page.componentKey !== skip.componentKey) {
|
|
4179
|
+
return false;
|
|
4180
|
+
}
|
|
4181
|
+
if (skip.field !== undefined) {
|
|
4182
|
+
return page.field === skip.field;
|
|
4183
|
+
}
|
|
4184
|
+
return true;
|
|
4185
|
+
}
|
|
4186
|
+
function normalizeRelatedPageListDetailOrders(relatedEntities, step) {
|
|
4187
|
+
const pageTabRelated = (relatedEntities ?? []).filter((re) => re.layout?.type === 'page-list' || re.layout?.type === 'page-detail');
|
|
4188
|
+
let maxExplicit = 0;
|
|
4189
|
+
for (const re of pageTabRelated) {
|
|
4190
|
+
const o = re.layout?.order;
|
|
4191
|
+
if (typeof o === 'number' && Number.isFinite(o)) {
|
|
4192
|
+
maxExplicit = Math.max(maxExplicit, o);
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
let cursor = maxExplicit;
|
|
4196
|
+
for (const re of pageTabRelated) {
|
|
4197
|
+
const layout = re.layout;
|
|
4198
|
+
if (!layout || layout.order != null) {
|
|
4199
|
+
continue;
|
|
4200
|
+
}
|
|
4201
|
+
cursor += step;
|
|
4202
|
+
re.layout = { ...layout, order: cursor };
|
|
4203
|
+
}
|
|
4204
|
+
let afterMax = 0;
|
|
4205
|
+
for (const re of pageTabRelated) {
|
|
4206
|
+
const o = re.layout?.order;
|
|
4207
|
+
if (typeof o === 'number' && Number.isFinite(o)) {
|
|
4208
|
+
afterMax = Math.max(afterMax, o);
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
return afterMax;
|
|
4212
|
+
}
|
|
4213
|
+
/**
|
|
4214
|
+
* Ordinal within a slot for multi-field pages (attachments, meta-data-builder), stable by field name.
|
|
4215
|
+
*/
|
|
4216
|
+
function subOrderWithinComponentSlot(pages, componentKey, skip, currentField) {
|
|
4217
|
+
const peerFieldKeys = (pages ?? [])
|
|
4218
|
+
.filter((p) => p.componentKey === componentKey && !shouldSkipPageForMax(p, skip))
|
|
4219
|
+
.map((p) => p.field ?? '');
|
|
4220
|
+
const keySet = new Set(peerFieldKeys);
|
|
4221
|
+
keySet.add(currentField ?? '');
|
|
4222
|
+
const sorted = [...keySet].sort((a, b) => a.localeCompare(b));
|
|
4223
|
+
const index = sorted.indexOf(currentField ?? '');
|
|
4224
|
+
return Math.max(0, index) * SUB_ORDER_STEP;
|
|
4225
|
+
}
|
|
4226
|
+
//#endregion
|
|
4227
|
+
//#region ---- Public API ----
|
|
4228
|
+
/**
|
|
4229
|
+
* Resolves `layout.order` for a built-in plugin detail tab (`entity.pages`).
|
|
4230
|
+
*
|
|
4231
|
+
* 1. Assigns finite `layout.order` values to related `page-list` / `page-detail` rows that omit
|
|
4232
|
+
* `order` (the composer otherwise treats them as +Infinity).
|
|
4233
|
+
* 2. Places plugin tabs in a fixed relative order: meta-data-builder → attachments → documents →
|
|
4234
|
+
* comments → history, after all related tabs.
|
|
4235
|
+
*/
|
|
4236
|
+
function resolveEntityPluginDetailPageOrder(input, slot, options) {
|
|
4237
|
+
const relatedStep = options.relatedOrderStep ?? DEFAULT_RELATED_ORDER_STEP;
|
|
4238
|
+
const zoneFloor = options.pluginZoneFloor ?? DEFAULT_PLUGIN_ZONE_FLOOR;
|
|
4239
|
+
const { componentKey, skipPage, field } = options;
|
|
4240
|
+
const afterRelatedMax = normalizeRelatedPageListDetailOrders(input.relatedEntities, relatedStep);
|
|
4241
|
+
const pluginZoneStart = Math.max(afterRelatedMax + relatedStep, zoneFloor);
|
|
4242
|
+
const slotIndex = PLUGIN_SLOT_INDEX[slot];
|
|
4243
|
+
const subOrder = subOrderWithinComponentSlot(input.pages, componentKey, skipPage, field);
|
|
4244
|
+
return pluginZoneStart + slotIndex * PLUGIN_SLOT_SPAN + subOrder;
|
|
4245
|
+
}
|
|
4246
|
+
//#endregion
|
|
4247
|
+
|
|
4248
|
+
const AXP_DATA_SEEDER_TOKEN = new InjectionToken('AXP_DATA_SEEDER_TOKEN');
|
|
4249
|
+
class AXPDataSeederService {
|
|
4250
|
+
constructor() {
|
|
4251
|
+
this.loaders = inject(AXP_DATA_SEEDER_TOKEN, { optional: true });
|
|
4252
|
+
}
|
|
4253
|
+
async seed() {
|
|
4254
|
+
for (const loader of castArray(this.loaders)) {
|
|
4255
|
+
if (!loader)
|
|
4256
|
+
continue;
|
|
4257
|
+
const seederName = loader.constructor?.name || 'UnknownSeeder';
|
|
4258
|
+
const startTime = performance.now();
|
|
4259
|
+
try {
|
|
4260
|
+
await loader.seed();
|
|
4261
|
+
}
|
|
4262
|
+
catch (err) {
|
|
4263
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4264
|
+
console.error(`[AXPDataSeeder] Seeder "${seederName}" failed (continuing with next):`, message);
|
|
4265
|
+
if (err instanceof Error && err.stack) {
|
|
4266
|
+
console.error(err.stack);
|
|
4267
|
+
}
|
|
4268
|
+
// Optionally log to your system-log / app-log entity here if you have one (inject a writer and persist).
|
|
4269
|
+
continue;
|
|
4270
|
+
}
|
|
4271
|
+
const duration = performance.now() - startTime;
|
|
4272
|
+
if (duration > 3000) {
|
|
4273
|
+
console.warn(`[AXPDataSeeder] Seeder "${seederName}" took ${duration.toFixed(2)}ms (>3000ms threshold)`);
|
|
4274
|
+
}
|
|
4275
|
+
}
|
|
4276
|
+
}
|
|
4277
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSeederService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4278
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSeederService, providedIn: 'root' }); }
|
|
4279
|
+
}
|
|
4280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDataSeederService, decorators: [{
|
|
4281
|
+
type: Injectable,
|
|
4282
|
+
args: [{ providedIn: 'root' }]
|
|
4283
|
+
}] });
|
|
4284
|
+
|
|
4285
|
+
/**
|
|
4286
|
+
* Re-export from domain to avoid circular dependency: layout/components must not depend on layout/entity.
|
|
4287
|
+
* Consumers that only need the token/interface can import from @acorex/platform/domain.
|
|
4288
|
+
*/
|
|
4289
|
+
|
|
4104
4290
|
class AXPEntityCommandTriggerViewModel {
|
|
4105
4291
|
constructor(entity, action, isChild = false) {
|
|
4106
4292
|
this.name = `${typeof action.command === 'string' ? action.command : action.command.name}&${action.name}`;
|
|
@@ -4504,136 +4690,24 @@ const AXPEntityEventsKeys = {
|
|
|
4504
4690
|
};
|
|
4505
4691
|
|
|
4506
4692
|
/**
|
|
4507
|
-
*
|
|
4693
|
+
* Entity Event Dispatcher - A wrapper for entity-specific events
|
|
4694
|
+
* Handles pattern-based dispatching for entity operations with wildcard support
|
|
4508
4695
|
*/
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
return String(value);
|
|
4696
|
+
class AXPEntityEventDispatcherService {
|
|
4697
|
+
constructor() {
|
|
4698
|
+
this.eventService = inject(AXPDistributedEventListenerService);
|
|
4513
4699
|
}
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
const metaChildren = rec?.['__meta__']?.['children'];
|
|
4526
|
-
const directChildren = rec?.['children'];
|
|
4527
|
-
const childArr = Array.isArray(metaChildren)
|
|
4528
|
-
? metaChildren
|
|
4529
|
-
: Array.isArray(directChildren)
|
|
4530
|
-
? directChildren
|
|
4531
|
-
: null;
|
|
4532
|
-
if (childArr?.length) {
|
|
4533
|
-
const found = findEntityListRowDataInTree(childArr, id, key);
|
|
4534
|
-
if (found) {
|
|
4535
|
-
return found;
|
|
4536
|
-
}
|
|
4537
|
-
}
|
|
4538
|
-
}
|
|
4539
|
-
return null;
|
|
4540
|
-
}
|
|
4541
|
-
/**
|
|
4542
|
-
* Restores expanded rows after data load (parents before children).
|
|
4543
|
-
*/
|
|
4544
|
-
async function restoreEntityListExpandedRows(options) {
|
|
4545
|
-
const pending = [...new Set(options.expandedRowIds.filter(Boolean))];
|
|
4546
|
-
if (!pending.length) {
|
|
4547
|
-
return;
|
|
4548
|
-
}
|
|
4549
|
-
let safety = 0;
|
|
4550
|
-
const maxPasses = Math.max(pending.length * 3, 10);
|
|
4551
|
-
while (pending.length > 0 && safety++ < maxPasses) {
|
|
4552
|
-
const rows = options.getDisplayedRows();
|
|
4553
|
-
let progressed = false;
|
|
4554
|
-
for (let i = pending.length - 1; i >= 0; i--) {
|
|
4555
|
-
const id = pending[i];
|
|
4556
|
-
const item = findEntityListRowDataInTree(rows, id, options.rowKey);
|
|
4557
|
-
if (!item) {
|
|
4558
|
-
continue;
|
|
4559
|
-
}
|
|
4560
|
-
const meta = item['__meta__'];
|
|
4561
|
-
if (meta?.['expanded'] !== true) {
|
|
4562
|
-
await options.expandRow({ data: item });
|
|
4563
|
-
}
|
|
4564
|
-
pending.splice(i, 1);
|
|
4565
|
-
progressed = true;
|
|
4566
|
-
}
|
|
4567
|
-
if (!progressed) {
|
|
4568
|
-
break;
|
|
4569
|
-
}
|
|
4570
|
-
}
|
|
4571
|
-
}
|
|
4572
|
-
|
|
4573
|
-
/**
|
|
4574
|
-
* Applies take/skip to the data source without triggering {@link AXDataSource.load}.
|
|
4575
|
-
*/
|
|
4576
|
-
function applyDataSourcePagingWithoutLoad(dataSource, paging) {
|
|
4577
|
-
const take = Math.max(1, paging.take);
|
|
4578
|
-
const skip = Math.max(0, paging.skip);
|
|
4579
|
-
const page = Math.floor(skip / take);
|
|
4580
|
-
const ds = dataSource;
|
|
4581
|
-
dataSource.config.pageSize = take;
|
|
4582
|
-
if (ds._query) {
|
|
4583
|
-
ds._query.take = take;
|
|
4584
|
-
ds._query.skip = skip;
|
|
4585
|
-
}
|
|
4586
|
-
ds._page = page;
|
|
4587
|
-
}
|
|
4588
|
-
function getDataSourcePageIndex(dataSource) {
|
|
4589
|
-
const ds = dataSource;
|
|
4590
|
-
return ds._page ?? 0;
|
|
4591
|
-
}
|
|
4592
|
-
function normalizeListPaging(paging, defaultTake) {
|
|
4593
|
-
const take = typeof paging?.take === 'number' && paging.take > 0 ? paging.take : defaultTake;
|
|
4594
|
-
const skip = typeof paging?.skip === 'number' && paging.skip >= 0 ? paging.skip : 0;
|
|
4595
|
-
return { take, skip };
|
|
4596
|
-
}
|
|
4597
|
-
|
|
4598
|
-
const AXPEntityListPersistenceModeDefault = 'persistent';
|
|
4599
|
-
function normalizeEntityListPersistenceMode(value) {
|
|
4600
|
-
if (value === 'none' || value === 'persistent' || value === 'route') {
|
|
4601
|
-
return value;
|
|
4602
|
-
}
|
|
4603
|
-
return AXPEntityListPersistenceModeDefault;
|
|
4604
|
-
}
|
|
4605
|
-
function canPersistEntityListState(mode) {
|
|
4606
|
-
return mode !== 'none';
|
|
4607
|
-
}
|
|
4608
|
-
/** `none` never reads list state from user settings. */
|
|
4609
|
-
function shouldLoadEntityListStateFromStorage(mode) {
|
|
4610
|
-
return mode !== 'none';
|
|
4611
|
-
}
|
|
4612
|
-
/** `route` clears stored list state when the route entity (module + name) changes. */
|
|
4613
|
-
function shouldResetEntityListStateOnRouteEntry(mode) {
|
|
4614
|
-
return mode === 'route';
|
|
4615
|
-
}
|
|
4616
|
-
const ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY = 'axp-entity-list-route-context';
|
|
4617
|
-
|
|
4618
|
-
/**
|
|
4619
|
-
* Entity Event Dispatcher - A wrapper for entity-specific events
|
|
4620
|
-
* Handles pattern-based dispatching for entity operations with wildcard support
|
|
4621
|
-
*/
|
|
4622
|
-
class AXPEntityEventDispatcherService {
|
|
4623
|
-
constructor() {
|
|
4624
|
-
this.eventService = inject(AXPDistributedEventListenerService);
|
|
4625
|
-
}
|
|
4626
|
-
async dispatchEntityEvent(operation, entityName, data) {
|
|
4627
|
-
const enhancedData = {
|
|
4628
|
-
...data,
|
|
4629
|
-
entityName,
|
|
4630
|
-
operation,
|
|
4631
|
-
timestamp: new Date(),
|
|
4632
|
-
source: 'entity-dispatcher',
|
|
4633
|
-
};
|
|
4634
|
-
const eventKeysToDispatch = await this.getAllMatchingEventKeys(operation, entityName);
|
|
4635
|
-
const dispatchPromises = eventKeysToDispatch.map((key) => this.eventService.dispatch(key, enhancedData));
|
|
4636
|
-
await Promise.all(dispatchPromises);
|
|
4700
|
+
async dispatchEntityEvent(operation, entityName, data) {
|
|
4701
|
+
const enhancedData = {
|
|
4702
|
+
...data,
|
|
4703
|
+
entityName,
|
|
4704
|
+
operation,
|
|
4705
|
+
timestamp: new Date(),
|
|
4706
|
+
source: 'entity-dispatcher',
|
|
4707
|
+
};
|
|
4708
|
+
const eventKeysToDispatch = await this.getAllMatchingEventKeys(operation, entityName);
|
|
4709
|
+
const dispatchPromises = eventKeysToDispatch.map((key) => this.eventService.dispatch(key, enhancedData));
|
|
4710
|
+
await Promise.all(dispatchPromises);
|
|
4637
4711
|
}
|
|
4638
4712
|
async getAllMatchingEventKeys(operation, entityName) {
|
|
4639
4713
|
const eventKeys = new Set();
|
|
@@ -4715,6 +4789,118 @@ function getMasterInterfacePropertySortKey(interfaceRow, indexInMasterInterfaceL
|
|
|
4715
4789
|
}
|
|
4716
4790
|
//#endregion
|
|
4717
4791
|
|
|
4792
|
+
/**
|
|
4793
|
+
* Resolves a stable row id from entity list row data.
|
|
4794
|
+
*/
|
|
4795
|
+
function getEntityListRowId(data, key = 'id') {
|
|
4796
|
+
const value = data[key];
|
|
4797
|
+
if (value != null && value !== '') {
|
|
4798
|
+
return String(value);
|
|
4799
|
+
}
|
|
4800
|
+
return '';
|
|
4801
|
+
}
|
|
4802
|
+
/**
|
|
4803
|
+
* Finds row data in a hierarchical grid tree (root rows and nested children).
|
|
4804
|
+
*/
|
|
4805
|
+
function findEntityListRowDataInTree(items, id, key) {
|
|
4806
|
+
for (const item of items) {
|
|
4807
|
+
if (item && typeof item === 'object' && String(item[key]) === id) {
|
|
4808
|
+
return item;
|
|
4809
|
+
}
|
|
4810
|
+
const rec = item;
|
|
4811
|
+
const metaChildren = rec?.['__meta__']?.['children'];
|
|
4812
|
+
const directChildren = rec?.['children'];
|
|
4813
|
+
const childArr = Array.isArray(metaChildren)
|
|
4814
|
+
? metaChildren
|
|
4815
|
+
: Array.isArray(directChildren)
|
|
4816
|
+
? directChildren
|
|
4817
|
+
: null;
|
|
4818
|
+
if (childArr?.length) {
|
|
4819
|
+
const found = findEntityListRowDataInTree(childArr, id, key);
|
|
4820
|
+
if (found) {
|
|
4821
|
+
return found;
|
|
4822
|
+
}
|
|
4823
|
+
}
|
|
4824
|
+
}
|
|
4825
|
+
return null;
|
|
4826
|
+
}
|
|
4827
|
+
/**
|
|
4828
|
+
* Restores expanded rows after data load (parents before children).
|
|
4829
|
+
*/
|
|
4830
|
+
async function restoreEntityListExpandedRows(options) {
|
|
4831
|
+
const pending = [...new Set(options.expandedRowIds.filter(Boolean))];
|
|
4832
|
+
if (!pending.length) {
|
|
4833
|
+
return;
|
|
4834
|
+
}
|
|
4835
|
+
let safety = 0;
|
|
4836
|
+
const maxPasses = Math.max(pending.length * 3, 10);
|
|
4837
|
+
while (pending.length > 0 && safety++ < maxPasses) {
|
|
4838
|
+
const rows = options.getDisplayedRows();
|
|
4839
|
+
let progressed = false;
|
|
4840
|
+
for (let i = pending.length - 1; i >= 0; i--) {
|
|
4841
|
+
const id = pending[i];
|
|
4842
|
+
const item = findEntityListRowDataInTree(rows, id, options.rowKey);
|
|
4843
|
+
if (!item) {
|
|
4844
|
+
continue;
|
|
4845
|
+
}
|
|
4846
|
+
const meta = item['__meta__'];
|
|
4847
|
+
if (meta?.['expanded'] !== true) {
|
|
4848
|
+
await options.expandRow({ data: item });
|
|
4849
|
+
}
|
|
4850
|
+
pending.splice(i, 1);
|
|
4851
|
+
progressed = true;
|
|
4852
|
+
}
|
|
4853
|
+
if (!progressed) {
|
|
4854
|
+
break;
|
|
4855
|
+
}
|
|
4856
|
+
}
|
|
4857
|
+
}
|
|
4858
|
+
|
|
4859
|
+
/**
|
|
4860
|
+
* Applies take/skip to the data source without triggering {@link AXDataSource.load}.
|
|
4861
|
+
*/
|
|
4862
|
+
function applyDataSourcePagingWithoutLoad(dataSource, paging) {
|
|
4863
|
+
const take = Math.max(1, paging.take);
|
|
4864
|
+
const skip = Math.max(0, paging.skip);
|
|
4865
|
+
const page = Math.floor(skip / take);
|
|
4866
|
+
const ds = dataSource;
|
|
4867
|
+
dataSource.config.pageSize = take;
|
|
4868
|
+
if (ds._query) {
|
|
4869
|
+
ds._query.take = take;
|
|
4870
|
+
ds._query.skip = skip;
|
|
4871
|
+
}
|
|
4872
|
+
ds._page = page;
|
|
4873
|
+
}
|
|
4874
|
+
function getDataSourcePageIndex(dataSource) {
|
|
4875
|
+
const ds = dataSource;
|
|
4876
|
+
return ds._page ?? 0;
|
|
4877
|
+
}
|
|
4878
|
+
function normalizeListPaging(paging, defaultTake) {
|
|
4879
|
+
const take = typeof paging?.take === 'number' && paging.take > 0 ? paging.take : defaultTake;
|
|
4880
|
+
const skip = typeof paging?.skip === 'number' && paging.skip >= 0 ? paging.skip : 0;
|
|
4881
|
+
return { take, skip };
|
|
4882
|
+
}
|
|
4883
|
+
|
|
4884
|
+
const AXPEntityListPersistenceModeDefault = 'persistent';
|
|
4885
|
+
function normalizeEntityListPersistenceMode(value) {
|
|
4886
|
+
if (value === 'none' || value === 'persistent' || value === 'route') {
|
|
4887
|
+
return value;
|
|
4888
|
+
}
|
|
4889
|
+
return AXPEntityListPersistenceModeDefault;
|
|
4890
|
+
}
|
|
4891
|
+
function canPersistEntityListState(mode) {
|
|
4892
|
+
return mode !== 'none';
|
|
4893
|
+
}
|
|
4894
|
+
/** `none` never reads list state from user settings. */
|
|
4895
|
+
function shouldLoadEntityListStateFromStorage(mode) {
|
|
4896
|
+
return mode !== 'none';
|
|
4897
|
+
}
|
|
4898
|
+
/** `route` clears stored list state when the route entity (module + name) changes. */
|
|
4899
|
+
function shouldResetEntityListStateOnRouteEntry(mode) {
|
|
4900
|
+
return mode === 'route';
|
|
4901
|
+
}
|
|
4902
|
+
const ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY = 'axp-entity-list-route-context';
|
|
4903
|
+
|
|
4718
4904
|
class AXPEntityCreateViewSectionViewModel {
|
|
4719
4905
|
constructor(entity, section) {
|
|
4720
4906
|
this.entity = entity;
|
|
@@ -7141,6 +7327,98 @@ const AXPEntityDetailViewModelResolver = (route, state, service = inject(AXPEnti
|
|
|
7141
7327
|
return service.create(moduleName, entityName, id);
|
|
7142
7328
|
};
|
|
7143
7329
|
|
|
7330
|
+
class AXPEntityPreloadFiltersViewModel {
|
|
7331
|
+
//#region ---- Constructor ----
|
|
7332
|
+
constructor(injector, config) {
|
|
7333
|
+
this.injector = injector;
|
|
7334
|
+
this.config = config;
|
|
7335
|
+
this.entityDef = cloneDeep(this.config);
|
|
7336
|
+
this.widgetResolver = this.injector.get(AXPWidgetRegistryService);
|
|
7337
|
+
//#endregion
|
|
7338
|
+
//#region ---- Computed Properties ----
|
|
7339
|
+
/**
|
|
7340
|
+
* Entity title
|
|
7341
|
+
*/
|
|
7342
|
+
this.title = computed(() => {
|
|
7343
|
+
return this.entityDef.formats.plural ?? this.entityDef.title;
|
|
7344
|
+
}, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
7345
|
+
/**
|
|
7346
|
+
* Entity description
|
|
7347
|
+
*/
|
|
7348
|
+
this.description = computed(() => {
|
|
7349
|
+
return this.entityDef.interfaces?.master?.list?.description ?? null;
|
|
7350
|
+
}, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
7351
|
+
/**
|
|
7352
|
+
* All filter definitions for properties with preload enabled
|
|
7353
|
+
*/
|
|
7354
|
+
this.preloadFiltersDef = computed(() => {
|
|
7355
|
+
const props = this.entityDef.properties.filter((c) => c.options?.filter?.preload?.enabled);
|
|
7356
|
+
return props.map((e) => {
|
|
7357
|
+
const widgetConfig = this.widgetResolver.resolve(e.schema.interface?.type);
|
|
7358
|
+
const type = e.schema.interface?.type;
|
|
7359
|
+
// Merge validations with existing options
|
|
7360
|
+
const validations = e.options?.filter?.preload?.required
|
|
7361
|
+
? [
|
|
7362
|
+
{
|
|
7363
|
+
rule: 'required',
|
|
7364
|
+
message: 'This field is required',
|
|
7365
|
+
options: {},
|
|
7366
|
+
},
|
|
7367
|
+
]
|
|
7368
|
+
: [];
|
|
7369
|
+
const mergedOptions = {
|
|
7370
|
+
...e.schema.interface?.options,
|
|
7371
|
+
validations,
|
|
7372
|
+
};
|
|
7373
|
+
return {
|
|
7374
|
+
title: e.title,
|
|
7375
|
+
field: e.name,
|
|
7376
|
+
operator: {
|
|
7377
|
+
type: 'contains',
|
|
7378
|
+
},
|
|
7379
|
+
widget: {
|
|
7380
|
+
...e.schema.interface,
|
|
7381
|
+
path: e.name,
|
|
7382
|
+
type,
|
|
7383
|
+
options: mergedOptions,
|
|
7384
|
+
},
|
|
7385
|
+
filters: [],
|
|
7386
|
+
isParametric: false,
|
|
7387
|
+
icon: widgetConfig?.icon,
|
|
7388
|
+
filterType: {
|
|
7389
|
+
advance: false,
|
|
7390
|
+
inline: false,
|
|
7391
|
+
preload: e.options?.filter?.preload,
|
|
7392
|
+
},
|
|
7393
|
+
};
|
|
7394
|
+
});
|
|
7395
|
+
}, ...(ngDevMode ? [{ debugName: "preloadFiltersDef" }] : /* istanbul ignore next */ []));
|
|
7396
|
+
/**
|
|
7397
|
+
* Required filter definitions only
|
|
7398
|
+
*/
|
|
7399
|
+
this.requiredFiltersDef = computed(() => {
|
|
7400
|
+
return this.preloadFiltersDef().filter((c) => c.filterType.preload?.required);
|
|
7401
|
+
}, ...(ngDevMode ? [{ debugName: "requiredFiltersDef" }] : /* istanbul ignore next */ []));
|
|
7402
|
+
}
|
|
7403
|
+
//#region ---- Methods ----
|
|
7404
|
+
/**
|
|
7405
|
+
* Serialize filter values to plain objects (remove signals, functions, etc.)
|
|
7406
|
+
*/
|
|
7407
|
+
serializeFilters(filters) {
|
|
7408
|
+
return JSON.parse(JSON.stringify(filters));
|
|
7409
|
+
}
|
|
7410
|
+
}
|
|
7411
|
+
//#region ---- Resolver ----
|
|
7412
|
+
const AXPEntityPreloadFiltersViewModelResolver = async (route, state) => {
|
|
7413
|
+
const injector = inject(Injector);
|
|
7414
|
+
const entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
7415
|
+
const moduleName = route.parent?.paramMap.get('module');
|
|
7416
|
+
const entityName = route.paramMap.get('entity');
|
|
7417
|
+
const entity = await entityRegistry.resolve(moduleName, entityName);
|
|
7418
|
+
return new AXPEntityPreloadFiltersViewModel(injector, entity);
|
|
7419
|
+
};
|
|
7420
|
+
//#endregion
|
|
7421
|
+
|
|
7144
7422
|
//#endregion
|
|
7145
7423
|
//#region ---- Quick search: schema-driven field paths ----
|
|
7146
7424
|
const NON_TEXT_DATATYPES = new Set([
|
|
@@ -7285,98 +7563,6 @@ async function collectEntityQuickSearchFieldPaths(entity, resolveRelatedDefiniti
|
|
|
7285
7563
|
}
|
|
7286
7564
|
//#endregion
|
|
7287
7565
|
|
|
7288
|
-
class AXPEntityPreloadFiltersViewModel {
|
|
7289
|
-
//#region ---- Constructor ----
|
|
7290
|
-
constructor(injector, config) {
|
|
7291
|
-
this.injector = injector;
|
|
7292
|
-
this.config = config;
|
|
7293
|
-
this.entityDef = cloneDeep(this.config);
|
|
7294
|
-
this.widgetResolver = this.injector.get(AXPWidgetRegistryService);
|
|
7295
|
-
//#endregion
|
|
7296
|
-
//#region ---- Computed Properties ----
|
|
7297
|
-
/**
|
|
7298
|
-
* Entity title
|
|
7299
|
-
*/
|
|
7300
|
-
this.title = computed(() => {
|
|
7301
|
-
return this.entityDef.formats.plural ?? this.entityDef.title;
|
|
7302
|
-
}, ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
7303
|
-
/**
|
|
7304
|
-
* Entity description
|
|
7305
|
-
*/
|
|
7306
|
-
this.description = computed(() => {
|
|
7307
|
-
return this.entityDef.interfaces?.master?.list?.description ?? null;
|
|
7308
|
-
}, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
|
|
7309
|
-
/**
|
|
7310
|
-
* All filter definitions for properties with preload enabled
|
|
7311
|
-
*/
|
|
7312
|
-
this.preloadFiltersDef = computed(() => {
|
|
7313
|
-
const props = this.entityDef.properties.filter((c) => c.options?.filter?.preload?.enabled);
|
|
7314
|
-
return props.map((e) => {
|
|
7315
|
-
const widgetConfig = this.widgetResolver.resolve(e.schema.interface?.type);
|
|
7316
|
-
const type = e.schema.interface?.type;
|
|
7317
|
-
// Merge validations with existing options
|
|
7318
|
-
const validations = e.options?.filter?.preload?.required
|
|
7319
|
-
? [
|
|
7320
|
-
{
|
|
7321
|
-
rule: 'required',
|
|
7322
|
-
message: 'This field is required',
|
|
7323
|
-
options: {},
|
|
7324
|
-
},
|
|
7325
|
-
]
|
|
7326
|
-
: [];
|
|
7327
|
-
const mergedOptions = {
|
|
7328
|
-
...e.schema.interface?.options,
|
|
7329
|
-
validations,
|
|
7330
|
-
};
|
|
7331
|
-
return {
|
|
7332
|
-
title: e.title,
|
|
7333
|
-
field: e.name,
|
|
7334
|
-
operator: {
|
|
7335
|
-
type: 'contains',
|
|
7336
|
-
},
|
|
7337
|
-
widget: {
|
|
7338
|
-
...e.schema.interface,
|
|
7339
|
-
path: e.name,
|
|
7340
|
-
type,
|
|
7341
|
-
options: mergedOptions,
|
|
7342
|
-
},
|
|
7343
|
-
filters: [],
|
|
7344
|
-
isParametric: false,
|
|
7345
|
-
icon: widgetConfig?.icon,
|
|
7346
|
-
filterType: {
|
|
7347
|
-
advance: false,
|
|
7348
|
-
inline: false,
|
|
7349
|
-
preload: e.options?.filter?.preload,
|
|
7350
|
-
},
|
|
7351
|
-
};
|
|
7352
|
-
});
|
|
7353
|
-
}, ...(ngDevMode ? [{ debugName: "preloadFiltersDef" }] : /* istanbul ignore next */ []));
|
|
7354
|
-
/**
|
|
7355
|
-
* Required filter definitions only
|
|
7356
|
-
*/
|
|
7357
|
-
this.requiredFiltersDef = computed(() => {
|
|
7358
|
-
return this.preloadFiltersDef().filter((c) => c.filterType.preload?.required);
|
|
7359
|
-
}, ...(ngDevMode ? [{ debugName: "requiredFiltersDef" }] : /* istanbul ignore next */ []));
|
|
7360
|
-
}
|
|
7361
|
-
//#region ---- Methods ----
|
|
7362
|
-
/**
|
|
7363
|
-
* Serialize filter values to plain objects (remove signals, functions, etc.)
|
|
7364
|
-
*/
|
|
7365
|
-
serializeFilters(filters) {
|
|
7366
|
-
return JSON.parse(JSON.stringify(filters));
|
|
7367
|
-
}
|
|
7368
|
-
}
|
|
7369
|
-
//#region ---- Resolver ----
|
|
7370
|
-
const AXPEntityPreloadFiltersViewModelResolver = async (route, state) => {
|
|
7371
|
-
const injector = inject(Injector);
|
|
7372
|
-
const entityRegistry = inject(AXPEntityDefinitionRegistryService);
|
|
7373
|
-
const moduleName = route.parent?.paramMap.get('module');
|
|
7374
|
-
const entityName = route.paramMap.get('entity');
|
|
7375
|
-
const entity = await entityRegistry.resolve(moduleName, entityName);
|
|
7376
|
-
return new AXPEntityPreloadFiltersViewModel(injector, entity);
|
|
7377
|
-
};
|
|
7378
|
-
//#endregion
|
|
7379
|
-
|
|
7380
7566
|
//#region ---- Path / numeric helpers ----
|
|
7381
7567
|
function getPath(obj, path) {
|
|
7382
7568
|
if (obj == null || path.length === 0) {
|
|
@@ -7569,128 +7755,32 @@ async function filterSortEntityRows(entityName, request, adapters) {
|
|
|
7569
7755
|
if (request.sort && request.sort.length) {
|
|
7570
7756
|
result = applySortArray(result, request.sort);
|
|
7571
7757
|
}
|
|
7572
|
-
if (request.filter && isCategoryFilter(request.filter)) {
|
|
7573
|
-
result = await applyRecursiveCategoryFilter(result, request.filter, entityName, adapters.getAllChildCategoryIds);
|
|
7574
|
-
}
|
|
7575
|
-
else {
|
|
7576
|
-
result = applyFilterArray(result, request.filter ? [request.filter] : []);
|
|
7577
|
-
}
|
|
7578
|
-
if (isCategoryEntity(entityName)) {
|
|
7579
|
-
result = await calculateChildrenCounts(result, entityName, adapters.getDirectChildCount);
|
|
7580
|
-
}
|
|
7581
|
-
return result;
|
|
7582
|
-
}
|
|
7583
|
-
/**
|
|
7584
|
-
* Shared entity query logic: sort, filter (including recursive category filter), childrenCount, pagination.
|
|
7585
|
-
*/
|
|
7586
|
-
async function runEntityQuery(entityName, request, adapters) {
|
|
7587
|
-
const rows = await filterSortEntityRows(entityName, request, adapters);
|
|
7588
|
-
const skip = request.skip ?? 0;
|
|
7589
|
-
const take = request.take ?? 0;
|
|
7590
|
-
return {
|
|
7591
|
-
total: rows.length,
|
|
7592
|
-
items: rows.slice(skip, skip + take),
|
|
7593
|
-
};
|
|
7594
|
-
}
|
|
7595
|
-
//#endregion
|
|
7596
|
-
|
|
7597
|
-
//#endregion
|
|
7598
|
-
|
|
7599
|
-
//#region ---- Imports ----
|
|
7600
|
-
//#endregion
|
|
7601
|
-
//#region ---- Constants ----
|
|
7602
|
-
const DEFAULT_RELATED_ORDER_STEP = 10;
|
|
7603
|
-
const DEFAULT_PLUGIN_ZONE_FLOOR = 100_000;
|
|
7604
|
-
/** Space per plugin slot so multiple fields in one slot do not cross into the next. */
|
|
7605
|
-
const PLUGIN_SLOT_SPAN = 10_000;
|
|
7606
|
-
const SUB_ORDER_STEP = 10;
|
|
7607
|
-
const PLUGIN_SLOT_INDEX = {
|
|
7608
|
-
'meta-data-builder': 0,
|
|
7609
|
-
attachments: 1,
|
|
7610
|
-
documents: 2,
|
|
7611
|
-
comments: 3,
|
|
7612
|
-
history: 4,
|
|
7613
|
-
};
|
|
7614
|
-
//#endregion
|
|
7615
|
-
//#region ---- Helpers ----
|
|
7616
|
-
function shouldSkipPageForMax(page, skip) {
|
|
7617
|
-
if (!skip) {
|
|
7618
|
-
return false;
|
|
7619
|
-
}
|
|
7620
|
-
if (page.componentKey !== skip.componentKey) {
|
|
7621
|
-
return false;
|
|
7622
|
-
}
|
|
7623
|
-
if (skip.field !== undefined) {
|
|
7624
|
-
return page.field === skip.field;
|
|
7625
|
-
}
|
|
7626
|
-
return true;
|
|
7627
|
-
}
|
|
7628
|
-
function normalizeRelatedPageListDetailOrders(relatedEntities, step) {
|
|
7629
|
-
const pageTabRelated = (relatedEntities ?? []).filter((re) => re.layout?.type === 'page-list' || re.layout?.type === 'page-detail');
|
|
7630
|
-
let maxExplicit = 0;
|
|
7631
|
-
for (const re of pageTabRelated) {
|
|
7632
|
-
const o = re.layout?.order;
|
|
7633
|
-
if (typeof o === 'number' && Number.isFinite(o)) {
|
|
7634
|
-
maxExplicit = Math.max(maxExplicit, o);
|
|
7635
|
-
}
|
|
7636
|
-
}
|
|
7637
|
-
let cursor = maxExplicit;
|
|
7638
|
-
for (const re of pageTabRelated) {
|
|
7639
|
-
const layout = re.layout;
|
|
7640
|
-
if (!layout || layout.order != null) {
|
|
7641
|
-
continue;
|
|
7642
|
-
}
|
|
7643
|
-
cursor += step;
|
|
7644
|
-
re.layout = { ...layout, order: cursor };
|
|
7645
|
-
}
|
|
7646
|
-
let afterMax = 0;
|
|
7647
|
-
for (const re of pageTabRelated) {
|
|
7648
|
-
const o = re.layout?.order;
|
|
7649
|
-
if (typeof o === 'number' && Number.isFinite(o)) {
|
|
7650
|
-
afterMax = Math.max(afterMax, o);
|
|
7651
|
-
}
|
|
7652
|
-
}
|
|
7653
|
-
return afterMax;
|
|
7654
|
-
}
|
|
7655
|
-
/**
|
|
7656
|
-
* Ordinal within a slot for multi-field pages (attachments, meta-data-builder), stable by field name.
|
|
7657
|
-
*/
|
|
7658
|
-
function subOrderWithinComponentSlot(pages, componentKey, skip, currentField) {
|
|
7659
|
-
const peerFieldKeys = (pages ?? [])
|
|
7660
|
-
.filter((p) => p.componentKey === componentKey && !shouldSkipPageForMax(p, skip))
|
|
7661
|
-
.map((p) => p.field ?? '');
|
|
7662
|
-
const keySet = new Set(peerFieldKeys);
|
|
7663
|
-
keySet.add(currentField ?? '');
|
|
7664
|
-
const sorted = [...keySet].sort((a, b) => a.localeCompare(b));
|
|
7665
|
-
const index = sorted.indexOf(currentField ?? '');
|
|
7666
|
-
return Math.max(0, index) * SUB_ORDER_STEP;
|
|
7758
|
+
if (request.filter && isCategoryFilter(request.filter)) {
|
|
7759
|
+
result = await applyRecursiveCategoryFilter(result, request.filter, entityName, adapters.getAllChildCategoryIds);
|
|
7760
|
+
}
|
|
7761
|
+
else {
|
|
7762
|
+
result = applyFilterArray(result, request.filter ? [request.filter] : []);
|
|
7763
|
+
}
|
|
7764
|
+
if (isCategoryEntity(entityName)) {
|
|
7765
|
+
result = await calculateChildrenCounts(result, entityName, adapters.getDirectChildCount);
|
|
7766
|
+
}
|
|
7767
|
+
return result;
|
|
7667
7768
|
}
|
|
7668
|
-
//#endregion
|
|
7669
|
-
//#region ---- Public API ----
|
|
7670
7769
|
/**
|
|
7671
|
-
*
|
|
7672
|
-
*
|
|
7673
|
-
* 1. Assigns finite `layout.order` values to related `page-list` / `page-detail` rows that omit
|
|
7674
|
-
* `order` (the composer otherwise treats them as +Infinity).
|
|
7675
|
-
* 2. Places plugin tabs in a fixed relative order: meta-data-builder → attachments → documents →
|
|
7676
|
-
* comments → history, after all related tabs.
|
|
7770
|
+
* Shared entity query logic: sort, filter (including recursive category filter), childrenCount, pagination.
|
|
7677
7771
|
*/
|
|
7678
|
-
function
|
|
7679
|
-
const
|
|
7680
|
-
const
|
|
7681
|
-
const
|
|
7682
|
-
|
|
7683
|
-
|
|
7684
|
-
|
|
7685
|
-
|
|
7686
|
-
return pluginZoneStart + slotIndex * PLUGIN_SLOT_SPAN + subOrder;
|
|
7772
|
+
async function runEntityQuery(entityName, request, adapters) {
|
|
7773
|
+
const rows = await filterSortEntityRows(entityName, request, adapters);
|
|
7774
|
+
const skip = request.skip ?? 0;
|
|
7775
|
+
const take = request.take ?? 0;
|
|
7776
|
+
return {
|
|
7777
|
+
total: rows.length,
|
|
7778
|
+
items: rows.slice(skip, skip + take),
|
|
7779
|
+
};
|
|
7687
7780
|
}
|
|
7688
7781
|
//#endregion
|
|
7689
7782
|
|
|
7690
|
-
|
|
7691
|
-
* Re-export from domain to avoid circular dependency: layout/components must not depend on layout/entity.
|
|
7692
|
-
* Consumers that only need the token/interface can import from @acorex/platform/domain.
|
|
7693
|
-
*/
|
|
7783
|
+
//#endregion
|
|
7694
7784
|
|
|
7695
7785
|
/** Component key used when display is 'page'. Register a page component with this key via AXP_PAGE_COMPONENT_PROVIDER. */
|
|
7696
7786
|
const ATTACHMENTS_PAGE_COMPONENT_KEY = 'entity-attachments-page';
|
|
@@ -7890,7 +7980,7 @@ class AXMAttachmentsPageComponentProvider {
|
|
|
7890
7980
|
return [
|
|
7891
7981
|
{
|
|
7892
7982
|
key: ATTACHMENTS_PAGE_COMPONENT_KEY,
|
|
7893
|
-
loader: () => import('./acorex-platform-layout-entity-attachments-page.component-
|
|
7983
|
+
loader: () => import('./acorex-platform-layout-entity-attachments-page.component-D8iQnT-R.mjs').then((m) => m.AXMAttachmentsPageComponent),
|
|
7894
7984
|
},
|
|
7895
7985
|
];
|
|
7896
7986
|
}
|
|
@@ -13233,7 +13323,7 @@ class AXPEntityListWidgetViewComponent extends AXPValueWidgetComponent {
|
|
|
13233
13323
|
></ng-container>
|
|
13234
13324
|
}
|
|
13235
13325
|
</div>
|
|
13236
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { 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: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type:
|
|
13326
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: i3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { 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: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
13237
13327
|
}
|
|
13238
13328
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityListWidgetViewComponent, decorators: [{
|
|
13239
13329
|
type: Component,
|
|
@@ -13398,6 +13488,382 @@ const AXPEntityListWidget = {
|
|
|
13398
13488
|
},
|
|
13399
13489
|
};
|
|
13400
13490
|
|
|
13491
|
+
class AXPPageComponentWidgetViewComponent extends AXPBaseWidgetComponent {
|
|
13492
|
+
constructor() {
|
|
13493
|
+
super(...arguments);
|
|
13494
|
+
//#region ---- Services & Dependencies ----
|
|
13495
|
+
this.deviceService = inject(AXPDeviceService);
|
|
13496
|
+
this.pageRenderer = viewChild(AXPPageComponentRendererDirective, ...(ngDevMode ? [{ debugName: "pageRenderer" }] : /* istanbul ignore next */ []));
|
|
13497
|
+
//#endregion
|
|
13498
|
+
//#region ---- Computed Options ----
|
|
13499
|
+
this.componentKey = computed(() => this.options()['componentKey'], ...(ngDevMode ? [{ debugName: "componentKey" }] : /* istanbul ignore next */ []));
|
|
13500
|
+
this.pageConfig = computed(() => {
|
|
13501
|
+
const field = this.options()['field'];
|
|
13502
|
+
return typeof field === 'string' ? { field } : undefined;
|
|
13503
|
+
}, ...(ngDevMode ? [{ debugName: "pageConfig" }] : /* istanbul ignore next */ []));
|
|
13504
|
+
this.pageOptions = computed(() => this.options()['pageOptions'] ?? {}, ...(ngDevMode ? [{ debugName: "pageOptions" }] : /* istanbul ignore next */ []));
|
|
13505
|
+
this.rootContext = computed(() => this.contextService.snapshot(), ...(ngDevMode ? [{ debugName: "rootContext" }] : /* istanbul ignore next */ []));
|
|
13506
|
+
this.showPageActions = computed(() => this.options()['showPageActions'] ?? true, ...(ngDevMode ? [{ debugName: "showPageActions" }] : /* istanbul ignore next */ []));
|
|
13507
|
+
//#endregion
|
|
13508
|
+
//#region ---- Toolbar Actions ----
|
|
13509
|
+
this.toolbarPrimaryActions = signal([], ...(ngDevMode ? [{ debugName: "toolbarPrimaryActions" }] : /* istanbul ignore next */ []));
|
|
13510
|
+
this.toolbarSecondaryActions = signal([], ...(ngDevMode ? [{ debugName: "toolbarSecondaryActions" }] : /* istanbul ignore next */ []));
|
|
13511
|
+
/** Bumped when the embedded page finishes async mount so toolbar can bind to the live instance. */
|
|
13512
|
+
this.pageHostRevision = signal(0, ...(ngDevMode ? [{ debugName: "pageHostRevision" }] : /* istanbul ignore next */ []));
|
|
13513
|
+
/** Keeps the toolbar in sync when the embedded page calls `recompute()` (e.g. dirty state). */
|
|
13514
|
+
this.#syncPageActionsEffect = effect(() => {
|
|
13515
|
+
this.pageHostRevision();
|
|
13516
|
+
this.componentKey();
|
|
13517
|
+
const instance = this.resolvePageHost();
|
|
13518
|
+
if (!instance) {
|
|
13519
|
+
return;
|
|
13520
|
+
}
|
|
13521
|
+
instance.primaryMenuItems();
|
|
13522
|
+
instance.secondaryMenuItems();
|
|
13523
|
+
console.log({ primaryMenuItems: instance.primaryMenuItems(), secondaryMenuItems: instance.secondaryMenuItems() });
|
|
13524
|
+
untracked(() => this.syncActionsFromPageInstance(instance));
|
|
13525
|
+
}, ...(ngDevMode ? [{ debugName: "#syncPageActionsEffect" }] : /* istanbul ignore next */ []));
|
|
13526
|
+
}
|
|
13527
|
+
/** Keeps the toolbar in sync when the embedded page calls `recompute()` (e.g. dirty state). */
|
|
13528
|
+
#syncPageActionsEffect;
|
|
13529
|
+
//#endregion
|
|
13530
|
+
//#region ---- Lifecycle ----
|
|
13531
|
+
ngOnInit() {
|
|
13532
|
+
super.ngOnInit();
|
|
13533
|
+
const widgetName = this.name;
|
|
13534
|
+
if (widgetName) {
|
|
13535
|
+
this.layoutService.registerWidget(widgetName, this);
|
|
13536
|
+
}
|
|
13537
|
+
this.setStatus(AXPWidgetStatus.Rendered);
|
|
13538
|
+
}
|
|
13539
|
+
//#endregion
|
|
13540
|
+
//#region ---- Public API ----
|
|
13541
|
+
api() {
|
|
13542
|
+
const self = this;
|
|
13543
|
+
return {
|
|
13544
|
+
syncContext: () => {
|
|
13545
|
+
self.syncPageComponentIntoFormContext();
|
|
13546
|
+
},
|
|
13547
|
+
refreshPageActions: () => {
|
|
13548
|
+
self.refreshPageActions();
|
|
13549
|
+
},
|
|
13550
|
+
};
|
|
13551
|
+
}
|
|
13552
|
+
/** Re-reads toolbar actions from the mounted page component. */
|
|
13553
|
+
refreshPageActions() {
|
|
13554
|
+
const instance = this.resolvePageHost();
|
|
13555
|
+
if (!instance) {
|
|
13556
|
+
this.toolbarPrimaryActions.set([]);
|
|
13557
|
+
this.toolbarSecondaryActions.set([]);
|
|
13558
|
+
return;
|
|
13559
|
+
}
|
|
13560
|
+
this.syncActionsFromPageInstance(instance);
|
|
13561
|
+
}
|
|
13562
|
+
//#endregion
|
|
13563
|
+
//#region ---- UI Handlers ----
|
|
13564
|
+
handleComponentReady() {
|
|
13565
|
+
this.pageHostRevision.update((value) => value + 1);
|
|
13566
|
+
}
|
|
13567
|
+
async handleActionClick(item) {
|
|
13568
|
+
if (!item.command || (item.items?.length ?? 0) > 0) {
|
|
13569
|
+
return;
|
|
13570
|
+
}
|
|
13571
|
+
const instance = this.resolvePageHost();
|
|
13572
|
+
if (!instance) {
|
|
13573
|
+
return;
|
|
13574
|
+
}
|
|
13575
|
+
const command = normalizeExecuteCommand(item.command);
|
|
13576
|
+
await instance.execute(command);
|
|
13577
|
+
this.pageHostRevision.update((value) => value + 1);
|
|
13578
|
+
}
|
|
13579
|
+
//#endregion
|
|
13580
|
+
//#region ---- Context Sync ----
|
|
13581
|
+
/** Merges the mounted page component's wizard payload into the dialog form context. */
|
|
13582
|
+
syncPageComponentIntoFormContext() {
|
|
13583
|
+
const partial = this.resolvePageHost()?.getWizardStepContext?.();
|
|
13584
|
+
if (!partial) {
|
|
13585
|
+
return;
|
|
13586
|
+
}
|
|
13587
|
+
for (const [path, value] of Object.entries(partial)) {
|
|
13588
|
+
this.contextService.update(path, value);
|
|
13589
|
+
}
|
|
13590
|
+
}
|
|
13591
|
+
//#endregion
|
|
13592
|
+
//#region ---- Utility Methods ----
|
|
13593
|
+
resolvePageHost() {
|
|
13594
|
+
const instance = this.pageRenderer()?.getMountedPageInstance();
|
|
13595
|
+
return isPageToolbarHost(instance) ? instance : null;
|
|
13596
|
+
}
|
|
13597
|
+
syncActionsFromPageInstance(page) {
|
|
13598
|
+
const primary = page.primaryMenuItems();
|
|
13599
|
+
const secondary = page.secondaryMenuItems();
|
|
13600
|
+
this.toolbarPrimaryActions.set(splitToolbarPrimaryActions(primary));
|
|
13601
|
+
this.toolbarSecondaryActions.set(splitToolbarSecondaryActions(primary, secondary));
|
|
13602
|
+
}
|
|
13603
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentWidgetViewComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
13604
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPPageComponentWidgetViewComponent, isStandalone: true, selector: "axp-page-component-widget-view", host: { classAttribute: "ax-block ax-w-full ax-h-full ax-min-h-0" }, viewQueries: [{ propertyName: "pageRenderer", first: true, predicate: AXPPageComponentRendererDirective, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
|
|
13605
|
+
@if (showPageActions() && (toolbarPrimaryActions().length || toolbarSecondaryActions().length)) {
|
|
13606
|
+
<div class="ax-flex ax-flex-wrap ax-gap-2 ax-justify-end ax-mb-4">
|
|
13607
|
+
@for (action of toolbarPrimaryActions(); track action.title) {
|
|
13608
|
+
@if (action.visible !== false) {
|
|
13609
|
+
<ax-button
|
|
13610
|
+
[class.ax-sm]="deviceService.isSmall()"
|
|
13611
|
+
[iconOnly]="deviceService.isSmall()"
|
|
13612
|
+
[disabled]="action.disabled"
|
|
13613
|
+
[text]="(action.title | translate | async)!"
|
|
13614
|
+
[look]="'solid'"
|
|
13615
|
+
[color]="action.color ?? 'default'"
|
|
13616
|
+
(onClick)="handleActionClick(action)"
|
|
13617
|
+
>
|
|
13618
|
+
<ax-prefix>
|
|
13619
|
+
<i [class]="action.icon"></i>
|
|
13620
|
+
</ax-prefix>
|
|
13621
|
+
@if (action.items?.length) {
|
|
13622
|
+
<ax-dropdown-panel #panel>
|
|
13623
|
+
<ax-button-item-list>
|
|
13624
|
+
@for (sub of action.items; track sub.title) {
|
|
13625
|
+
@if (sub.visible !== false) {
|
|
13626
|
+
<ax-button-item
|
|
13627
|
+
[text]="(sub.title | translate | async)!"
|
|
13628
|
+
[color]="sub.color"
|
|
13629
|
+
[disabled]="sub.disabled"
|
|
13630
|
+
(onClick)="handleActionClick(sub)"
|
|
13631
|
+
>
|
|
13632
|
+
<ax-prefix>
|
|
13633
|
+
<i [class]="sub.icon"></i>
|
|
13634
|
+
</ax-prefix>
|
|
13635
|
+
</ax-button-item>
|
|
13636
|
+
@if (sub.break) {
|
|
13637
|
+
<ax-divider></ax-divider>
|
|
13638
|
+
}
|
|
13639
|
+
}
|
|
13640
|
+
}
|
|
13641
|
+
</ax-button-item-list>
|
|
13642
|
+
</ax-dropdown-panel>
|
|
13643
|
+
}
|
|
13644
|
+
</ax-button>
|
|
13645
|
+
}
|
|
13646
|
+
}
|
|
13647
|
+
@if (toolbarSecondaryActions().length) {
|
|
13648
|
+
<ax-button
|
|
13649
|
+
[class.ax-sm]="deviceService.isSmall()"
|
|
13650
|
+
[iconOnly]="deviceService.isSmall()"
|
|
13651
|
+
[text]="'@general:terms.interface.actions' | translate | async"
|
|
13652
|
+
[look]="deviceService.isSmall() ? 'blank' : 'solid'"
|
|
13653
|
+
[color]="'default'"
|
|
13654
|
+
>
|
|
13655
|
+
<ax-prefix>
|
|
13656
|
+
<i class="fa-solid fa-ellipsis-vertical"></i>
|
|
13657
|
+
</ax-prefix>
|
|
13658
|
+
<ax-dropdown-panel #panel>
|
|
13659
|
+
<ax-button-item-list>
|
|
13660
|
+
@for (item of toolbarSecondaryActions(); track item.title) {
|
|
13661
|
+
@if (item.visible !== false) {
|
|
13662
|
+
<ax-button-item
|
|
13663
|
+
[text]="(item.title | translate | async)!"
|
|
13664
|
+
[color]="item.color"
|
|
13665
|
+
[disabled]="item.disabled"
|
|
13666
|
+
(onClick)="handleActionClick(item)"
|
|
13667
|
+
>
|
|
13668
|
+
<ax-prefix>
|
|
13669
|
+
<i [class]="item.icon"></i>
|
|
13670
|
+
</ax-prefix>
|
|
13671
|
+
</ax-button-item>
|
|
13672
|
+
@if (item.break) {
|
|
13673
|
+
<ax-divider></ax-divider>
|
|
13674
|
+
}
|
|
13675
|
+
}
|
|
13676
|
+
}
|
|
13677
|
+
</ax-button-item-list>
|
|
13678
|
+
</ax-dropdown-panel>
|
|
13679
|
+
</ax-button>
|
|
13680
|
+
}
|
|
13681
|
+
</div>
|
|
13682
|
+
}
|
|
13683
|
+
<div
|
|
13684
|
+
class="ax-w-full ax-min-h-0"
|
|
13685
|
+
axp-page-component-renderer
|
|
13686
|
+
[componentKey]="componentKey()"
|
|
13687
|
+
[rootContext]="rootContext()"
|
|
13688
|
+
[pageConfig]="pageConfig()"
|
|
13689
|
+
[options]="pageOptions()"
|
|
13690
|
+
(componentReady)="handleComponentReady()"
|
|
13691
|
+
></div>
|
|
13692
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "directive", type: AXPPageComponentRendererDirective, selector: "[axp-page-component-renderer]", inputs: ["componentKey", "rootContext", "pageConfig", "options"], outputs: ["componentReady"] }, { 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: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
13693
|
+
}
|
|
13694
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPPageComponentWidgetViewComponent, decorators: [{
|
|
13695
|
+
type: Component,
|
|
13696
|
+
args: [{
|
|
13697
|
+
selector: 'axp-page-component-widget-view',
|
|
13698
|
+
host: {
|
|
13699
|
+
class: 'ax-block ax-w-full ax-h-full ax-min-h-0',
|
|
13700
|
+
},
|
|
13701
|
+
template: `
|
|
13702
|
+
@if (showPageActions() && (toolbarPrimaryActions().length || toolbarSecondaryActions().length)) {
|
|
13703
|
+
<div class="ax-flex ax-flex-wrap ax-gap-2 ax-justify-end ax-mb-4">
|
|
13704
|
+
@for (action of toolbarPrimaryActions(); track action.title) {
|
|
13705
|
+
@if (action.visible !== false) {
|
|
13706
|
+
<ax-button
|
|
13707
|
+
[class.ax-sm]="deviceService.isSmall()"
|
|
13708
|
+
[iconOnly]="deviceService.isSmall()"
|
|
13709
|
+
[disabled]="action.disabled"
|
|
13710
|
+
[text]="(action.title | translate | async)!"
|
|
13711
|
+
[look]="'solid'"
|
|
13712
|
+
[color]="action.color ?? 'default'"
|
|
13713
|
+
(onClick)="handleActionClick(action)"
|
|
13714
|
+
>
|
|
13715
|
+
<ax-prefix>
|
|
13716
|
+
<i [class]="action.icon"></i>
|
|
13717
|
+
</ax-prefix>
|
|
13718
|
+
@if (action.items?.length) {
|
|
13719
|
+
<ax-dropdown-panel #panel>
|
|
13720
|
+
<ax-button-item-list>
|
|
13721
|
+
@for (sub of action.items; track sub.title) {
|
|
13722
|
+
@if (sub.visible !== false) {
|
|
13723
|
+
<ax-button-item
|
|
13724
|
+
[text]="(sub.title | translate | async)!"
|
|
13725
|
+
[color]="sub.color"
|
|
13726
|
+
[disabled]="sub.disabled"
|
|
13727
|
+
(onClick)="handleActionClick(sub)"
|
|
13728
|
+
>
|
|
13729
|
+
<ax-prefix>
|
|
13730
|
+
<i [class]="sub.icon"></i>
|
|
13731
|
+
</ax-prefix>
|
|
13732
|
+
</ax-button-item>
|
|
13733
|
+
@if (sub.break) {
|
|
13734
|
+
<ax-divider></ax-divider>
|
|
13735
|
+
}
|
|
13736
|
+
}
|
|
13737
|
+
}
|
|
13738
|
+
</ax-button-item-list>
|
|
13739
|
+
</ax-dropdown-panel>
|
|
13740
|
+
}
|
|
13741
|
+
</ax-button>
|
|
13742
|
+
}
|
|
13743
|
+
}
|
|
13744
|
+
@if (toolbarSecondaryActions().length) {
|
|
13745
|
+
<ax-button
|
|
13746
|
+
[class.ax-sm]="deviceService.isSmall()"
|
|
13747
|
+
[iconOnly]="deviceService.isSmall()"
|
|
13748
|
+
[text]="'@general:terms.interface.actions' | translate | async"
|
|
13749
|
+
[look]="deviceService.isSmall() ? 'blank' : 'solid'"
|
|
13750
|
+
[color]="'default'"
|
|
13751
|
+
>
|
|
13752
|
+
<ax-prefix>
|
|
13753
|
+
<i class="fa-solid fa-ellipsis-vertical"></i>
|
|
13754
|
+
</ax-prefix>
|
|
13755
|
+
<ax-dropdown-panel #panel>
|
|
13756
|
+
<ax-button-item-list>
|
|
13757
|
+
@for (item of toolbarSecondaryActions(); track item.title) {
|
|
13758
|
+
@if (item.visible !== false) {
|
|
13759
|
+
<ax-button-item
|
|
13760
|
+
[text]="(item.title | translate | async)!"
|
|
13761
|
+
[color]="item.color"
|
|
13762
|
+
[disabled]="item.disabled"
|
|
13763
|
+
(onClick)="handleActionClick(item)"
|
|
13764
|
+
>
|
|
13765
|
+
<ax-prefix>
|
|
13766
|
+
<i [class]="item.icon"></i>
|
|
13767
|
+
</ax-prefix>
|
|
13768
|
+
</ax-button-item>
|
|
13769
|
+
@if (item.break) {
|
|
13770
|
+
<ax-divider></ax-divider>
|
|
13771
|
+
}
|
|
13772
|
+
}
|
|
13773
|
+
}
|
|
13774
|
+
</ax-button-item-list>
|
|
13775
|
+
</ax-dropdown-panel>
|
|
13776
|
+
</ax-button>
|
|
13777
|
+
}
|
|
13778
|
+
</div>
|
|
13779
|
+
}
|
|
13780
|
+
<div
|
|
13781
|
+
class="ax-w-full ax-min-h-0"
|
|
13782
|
+
axp-page-component-renderer
|
|
13783
|
+
[componentKey]="componentKey()"
|
|
13784
|
+
[rootContext]="rootContext()"
|
|
13785
|
+
[pageConfig]="pageConfig()"
|
|
13786
|
+
[options]="pageOptions()"
|
|
13787
|
+
(componentReady)="handleComponentReady()"
|
|
13788
|
+
></div>
|
|
13789
|
+
`,
|
|
13790
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
13791
|
+
imports: [
|
|
13792
|
+
AXPWidgetCoreModule,
|
|
13793
|
+
AXPPageComponentRendererDirective,
|
|
13794
|
+
AXButtonModule,
|
|
13795
|
+
AXDecoratorModule,
|
|
13796
|
+
AXDropdownModule,
|
|
13797
|
+
AXTranslationModule,
|
|
13798
|
+
AsyncPipe,
|
|
13799
|
+
],
|
|
13800
|
+
}]
|
|
13801
|
+
}], propDecorators: { pageRenderer: [{ type: i0.ViewChild, args: [i0.forwardRef(() => AXPPageComponentRendererDirective), { isSignal: true }] }] } });
|
|
13802
|
+
function isPageToolbarHost(instance) {
|
|
13803
|
+
return (!!instance &&
|
|
13804
|
+
typeof instance === 'object' &&
|
|
13805
|
+
'primaryMenuItems' in instance &&
|
|
13806
|
+
'secondaryMenuItems' in instance &&
|
|
13807
|
+
typeof instance.execute === 'function');
|
|
13808
|
+
}
|
|
13809
|
+
function splitToolbarPrimaryActions(actions) {
|
|
13810
|
+
return actions.filter((action) => action.visible !== false && isHeaderZoneAction(action) && getActionPriority(action) === 'primary');
|
|
13811
|
+
}
|
|
13812
|
+
function splitToolbarSecondaryActions(primary, secondary) {
|
|
13813
|
+
const fromPrimary = primary.filter((action) => action.visible !== false && isHeaderZoneAction(action) && getActionPriority(action) === 'secondary');
|
|
13814
|
+
const fromSecondary = secondary.filter((action) => action.visible !== false && isHeaderZoneAction(action));
|
|
13815
|
+
return [...fromPrimary, ...fromSecondary];
|
|
13816
|
+
}
|
|
13817
|
+
function isHeaderZoneAction(action) {
|
|
13818
|
+
return action.zone === 'header';
|
|
13819
|
+
}
|
|
13820
|
+
function getActionPriority(action) {
|
|
13821
|
+
const priority = action.priority;
|
|
13822
|
+
return priority === 'secondary' ? 'secondary' : 'primary';
|
|
13823
|
+
}
|
|
13824
|
+
function normalizeExecuteCommand(command) {
|
|
13825
|
+
if (command == null) {
|
|
13826
|
+
return { name: '', options: {} };
|
|
13827
|
+
}
|
|
13828
|
+
if (typeof command === 'string') {
|
|
13829
|
+
return { name: command, options: {} };
|
|
13830
|
+
}
|
|
13831
|
+
return {
|
|
13832
|
+
name: command.name,
|
|
13833
|
+
options: command.options ?? {},
|
|
13834
|
+
};
|
|
13835
|
+
}
|
|
13836
|
+
|
|
13837
|
+
var pageComponentWidgetView_component = /*#__PURE__*/Object.freeze({
|
|
13838
|
+
__proto__: null,
|
|
13839
|
+
AXPPageComponentWidgetViewComponent: AXPPageComponentWidgetViewComponent
|
|
13840
|
+
});
|
|
13841
|
+
|
|
13842
|
+
const AXPPageComponentWidget = {
|
|
13843
|
+
name: 'page-component',
|
|
13844
|
+
title: 'Page Component',
|
|
13845
|
+
description: 'Renders a registered page component via page-component-renderer and exposes its toolbar actions',
|
|
13846
|
+
type: 'view',
|
|
13847
|
+
categories: [],
|
|
13848
|
+
groups: [AXPWidgetGroupEnum.FormElement],
|
|
13849
|
+
icon: 'fa-light fa-file-lines',
|
|
13850
|
+
properties: [AXP_NAME_PROPERTY],
|
|
13851
|
+
components: {
|
|
13852
|
+
view: {
|
|
13853
|
+
component: () => Promise.resolve().then(function () { return pageComponentWidgetView_component; }).then((c) => c.AXPPageComponentWidgetViewComponent),
|
|
13854
|
+
},
|
|
13855
|
+
edit: {
|
|
13856
|
+
component: () => Promise.resolve().then(function () { return pageComponentWidgetView_component; }).then((c) => c.AXPPageComponentWidgetViewComponent),
|
|
13857
|
+
},
|
|
13858
|
+
print: {
|
|
13859
|
+
component: () => Promise.resolve().then(function () { return pageComponentWidgetView_component; }).then((c) => c.AXPPageComponentWidgetViewComponent),
|
|
13860
|
+
},
|
|
13861
|
+
designer: {
|
|
13862
|
+
component: () => Promise.resolve().then(function () { return pageComponentWidgetView_component; }).then((c) => c.AXPPageComponentWidgetViewComponent),
|
|
13863
|
+
},
|
|
13864
|
+
},
|
|
13865
|
+
};
|
|
13866
|
+
|
|
13401
13867
|
class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
|
|
13402
13868
|
constructor() {
|
|
13403
13869
|
super(...arguments);
|
|
@@ -19108,7 +19574,7 @@ class AXPFileUploaderWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
19108
19574
|
(onRename)="handleFileRename($event)"
|
|
19109
19575
|
></axp-file-list>
|
|
19110
19576
|
</div>
|
|
19111
|
-
`, isInline: true, styles: [":host{border-color:rgba(var(--ax-comp-editor-border-color))}:host.axp-file-uploader-widget-edit--borderless{border:none!important}.__drag-over{background-color:rgba(var(--ax-sys-color-primary-50),.1);border:2px dashed rgb(var(--ax-sys-color-primary-500));border-radius:.375rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "directive", type: AXUploaderZoneDirective, selector: "[axUploaderZone]", inputs: ["multiple", "accept", "overlayTemplate", "disableBrowse", "disableDragDrop"], outputs: ["fileChange", "onChanged", "dragEnter", "dragLeave", "dragOver", "onFileUploadComplete", "onFilesUploadComplete"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type:
|
|
19577
|
+
`, isInline: true, styles: [":host{border-color:rgba(var(--ax-comp-editor-border-color))}:host.axp-file-uploader-widget-edit--borderless{border:none!important}.__drag-over{background-color:rgba(var(--ax-sys-color-primary-50),.1);border:2px dashed rgb(var(--ax-sys-color-primary-500));border-radius:.375rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { 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: "component", type: i1.AXButtonItemComponent, selector: "ax-button-item", inputs: ["color", "disabled", "text", "selected", "divided", "data", "name"], outputs: ["onClick", "onFocus", "onBlur", "disabledChange"] }, { kind: "component", type: i1.AXButtonItemListComponent, selector: "ax-button-item-list", inputs: ["items", "closeParentOnClick", "lockOnLoading"], outputs: ["onItemClick"] }, { kind: "directive", type: AXUploaderZoneDirective, selector: "[axUploaderZone]", inputs: ["multiple", "accept", "overlayTemplate", "disableBrowse", "disableDragDrop"], outputs: ["fileChange", "onChanged", "dragEnter", "dragLeave", "dragOver", "onFileUploadComplete", "onFilesUploadComplete"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "component", type: i3$3.AXDropdownPanelComponent, selector: "ax-dropdown-panel", inputs: ["isOpen", "fitParent", "dropdownWidth", "position", "placement", "_target", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPComponentSlotModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i6.AXTranslatorDirective, selector: "[translate]" }, { kind: "component", type: AXPFileListComponent, selector: "axp-file-list", inputs: ["readonly", "fileEditable", "enableTitleDescription", "multiple", "files", "plugins", "excludePlugins", "capabilities"], outputs: ["onRemove", "onRevert", "onRename"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
19112
19578
|
}
|
|
19113
19579
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPFileUploaderWidgetEditComponent, decorators: [{
|
|
19114
19580
|
type: Component,
|
|
@@ -20166,7 +20632,7 @@ class AXPSelectorStructureWidgetEditComponent extends AXPValueWidgetComponent {
|
|
|
20166
20632
|
} @else {
|
|
20167
20633
|
<span class="ax-text-muted">{{ disabledHint() }}</span>
|
|
20168
20634
|
}
|
|
20169
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i2$2.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i5$1.AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "ngmodule", type: AXCollapseModule }, { kind: "component", type: i4$
|
|
20635
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i2$2.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i5$1.AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "ngmodule", type: AXCollapseModule }, { kind: "component", type: i4$2.AXCollapseComponent, selector: "ax-collapse", inputs: ["disabled", "look", "isCollapsed", "showHeader", "caption", "icon", "isLoading", "headerTemplate"], outputs: ["onClick", "isCollapsedChange"] }, { kind: "component", type: i4$2.AXCollapseGroupComponent, selector: "ax-collapse-group", inputs: ["look", "accordion", "activeIndex"], outputs: ["accordionChange", "activeIndexChange"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i5$2.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i7.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "maskPattern", "customTokens", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onMaskChanged"] }, { 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: i3$1.AXDecoratorClearButtonComponent, selector: "ax-clear-button", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
20170
20636
|
}
|
|
20171
20637
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPSelectorStructureWidgetEditComponent, decorators: [{
|
|
20172
20638
|
type: Component,
|
|
@@ -20576,6 +21042,7 @@ const ENTITY_WIDGETS = [
|
|
|
20576
21042
|
AXPLookupWidget,
|
|
20577
21043
|
AXPSelectorStructureWidget,
|
|
20578
21044
|
AXPEntityListWidget,
|
|
21045
|
+
AXPPageComponentWidget,
|
|
20579
21046
|
AXPEntityCategoryWidget,
|
|
20580
21047
|
AXPMultiSourceSelectorWidget,
|
|
20581
21048
|
AXPEntityDefinitionProviderWidget,
|
|
@@ -22669,7 +23136,7 @@ class AXPLayoutAdapterFactory {
|
|
|
22669
23136
|
const title = await dependencies.expressionEvaluator.evaluate(titleTemplate, scope);
|
|
22670
23137
|
return title;
|
|
22671
23138
|
}
|
|
22672
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }, { token: i4$
|
|
23139
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutAdapterFactory, deps: [{ token: AXPRelatedEntityConverterFactory }, { token: AXPMainEntityContentBuilder }, { token: AXPLayoutAdapterBuilder }, { token: i4$3.AXPFilterOperatorMiddlewareService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
22673
23140
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutAdapterFactory, providedIn: 'root' }); }
|
|
22674
23141
|
}
|
|
22675
23142
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLayoutAdapterFactory, decorators: [{
|
|
@@ -22677,7 +23144,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
22677
23144
|
args: [{
|
|
22678
23145
|
providedIn: 'root',
|
|
22679
23146
|
}]
|
|
22680
|
-
}], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$
|
|
23147
|
+
}], ctorParameters: () => [{ type: AXPRelatedEntityConverterFactory }, { type: AXPMainEntityContentBuilder }, { type: AXPLayoutAdapterBuilder }, { type: i4$3.AXPFilterOperatorMiddlewareService }] });
|
|
22681
23148
|
|
|
22682
23149
|
const AXPLayoutDetailsViewRouteResolver = async (route, state, entityResolver = inject(AXPEntityDefinitionRegistryService), expressionEvaluator = inject(AXPExpressionEvaluatorService), session = inject(AXPSessionService), formatService = inject(AXFormatService), workflowService = inject(AXPWorkflowService), commandService = inject(AXPCommandService), layoutAdapterFactory = inject(AXPLayoutAdapterFactory)) => {
|
|
22683
23150
|
const moduleName = route.parent?.paramMap.get('module');
|