@acorex/platform 20.9.35 → 20.9.36

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.
@@ -1,16 +1,16 @@
1
- import { mergeForeignKeyFieldIntoCreateActions, collectNestedCreateHiddenProperties, AXPEntityCommandScope, normalizeEntityDisplayTemplate, sanitizeResolvedEntityDisplayTitle, isUnresolvedEntityDisplayTemplate, AXPEntityDataSourceKeys, isCardFieldBadgeDisplay, resolveCardFieldBadgeColor, isEntityActionPermitted, getEntityInfo, resolveEnabledMasterListLayouts, resolveDefaultMasterListLayout, AXPEntityEventsKeys, collectEntityListSortableFields, collectEntityListFilterDefinitions, parseDottedFieldPath, ENTITY_ROW_POPUP_TITLE_OPTION, resolveLookupWidgetCreateOptions, buildPageListWidgetName, AXPEntityQueryType, buildEntitySearchTitleContext } from '@acorex/platform/layout/entity-contracts';
1
+ import { mergeForeignKeyFieldIntoCreateActions, collectNestedCreateHiddenProperties, AXPEntityCommandScope, normalizeEntityDisplayTemplate, sanitizeResolvedEntityDisplayTitle, isUnresolvedEntityDisplayTemplate, resolveEntityListFilterContextField, resolveEntityListFilterQueryField, AXPEntityDataSourceKeys, isCardFieldBadgeDisplay, resolveCardFieldBadgeColor, isEntityActionPermitted, getEntityInfo, resolveEnabledMasterListLayouts, resolveDefaultMasterListLayout, AXPEntityEventsKeys, collectEntityListSortableFields, collectEntityListFilterDefinitions, parseDottedFieldPath, ENTITY_ROW_POPUP_TITLE_OPTION, resolveLookupWidgetCreateOptions, buildPageListWidgetName, AXPEntityQueryType, buildEntitySearchTitleContext } from '@acorex/platform/layout/entity-contracts';
2
2
  export * from '@acorex/platform/layout/entity-contracts';
3
3
  export { collectNestedCreateHiddenProperties, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, mergeForeignKeyFieldIntoCreateActions } from '@acorex/platform/layout/entity-contracts';
4
4
  import { AXToastService } from '@acorex/components/toast';
5
5
  import * as i3$1 from '@acorex/core/translation';
6
6
  import { AXTranslationService, resolveMultiLanguageString, AXTranslationModule, translateSync } from '@acorex/core/translation';
7
7
  import * as i4$2 from '@acorex/platform/common';
8
- import { AXPNotFoundError, axpNavigateAppPath, AXPSettingsService, AXPCommonSettings, resolveEntityCreateListBehavior, AXPRefreshEvent, resolveEntityModifyPopupTitle, resolveSearchableText, evaluateEntityDisplayTemplate, AXPFilterOperatorMiddlewareService, AXPReloadEvent, axpRedirectToNotFound, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, AXPCleanNestedFilters, AXPFileTypeProviderService, AXPFileStorageService, resolveEntityRowDisplayTitle, AXPFileActionsService, axpIsEntityRecordNotFound, coerceAXPSettingRawValueByKind, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPWorkflowNavigateAction, axpIsEntityListPath, axpIsEntityDetailsPath, axpParseEntityListRoute, axpParseEntityDetailsRoute, axpSaveEntityListReturnUrl, AXP_NOT_FOUND_ROUTE, AXP_PROTECTED_ROUTE_GUARDS, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
8
+ import { AXPNotFoundError, axpNavigateAppPath, AXPSettingsService, AXPCommonSettings, resolveEntityCreateListBehavior, AXPRefreshEvent, resolveEntityModifyPopupTitle, resolveSearchableText, evaluateEntityDisplayTemplate, AXPFilterOperatorMiddlewareService, AXPReloadEvent, axpRedirectToNotFound, AXP_ENTITY_DELETED_WORKFLOW_EVENT_TYPE, CONTAINS_OPER, AXPCleanNestedFilters, AXPFileTypeProviderService, AXPFileStorageService, resolveEntityRowDisplayTitle, AXPFileActionsService, axpIsEntityRecordNotFound, coerceAXPSettingRawValueByKind, AXPDefaultMultiLanguageConfigService, withDefaultMultiLanguageOnWidgetNodeTree, AXPWorkflowNavigateAction, axpIsEntityListPath, axpIsEntityDetailsPath, axpParseEntityListRoute, axpParseEntityDetailsRoute, axpSaveEntityListReturnUrl, AXP_NOT_FOUND_ROUTE, AXP_PROTECTED_ROUTE_GUARDS, AXPToastAction, AXP_SEARCH_DEFINITION_PROVIDER, AXP_SEARCH_DEFINITION_LAZY_RESOLVER, AXPMenuItemsDataSourceDefinition } from '@acorex/platform/common';
9
9
  import * as i1$3 from '@acorex/platform/workflow';
10
10
  import { AXPWorkflowEventService, AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowModule } from '@acorex/platform/workflow';
11
11
  import * as i0 from '@angular/core';
12
12
  import { InjectionToken, inject, Injector, runInInjectionContext, Injectable, ChangeDetectorRef, input, signal, computed, effect, ChangeDetectionStrategy, Component, ElementRef, NgModule, viewChild, Input, afterNextRender, untracked, ViewEncapsulation, viewChildren, linkedSignal, HostBinding, output, EnvironmentInjector, DestroyRef, makeEnvironmentProviders } from '@angular/core';
13
- import { cloneDeep, merge, get, castArray, set, orderBy, defaultTo, isNil, isEmpty, isEqual, isObjectLike, isArray, has, isString, isPlainObject } from 'lodash-es';
13
+ import { cloneDeep, merge, get, isString, isPlainObject, castArray, set, orderBy, defaultTo, isNil, isEmpty, isEqual, isObjectLike, isArray, has } from 'lodash-es';
14
14
  import { Subject, filter, takeUntil } from 'rxjs';
15
15
  import { AXPWidgetsCatalog, resolveActionLook, AXPPlatformScope, extractValue, setSmart, getChangedPaths, isSelectionValueEqual, AXPDataGenerator, AXPSystemActionType } from '@acorex/platform/contracts';
16
16
  import { AXPLayoutBuilderService, LayoutBuilderModule } from '@acorex/platform/layout/builder';
@@ -3955,6 +3955,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3955
3955
  args: [{ providedIn: 'root' }]
3956
3956
  }] });
3957
3957
 
3958
+ //#region ---- Filter operator helpers ----
3959
+ const PRELOAD_FILTER_OPERATOR_TYPES = new Set([
3960
+ 'endsWith',
3961
+ 'startsWith',
3962
+ 'in',
3963
+ 'equal',
3964
+ 'isNull',
3965
+ 'isEmpty',
3966
+ 'lt',
3967
+ 'lte',
3968
+ 'gt',
3969
+ 'gte',
3970
+ 'contains',
3971
+ ]);
3972
+ function coercePreloadFilterOperator(type) {
3973
+ if (!isString(type) || !PRELOAD_FILTER_OPERATOR_TYPES.has(type)) {
3974
+ return undefined;
3975
+ }
3976
+ return { type: type };
3977
+ }
3978
+ //#endregion
3958
3979
  class AXPEntityPreloadFiltersContainerComponent extends AXPPageLayoutBaseComponent {
3959
3980
  constructor() {
3960
3981
  super(...arguments);
@@ -4062,18 +4083,55 @@ class AXPEntityPreloadFiltersContainerComponent extends AXPPageLayoutBaseCompone
4062
4083
  const filters = [];
4063
4084
  const filterDefs = this.preloadFiltersDef();
4064
4085
  for (const filterDef of filterDefs) {
4065
- const fieldName = filterDef.field;
4066
- const value = fieldName ? context[fieldName] : undefined;
4067
- if (value !== undefined && value !== null && value !== '') {
4068
- filters.push({
4069
- field: fieldName,
4070
- operator: { type: 'equal' },
4071
- value,
4072
- });
4086
+ const contextField = resolveEntityListFilterContextField(filterDef);
4087
+ if (!contextField) {
4088
+ continue;
4073
4089
  }
4090
+ const raw = context[contextField];
4091
+ if (raw === undefined || raw === null || raw === '') {
4092
+ continue;
4093
+ }
4094
+ const entry = this.unwrapFilterWidgetEntry(raw);
4095
+ if (entry.value === undefined || entry.value === null || entry.value === '') {
4096
+ continue;
4097
+ }
4098
+ const operator = entry.operator ??
4099
+ coercePreloadFilterOperator(filterDef.operator?.type) ??
4100
+ { type: 'equal' };
4101
+ const field = resolveEntityListFilterQueryField(filterDef, operator);
4102
+ if (!field) {
4103
+ continue;
4104
+ }
4105
+ const filterQuery = {
4106
+ field,
4107
+ operator,
4108
+ value: entry.value,
4109
+ };
4110
+ if (isString(entry.displayText)) {
4111
+ filterQuery.displayText = entry.displayText;
4112
+ }
4113
+ filters.push(filterQuery);
4074
4114
  }
4075
4115
  return filters;
4076
4116
  }
4117
+ /**
4118
+ * Filter widgets store `{ value, operation, displayText? }`; plain values are treated as equal filters.
4119
+ */
4120
+ unwrapFilterWidgetEntry(raw) {
4121
+ if (!isPlainObject(raw)) {
4122
+ return { value: raw };
4123
+ }
4124
+ const entry = raw;
4125
+ const hasFilterShape = 'value' in entry || 'operation' in entry;
4126
+ if (!hasFilterShape) {
4127
+ return { value: raw };
4128
+ }
4129
+ return {
4130
+ value: entry.value,
4131
+ operator: coercePreloadFilterOperator(entry.operation?.type),
4132
+ displayText: isString(entry.displayText) ? entry.displayText : undefined,
4133
+ };
4134
+ }
4077
4135
  buildListQueryFilter(filterQueries) {
4078
4136
  return this.filterOperatorMiddleware.transformFilter({
4079
4137
  field: null,
@@ -6953,10 +7011,9 @@ const AXPEntityListViewModelResolver = async (route, state, service = inject(AXP
6953
7011
  const entityName = route.paramMap.get('entity');
6954
7012
  try {
6955
7013
  const vm = await service.create(moduleName, entityName);
6956
- // URL `filters` are for one-off deep links only; persisted list state loads from user settings.
7014
+ // URL `filters` (preload / deep link) always win over persisted list filters when present.
6957
7015
  const filtersParam = route.queryParamMap.get('filters');
6958
- const shouldLoadPersisted = await vm.shouldLoadPersistedListState();
6959
- if (filtersParam && !shouldLoadPersisted) {
7016
+ if (filtersParam) {
6960
7017
  const applied = vm.applyFiltersFromQueryParams(filtersParam);
6961
7018
  if (applied) {
6962
7019
  await vm.applyFilterAndSort();
@@ -7725,10 +7782,22 @@ class AXPEntityPreloadFiltersViewModel {
7725
7782
  return this.entityDef.interfaces?.master?.list?.description ?? null;
7726
7783
  }, ...(ngDevMode ? [{ debugName: "description" }] : /* istanbul ignore next */ []));
7727
7784
  /**
7728
- * All filter definitions for properties with preload enabled
7785
+ * Preload filter definitions with a single `contains` operator (hides the filter operations menu).
7729
7786
  */
7730
7787
  this.preloadFiltersDef = computed(() => {
7731
- return this.filterDefinitions().filter((definition) => definition.filterType.preload?.enabled);
7788
+ return this.filterDefinitions()
7789
+ .filter((definition) => definition.filterType.preload?.enabled)
7790
+ .map((definition) => ({
7791
+ ...definition,
7792
+ operator: { type: 'contains' },
7793
+ widget: {
7794
+ ...definition.widget,
7795
+ options: {
7796
+ ...definition.widget?.options,
7797
+ operations: [CONTAINS_OPER],
7798
+ },
7799
+ },
7800
+ }));
7732
7801
  }, ...(ngDevMode ? [{ debugName: "preloadFiltersDef" }] : /* istanbul ignore next */ []));
7733
7802
  /**
7734
7803
  * Required filter definitions only