@praxisui/table 10.0.0-rc.31 → 10.0.0-rc.32
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/ai/component-registry.json +2 -2
- package/fesm2022/{praxisui-table-praxisui-table-CPAjJGGd.mjs → praxisui-table-praxisui-table-CWOg6JDN.mjs} +241 -35
- package/fesm2022/{praxisui-table-table-agentic-authoring-turn-flow-CITekGF7.mjs → praxisui-table-table-agentic-authoring-turn-flow-EvaZNCNd.mjs} +1 -1
- package/fesm2022/{praxisui-table-table-ai.adapter-CBRNHKvA.mjs → praxisui-table-table-ai.adapter-DqlbvUHe.mjs} +1 -1
- package/fesm2022/praxisui-table.mjs +1 -1
- package/package.json +10 -10
- package/types/praxisui-table.d.ts +19 -6
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-17T14:44:09.509Z",
|
|
4
4
|
"packageName": "@praxisui/table",
|
|
5
|
-
"packageVersion": "10.0.0-rc.
|
|
5
|
+
"packageVersion": "10.0.0-rc.32",
|
|
6
6
|
"sourceRegistry": "praxis-component-registry-ingestion",
|
|
7
7
|
"sourceRegistryVersion": "1.0.0",
|
|
8
8
|
"componentCount": 3,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { input, inject, computed, ChangeDetectionStrategy, Component, output, signal, InjectionToken, EventEmitter, ElementRef, Output, Input, ViewChild, Optional, Inject, LOCALE_ID, Injectable, Injector, HostListener, Directive, ChangeDetectorRef, DestroyRef, ENVIRONMENT_INITIALIZER, effect, booleanAttribute, HostBinding, ContentChild, TemplateRef, ViewContainerRef, numberAttribute } from '@angular/core';
|
|
3
3
|
import * as i1 from '@praxisui/core';
|
|
4
|
-
import { PraxisI18nService, BulkOperationClientService, isBulkExecutionTerminal, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, PraxisJsonLogicService, resolveResourceAvailabilityReasonKey, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, PraxisIconDirective, PraxisIconButtonComponent, SafeExpressionEvaluator, API_URL, EnterpriseRuntimeContextService, buildApiUrl, ResourceDiscoveryService, renderPraxisPresentationVisualizationHtml, createDefaultTableConfig,
|
|
4
|
+
import { PraxisI18nService, BulkOperationClientService, isBulkExecutionTerminal, LoggerService, createCorporateLoggerConfig, ConsoleLoggerSink, PraxisJsonLogicService, resolveResourceAvailabilityReasonKey, RESOURCE_DISCOVERY_I18N_CONFIG, RESOURCE_DISCOVERY_I18N_NAMESPACE, PraxisIconDirective, PraxisIconButtonComponent, SafeExpressionEvaluator, API_URL, EnterpriseRuntimeContextService, buildApiUrl, ResourceDiscoveryService, renderPraxisPresentationVisualizationHtml, createDefaultTableConfig, deepMerge as deepMerge$1, ASYNC_CONFIG_STORAGE, providePraxisI18nConfig, INLINE_FILTER_CONTROL_TYPES, INLINE_FILTER_CONTROL_TYPE_VALUES, FieldControlType, normalizeControlTypeToken, resolveControlTypeAlias, INLINE_FILTER_ALIAS_TOKENS, SCHEMA_METADATA_CLIENT_OPTIONS, GlobalConfigService, buildSchemaId, MemoryCacheAdapter, LocalStorageCacheAdapter, SchemaMetadataClient, mapFieldDefinitionsToMetadata, resolveInlineFilterControlType, fetchWithETag, serializeEntityLookupValueForPayload, GenericCrudService, SchemaNormalizerService, ResourceQuickConnectComponent, ComponentMetadataRegistry, AnalyticsStatsRequestBuilderService, normalizePraxisDataQueryContext, normalizeUnknownError, PraxisRuntimeComponentObservationRegistryService, PRAXIS_TABLE_DETAIL_INLINE_RENDERERS, BulkSyncStateService, PRAXIS_TABLE_DETAIL_INLINE_NODE_RESOLVERS, PRAXIS_TABLE_DETAIL_RESOURCE_RESOLVER, PraxisWidgetEventBus, PraxisCollectionExportService, fillUndefined, translateResourceAvailabilityReason, ResourceSurfaceOpenAdapterService, ResourceActionOpenAdapterService, CrudOperationResolutionService, SURFACE_OPEN_PRESETS, SURFACE_DRAWER_REF, assertPraxisCollectionExportArtifact, PRAXIS_LOADING_CTX, resolveColumnTypeFromFieldDefinition as resolveColumnTypeFromFieldDefinition$1, isPraxisPresentationVisualizationTableSafe as isPraxisPresentationVisualizationTableSafe$1, resolveTextMaskFormatFromFieldDefinition as resolveTextMaskFormatFromFieldDefinition$1, translateResourceDiscoveryText, supportsImplicitValuePresentation, resolveValuePresentation, resolvePraxisMicroVisualizationTone, resolveResourceIdentityContract, materializeResourceIdentity, translateUnavailableWorkflowMessage, CONNECTION_STORAGE, PRAXIS_LOADING_RENDERER, EmptyStateCardComponent, getPraxisTableCellVisualizationGuidance, getPraxisTableCellVisualizationConstraint, isTableConfigV2, normalizePraxisPresentationVisualization, PRAXIS_GLOBAL_ACTION_CATALOG, SURFACE_OPEN_I18N_NAMESPACE, isRequiredGlobalActionPayloadMissing, getGlobalActionUiSchema, getRequiredGlobalActionPayloadKeys, hasMeaningfulGlobalActionPayloadValue, SurfaceOpenActionEditorComponent, SURFACE_OPEN_I18N_CONFIG, PraxisJsonLogicError, GLOBAL_ACTION_CATALOG, validateGlobalActionRefs, getGlobalActionCatalog, TableConfigService } from '@praxisui/core';
|
|
5
5
|
import * as i1$3 from '@angular/common/http';
|
|
6
6
|
import { HttpErrorResponse, HttpClient, HttpContext } from '@angular/common/http';
|
|
7
7
|
import * as i3 from '@angular/material/button';
|
|
@@ -7649,6 +7649,7 @@ class TableDefaultsProvider {
|
|
|
7649
7649
|
}
|
|
7650
7650
|
/**
|
|
7651
7651
|
* Returns default configuration for a given table identifier.
|
|
7652
|
+
* Precedence inside defaults: GlobalConfig.table > createDefaultTableConfig().
|
|
7652
7653
|
* @param tableId Table identifier
|
|
7653
7654
|
*/
|
|
7654
7655
|
getDefaults(_tableId) {
|
|
@@ -7664,11 +7665,17 @@ class TableDefaultsProvider {
|
|
|
7664
7665
|
const g = this.global.getTable();
|
|
7665
7666
|
if (!g)
|
|
7666
7667
|
return base;
|
|
7667
|
-
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
|
|
7671
|
-
merged.
|
|
7668
|
+
const merged = deepMerge$1(base, g);
|
|
7669
|
+
if (g.filteringUi) {
|
|
7670
|
+
merged.behavior = merged.behavior || {};
|
|
7671
|
+
merged.behavior.filtering = merged.behavior.filtering || {};
|
|
7672
|
+
merged.behavior.filtering.advancedFilters =
|
|
7673
|
+
merged.behavior.filtering.advancedFilters || { enabled: false };
|
|
7674
|
+
const currentSettings = (merged.behavior.filtering.advancedFilters.settings || {});
|
|
7675
|
+
merged.behavior.filtering.advancedFilters.settings = {
|
|
7676
|
+
...g.filteringUi,
|
|
7677
|
+
...currentSettings,
|
|
7678
|
+
};
|
|
7672
7679
|
}
|
|
7673
7680
|
return merged;
|
|
7674
7681
|
}
|
|
@@ -21041,7 +21048,10 @@ class PraxisTable {
|
|
|
21041
21048
|
'audit-warning': 'audit-review',
|
|
21042
21049
|
'sync-warning': 'sync-pending',
|
|
21043
21050
|
};
|
|
21044
|
-
|
|
21051
|
+
static ngAcceptInputType_config;
|
|
21052
|
+
config = { columns: [] };
|
|
21053
|
+
hostInputConfig;
|
|
21054
|
+
persistedUserConfig;
|
|
21045
21055
|
resourcePath;
|
|
21046
21056
|
data = null;
|
|
21047
21057
|
tableId;
|
|
@@ -21056,11 +21066,29 @@ class PraxisTable {
|
|
|
21056
21066
|
autoOpenSettingsOnOutdated = false;
|
|
21057
21067
|
crudContext;
|
|
21058
21068
|
filterCriteria = {};
|
|
21059
|
-
|
|
21069
|
+
filterCriteriaChange = new EventEmitter();
|
|
21070
|
+
_filterTeleport = false;
|
|
21071
|
+
set filterTeleport(value) {
|
|
21072
|
+
if (this._filterTeleport === value)
|
|
21073
|
+
return;
|
|
21074
|
+
this._filterTeleport = value;
|
|
21075
|
+
this.setShowToolbar(this.shouldExposeToolbar(), true);
|
|
21076
|
+
}
|
|
21077
|
+
get filterTeleport() {
|
|
21078
|
+
return this._filterTeleport;
|
|
21079
|
+
}
|
|
21060
21080
|
widgetId;
|
|
21061
|
-
|
|
21081
|
+
filterTemplateSignal = signal(undefined, ...(ngDevMode ? [{ debugName: "filterTemplateSignal" }] : /* istanbul ignore next */ []));
|
|
21082
|
+
_filterBarTemplate;
|
|
21083
|
+
set filterBarTemplate(tpl) {
|
|
21084
|
+
this._filterBarTemplate = tpl;
|
|
21085
|
+
this.filterTemplateSignal.set(tpl);
|
|
21086
|
+
}
|
|
21087
|
+
get filterBarTemplate() {
|
|
21088
|
+
return this._filterBarTemplate;
|
|
21089
|
+
}
|
|
21062
21090
|
get filterTemplate() {
|
|
21063
|
-
return this.
|
|
21091
|
+
return this.filterTemplateSignal();
|
|
21064
21092
|
}
|
|
21065
21093
|
widgetEventBus = inject(PraxisWidgetEventBus, { optional: true });
|
|
21066
21094
|
queryContext = null;
|
|
@@ -23062,6 +23090,40 @@ class PraxisTable {
|
|
|
23062
23090
|
}
|
|
23063
23091
|
catch { }
|
|
23064
23092
|
}
|
|
23093
|
+
recomposeEffectiveTableConfig() {
|
|
23094
|
+
const existingColumns = Array.isArray(this.config?.columns)
|
|
23095
|
+
? [...this.config.columns]
|
|
23096
|
+
: [];
|
|
23097
|
+
const baseInput = this.hostInputConfig
|
|
23098
|
+
? this.clonePlainObject(this.hostInputConfig)
|
|
23099
|
+
: { columns: [] };
|
|
23100
|
+
if (this.persistedUserConfig) {
|
|
23101
|
+
const storedClone = this.clonePlainObject(this.persistedUserConfig);
|
|
23102
|
+
this.config = this.mergePersistedTableConfigWithInput(storedClone, baseInput);
|
|
23103
|
+
}
|
|
23104
|
+
else {
|
|
23105
|
+
this.config = baseInput;
|
|
23106
|
+
}
|
|
23107
|
+
const globalTable = this.global?.getTable?.();
|
|
23108
|
+
this.hostDeclaredAppearanceDensity =
|
|
23109
|
+
this.hasDeclaredAppearanceDensity(this.persistedUserConfig) ||
|
|
23110
|
+
this.hasDeclaredAppearanceDensity(this.hostInputConfig) ||
|
|
23111
|
+
this.hasDeclaredAppearanceDensity(globalTable);
|
|
23112
|
+
this.hostDeclaredAppearanceSpacing =
|
|
23113
|
+
this.hasDeclaredAppearanceSection(this.persistedUserConfig, 'spacing') ||
|
|
23114
|
+
this.hasDeclaredAppearanceSection(this.hostInputConfig, 'spacing') ||
|
|
23115
|
+
this.hasDeclaredAppearanceSection(globalTable, 'spacing');
|
|
23116
|
+
this.hostDeclaredAppearanceTypography =
|
|
23117
|
+
this.hasDeclaredAppearanceSection(this.persistedUserConfig, 'typography') ||
|
|
23118
|
+
this.hasDeclaredAppearanceSection(this.hostInputConfig, 'typography') ||
|
|
23119
|
+
this.hasDeclaredAppearanceSection(globalTable, 'typography');
|
|
23120
|
+
this.ensureConfigDefaults();
|
|
23121
|
+
if ((!Array.isArray(this.config.columns) || this.config.columns.length === 0) &&
|
|
23122
|
+
existingColumns.length > 0 &&
|
|
23123
|
+
(this.usesSchemaColumnProjection(this.config) || this.isRemoteMode())) {
|
|
23124
|
+
this.config.columns = existingColumns;
|
|
23125
|
+
}
|
|
23126
|
+
}
|
|
23065
23127
|
hasDeclaredAppearanceDensity(config) {
|
|
23066
23128
|
const appearance = config?.appearance;
|
|
23067
23129
|
return !!appearance && Object.prototype.hasOwnProperty.call(appearance, 'density');
|
|
@@ -23307,11 +23369,19 @@ class PraxisTable {
|
|
|
23307
23369
|
return false;
|
|
23308
23370
|
if (config.toolbar?.visible)
|
|
23309
23371
|
return true;
|
|
23372
|
+
if (typeof config.toolbar?.title === 'string' && config.toolbar.title.trim().length > 0)
|
|
23373
|
+
return true;
|
|
23374
|
+
if (typeof config.toolbar?.subtitle === 'string' && config.toolbar.subtitle.trim().length > 0)
|
|
23375
|
+
return true;
|
|
23310
23376
|
if (config.export?.enabled)
|
|
23311
23377
|
return true;
|
|
23312
23378
|
if (config.actions?.bulk?.enabled)
|
|
23313
23379
|
return true;
|
|
23314
|
-
if (this.isAdvancedFiltersEffectivelyEnabled(config))
|
|
23380
|
+
if (!this.filterTeleport && this.isAdvancedFiltersEffectivelyEnabled(config))
|
|
23381
|
+
return true;
|
|
23382
|
+
if (this.getConfiguredQuickFilters().length > 0)
|
|
23383
|
+
return true;
|
|
23384
|
+
if ((this.activeCrossFilters?.length ?? 0) > 0)
|
|
23315
23385
|
return true;
|
|
23316
23386
|
return (config.toolbar?.actions?.length ?? 0) > 0;
|
|
23317
23387
|
}
|
|
@@ -23965,7 +24035,7 @@ class PraxisTable {
|
|
|
23965
24035
|
if (this.aiAdapter || this.aiAdapterLoadStarted)
|
|
23966
24036
|
return;
|
|
23967
24037
|
this.aiAdapterLoadStarted = true;
|
|
23968
|
-
import('./praxisui-table-table-ai.adapter-
|
|
24038
|
+
import('./praxisui-table-table-ai.adapter-DqlbvUHe.mjs')
|
|
23969
24039
|
.then(({ TableAiAdapter }) => {
|
|
23970
24040
|
if (!this.isAiAssistantEnabled()) {
|
|
23971
24041
|
this.aiAssistantOpenAfterAdapterLoad = false;
|
|
@@ -24737,7 +24807,7 @@ class PraxisTable {
|
|
|
24737
24807
|
initializeAiAssistantController() {
|
|
24738
24808
|
if (!this.aiAdapter || this.aiAssistantController)
|
|
24739
24809
|
return;
|
|
24740
|
-
import('./praxisui-table-table-agentic-authoring-turn-flow-
|
|
24810
|
+
import('./praxisui-table-table-agentic-authoring-turn-flow-EvaZNCNd.mjs')
|
|
24741
24811
|
.then(({ TableAgenticAuthoringTurnFlow }) => {
|
|
24742
24812
|
if (this.aiAssistantController || !this.aiAdapter)
|
|
24743
24813
|
return;
|
|
@@ -25607,6 +25677,8 @@ class PraxisTable {
|
|
|
25607
25677
|
};
|
|
25608
25678
|
this.queryContextClear.emit(clearEvent);
|
|
25609
25679
|
this.queryContextChange.emit(this.queryContext);
|
|
25680
|
+
this.filterCriteriaChange.emit({ ...this.getEffectiveEditableFilterCriteria() });
|
|
25681
|
+
this.setShowToolbar(this.shouldExposeToolbar(), true);
|
|
25610
25682
|
// Host-mediated widgetEvent for composition runtime
|
|
25611
25683
|
this.widgetEvent.emit({
|
|
25612
25684
|
ownerWidgetKey: this.componentInstanceId || this.tableId || undefined,
|
|
@@ -25665,6 +25737,8 @@ class PraxisTable {
|
|
|
25665
25737
|
};
|
|
25666
25738
|
this.queryContextClear.emit(clearEvent);
|
|
25667
25739
|
this.queryContextChange.emit(this.queryContext);
|
|
25740
|
+
this.filterCriteriaChange.emit({ ...this.getEffectiveEditableFilterCriteria() });
|
|
25741
|
+
this.setShowToolbar(this.shouldExposeToolbar(), true);
|
|
25668
25742
|
this.widgetEvent.emit({
|
|
25669
25743
|
ownerWidgetKey: this.componentInstanceId || this.tableId || undefined,
|
|
25670
25744
|
sourceComponentId: 'praxis-table',
|
|
@@ -25810,8 +25884,11 @@ class PraxisTable {
|
|
|
25810
25884
|
ref.saved$.subscribe(apply);
|
|
25811
25885
|
}
|
|
25812
25886
|
async ngOnInit() {
|
|
25887
|
+
if (!this.hostInputConfig && this.config) {
|
|
25888
|
+
this.hostInputConfig = this.clonePlainObject(this.config);
|
|
25889
|
+
}
|
|
25813
25890
|
// Ensure config exists before any awaited operations to avoid template errors
|
|
25814
|
-
this.
|
|
25891
|
+
this.recomposeEffectiveTableConfig();
|
|
25815
25892
|
this.enforceUnsupportedFeatureGuards();
|
|
25816
25893
|
this.syncPaginatorIntl();
|
|
25817
25894
|
this.setShowToolbar(this.shouldExposeToolbar(), true);
|
|
@@ -25827,6 +25904,21 @@ class PraxisTable {
|
|
|
25827
25904
|
}
|
|
25828
25905
|
}));
|
|
25829
25906
|
}
|
|
25907
|
+
if (this.global?.configChanges$) {
|
|
25908
|
+
this.subscriptions.push(this.global.configChanges$.subscribe(() => {
|
|
25909
|
+
this.recomposeEffectiveTableConfig();
|
|
25910
|
+
this.enforceUnsupportedFeatureGuards();
|
|
25911
|
+
this.syncPaginatorIntl();
|
|
25912
|
+
this.syncHorizontalScrollFromAppearanceConfig();
|
|
25913
|
+
this.setShowToolbar(this.shouldExposeToolbar(), true);
|
|
25914
|
+
this.applyAppearanceVariables();
|
|
25915
|
+
this.cdr.markForCheck();
|
|
25916
|
+
}));
|
|
25917
|
+
}
|
|
25918
|
+
try {
|
|
25919
|
+
await this.global?.ready?.();
|
|
25920
|
+
}
|
|
25921
|
+
catch { }
|
|
25830
25922
|
// Resolve global fallback for schema prefs
|
|
25831
25923
|
try {
|
|
25832
25924
|
await this.resolveSchemaPrefs();
|
|
@@ -25857,14 +25949,8 @@ class PraxisTable {
|
|
|
25857
25949
|
try {
|
|
25858
25950
|
const storedConfig = await firstValueFrom(this.asyncConfigStorage.loadConfig(cfgKey));
|
|
25859
25951
|
if (storedConfig) {
|
|
25860
|
-
this.
|
|
25861
|
-
|
|
25862
|
-
this.hostDeclaredAppearanceSpacing =
|
|
25863
|
-
this.hostDeclaredAppearanceSpacing || this.hasDeclaredAppearanceSection(storedConfig, 'spacing');
|
|
25864
|
-
this.hostDeclaredAppearanceTypography =
|
|
25865
|
-
this.hostDeclaredAppearanceTypography || this.hasDeclaredAppearanceSection(storedConfig, 'typography');
|
|
25866
|
-
this.config = this.mergePersistedTableConfigWithInput(storedConfig, this.config);
|
|
25867
|
-
this.ensureConfigDefaults();
|
|
25952
|
+
this.persistedUserConfig = this.clonePlainObject(storedConfig);
|
|
25953
|
+
this.recomposeEffectiveTableConfig();
|
|
25868
25954
|
this.enforceUnsupportedFeatureGuards();
|
|
25869
25955
|
this.setupColumns();
|
|
25870
25956
|
this.cdr.markForCheck();
|
|
@@ -25889,8 +25975,8 @@ class PraxisTable {
|
|
|
25889
25975
|
}
|
|
25890
25976
|
}
|
|
25891
25977
|
catch { }
|
|
25892
|
-
//
|
|
25893
|
-
this.
|
|
25978
|
+
// Recompose effective config after GlobalConfig.ready() and persisted user config hydration
|
|
25979
|
+
this.recomposeEffectiveTableConfig();
|
|
25894
25980
|
this.resetDetailRuntimeForConfig();
|
|
25895
25981
|
this.syncPaginatorIntl();
|
|
25896
25982
|
// ngOnInit is async and Angular does not await it before ngAfterContentInit.
|
|
@@ -25914,6 +26000,7 @@ class PraxisTable {
|
|
|
25914
26000
|
resetPageSizeOverride: true,
|
|
25915
26001
|
});
|
|
25916
26002
|
this.applyDataSourceSettings();
|
|
26003
|
+
this.applyAppearanceVariables();
|
|
25917
26004
|
if (this.isAiAssistantEnabled()) {
|
|
25918
26005
|
this.ensureAiAdapterLoaded();
|
|
25919
26006
|
}
|
|
@@ -25944,10 +26031,24 @@ class PraxisTable {
|
|
|
25944
26031
|
this.localPageSizeRuntimeOverride = false;
|
|
25945
26032
|
}
|
|
25946
26033
|
if (changes['config']?.currentValue && this.config) {
|
|
25947
|
-
this.
|
|
25948
|
-
|
|
25949
|
-
this.
|
|
26034
|
+
this.hostInputConfig = this.clonePlainObject(changes['config'].currentValue);
|
|
26035
|
+
const globalTable = this.global?.getTable?.();
|
|
26036
|
+
this.hostDeclaredAppearanceDensity =
|
|
26037
|
+
this.hasDeclaredAppearanceDensity(this.persistedUserConfig) ||
|
|
26038
|
+
this.hasDeclaredAppearanceDensity(changes['config'].currentValue) ||
|
|
26039
|
+
this.hasDeclaredAppearanceDensity(globalTable);
|
|
26040
|
+
this.hostDeclaredAppearanceSpacing =
|
|
26041
|
+
this.hasDeclaredAppearanceSection(this.persistedUserConfig, 'spacing') ||
|
|
26042
|
+
this.hasDeclaredAppearanceSection(changes['config'].currentValue, 'spacing') ||
|
|
26043
|
+
this.hasDeclaredAppearanceSection(globalTable, 'spacing');
|
|
26044
|
+
this.hostDeclaredAppearanceTypography =
|
|
26045
|
+
this.hasDeclaredAppearanceSection(this.persistedUserConfig, 'typography') ||
|
|
26046
|
+
this.hasDeclaredAppearanceSection(changes['config'].currentValue, 'typography') ||
|
|
26047
|
+
this.hasDeclaredAppearanceSection(globalTable, 'typography');
|
|
25950
26048
|
this.config = this.reconcileTableConfigInputChange(changes['config'].previousValue, changes['config'].currentValue);
|
|
26049
|
+
if (this.persistedUserConfig) {
|
|
26050
|
+
this.persistedUserConfig = this.clonePlainObject(this.config);
|
|
26051
|
+
}
|
|
25951
26052
|
}
|
|
25952
26053
|
this.ensureConfigDefaults();
|
|
25953
26054
|
this.enforceUnsupportedFeatureGuards();
|
|
@@ -26087,6 +26188,16 @@ class PraxisTable {
|
|
|
26087
26188
|
shouldFetchRemoteDataForQueryChanges(changes) {
|
|
26088
26189
|
if (!this.isRemoteMode())
|
|
26089
26190
|
return false;
|
|
26191
|
+
if (changes['filterCriteria'] &&
|
|
26192
|
+
!changes['queryContext'] &&
|
|
26193
|
+
this.lastAppliedFilterCriteria !== null) {
|
|
26194
|
+
const incoming = normalizePraxisFilterCriteriaRecord(changes['filterCriteria'].currentValue);
|
|
26195
|
+
const prevApplied = this.lastAppliedFilterCriteria;
|
|
26196
|
+
this.lastAppliedFilterCriteria = null;
|
|
26197
|
+
if (this.hasEquivalentFilterCriteria(incoming, prevApplied)) {
|
|
26198
|
+
return false;
|
|
26199
|
+
}
|
|
26200
|
+
}
|
|
26090
26201
|
if (this.hasInitialized)
|
|
26091
26202
|
return true;
|
|
26092
26203
|
const queryChanges = [changes['filterCriteria'], changes['queryContext']];
|
|
@@ -28368,8 +28479,13 @@ class PraxisTable {
|
|
|
28368
28479
|
return false;
|
|
28369
28480
|
if (visibleFieldNames.has(name))
|
|
28370
28481
|
return false;
|
|
28371
|
-
if (name.startsWith('_')
|
|
28482
|
+
if (name.startsWith('_')
|
|
28483
|
+
|| name === 'id'
|
|
28484
|
+
|| name === '__v'
|
|
28485
|
+
|| name === 'version'
|
|
28486
|
+
|| name === 'resourceVersion') {
|
|
28372
28487
|
return false;
|
|
28488
|
+
}
|
|
28373
28489
|
if (this.isSensitiveAiAssistantField(name))
|
|
28374
28490
|
return false;
|
|
28375
28491
|
return true;
|
|
@@ -32295,6 +32411,7 @@ class PraxisTable {
|
|
|
32295
32411
|
this.clearQuickFilterRuntimeState();
|
|
32296
32412
|
this.applyAdvancedFilterCriteria(editableCriteria, 'advanced-filter-submit');
|
|
32297
32413
|
this.syncQuickFilterStateFromEffectiveCriteria();
|
|
32414
|
+
this.filterCriteriaChange.emit({ ...this.filterCriteria });
|
|
32298
32415
|
if (this.widgetEventBus) {
|
|
32299
32416
|
this.widgetEventBus.publish({
|
|
32300
32417
|
sourceWidgetId: this.widgetId || this.tableId,
|
|
@@ -32311,6 +32428,7 @@ class PraxisTable {
|
|
|
32311
32428
|
this.clearQuickFilterRuntimeState();
|
|
32312
32429
|
this.applyAdvancedFilterCriteria({}, 'advanced-filter-clear');
|
|
32313
32430
|
this.syncQuickFilterStateFromEffectiveCriteria();
|
|
32431
|
+
this.filterCriteriaChange.emit({});
|
|
32314
32432
|
if (this.widgetEventBus) {
|
|
32315
32433
|
this.widgetEventBus.publish({
|
|
32316
32434
|
sourceWidgetId: this.widgetId || this.tableId,
|
|
@@ -32342,6 +32460,7 @@ class PraxisTable {
|
|
|
32342
32460
|
this.activeQuickFilterId = id;
|
|
32343
32461
|
this.activeQuickFilterCriteria = {};
|
|
32344
32462
|
this.applyAdvancedFilterCriteria({}, 'quick-filter-apply');
|
|
32463
|
+
this.filterCriteriaChange.emit({});
|
|
32345
32464
|
return;
|
|
32346
32465
|
}
|
|
32347
32466
|
const current = normalizePraxisFilterCriteriaRecord(this.filterCriteria);
|
|
@@ -32359,12 +32478,14 @@ class PraxisTable {
|
|
|
32359
32478
|
this.clearQuickFilterRuntimeState();
|
|
32360
32479
|
this.applyAdvancedFilterCriteria(cleanedBase, 'quick-filter-clear');
|
|
32361
32480
|
this.syncQuickFilterStateFromEffectiveCriteria();
|
|
32481
|
+
this.filterCriteriaChange.emit({ ...this.filterCriteria });
|
|
32362
32482
|
return;
|
|
32363
32483
|
}
|
|
32364
32484
|
this.quickFilterBaseCriteria = cleanedBase;
|
|
32365
32485
|
this.activeQuickFilterId = id;
|
|
32366
32486
|
this.activeQuickFilterCriteria = { ...cleanedBase, ...patch };
|
|
32367
32487
|
this.applyAdvancedFilterCriteria(this.activeQuickFilterCriteria, 'quick-filter-apply');
|
|
32488
|
+
this.filterCriteriaChange.emit({ ...this.filterCriteria });
|
|
32368
32489
|
}
|
|
32369
32490
|
getConfiguredQuickFilters() {
|
|
32370
32491
|
const filters = this.config?.toolbar?.filters;
|
|
@@ -32507,6 +32628,7 @@ class PraxisTable {
|
|
|
32507
32628
|
};
|
|
32508
32629
|
this.queryContextClear?.emit(clearEvent);
|
|
32509
32630
|
this.queryContextChange?.emit(this.queryContext);
|
|
32631
|
+
this.filterCriteriaChange.emit({ ...this.getEffectiveEditableFilterCriteria() });
|
|
32510
32632
|
this.widgetEvent?.emit({
|
|
32511
32633
|
ownerWidgetKey: this.componentInstanceId || this.tableId || undefined,
|
|
32512
32634
|
sourceComponentId: 'praxis-table',
|
|
@@ -32562,8 +32684,15 @@ class PraxisTable {
|
|
|
32562
32684
|
}
|
|
32563
32685
|
hasEquivalentFilterCriteria(left, right) {
|
|
32564
32686
|
const canonicalize = (value) => {
|
|
32565
|
-
if (Array.isArray(value))
|
|
32566
|
-
|
|
32687
|
+
if (Array.isArray(value)) {
|
|
32688
|
+
const items = value.map(canonicalize);
|
|
32689
|
+
if (items.length === 2 &&
|
|
32690
|
+
typeof items[0] === 'number' &&
|
|
32691
|
+
typeof items[1] === 'number') {
|
|
32692
|
+
return { end: items[1], start: items[0] };
|
|
32693
|
+
}
|
|
32694
|
+
return items;
|
|
32695
|
+
}
|
|
32567
32696
|
if (!value || typeof value !== 'object')
|
|
32568
32697
|
return value;
|
|
32569
32698
|
return Object.keys(value)
|
|
@@ -32575,8 +32704,10 @@ class PraxisTable {
|
|
|
32575
32704
|
};
|
|
32576
32705
|
return JSON.stringify(canonicalize(left)) === JSON.stringify(canonicalize(right));
|
|
32577
32706
|
}
|
|
32707
|
+
lastAppliedFilterCriteria = null;
|
|
32578
32708
|
applyAdvancedFilterCriteria(criteria, reason = 'external-api') {
|
|
32579
32709
|
this.setAdvancedFilterCriteria(criteria);
|
|
32710
|
+
this.lastAppliedFilterCriteria = { ...this.filterCriteria };
|
|
32580
32711
|
this.applyExpansionCollapsePolicy('filterChange');
|
|
32581
32712
|
this.clearCellAnimationChangeState();
|
|
32582
32713
|
this.pageIndex = 0;
|
|
@@ -33062,6 +33193,7 @@ class PraxisTable {
|
|
|
33062
33193
|
const compactConfig = this.toPortableTableConfig(plan.canonicalConfig);
|
|
33063
33194
|
const cfg = this.attachRuntimeMetadataToEditorConfig(compactConfig, plan.metadata?.attachServerMeta === true && !shouldReloadSchema, plan.persistence?.saveConfig === true);
|
|
33064
33195
|
if (plan.persistence?.saveConfig) {
|
|
33196
|
+
this.persistedUserConfig = this.clonePlainObject(cfg);
|
|
33065
33197
|
const cfgKey = this.tableConfigKey();
|
|
33066
33198
|
if (cfgKey) {
|
|
33067
33199
|
this.saveConfigWithAck(cfgKey, cfg, 'table-settings-save', {
|
|
@@ -33230,8 +33362,27 @@ class PraxisTable {
|
|
|
33230
33362
|
onResetPersistenceSettled(false, 'reset-filter-config');
|
|
33231
33363
|
});
|
|
33232
33364
|
}
|
|
33365
|
+
this.persistedUserConfig = undefined;
|
|
33233
33366
|
const defaults = this.tableDefaultsProvider.getDefaults(this.tableId);
|
|
33234
|
-
this.
|
|
33367
|
+
const restoredConfig = this.hostInputConfig
|
|
33368
|
+
? fillUndefined(this.clonePlainObject(this.hostInputConfig), defaults)
|
|
33369
|
+
: defaults;
|
|
33370
|
+
if ((!Array.isArray(restoredConfig.columns) || restoredConfig.columns.length === 0) &&
|
|
33371
|
+
this.schemaColumnFieldsSnapshot.length > 0 &&
|
|
33372
|
+
(this.usesSchemaColumnProjection(restoredConfig) || this.isRemoteMode())) {
|
|
33373
|
+
restoredConfig.columns = this.projectSchemaColumns(this.schemaColumnFieldsSnapshot, restoredConfig.columnProjection);
|
|
33374
|
+
}
|
|
33375
|
+
const globalTable = this.global?.getTable?.();
|
|
33376
|
+
this.hostDeclaredAppearanceDensity =
|
|
33377
|
+
this.hasDeclaredAppearanceDensity(this.hostInputConfig) ||
|
|
33378
|
+
this.hasDeclaredAppearanceDensity(globalTable);
|
|
33379
|
+
this.hostDeclaredAppearanceSpacing =
|
|
33380
|
+
this.hasDeclaredAppearanceSection(this.hostInputConfig, 'spacing') ||
|
|
33381
|
+
this.hasDeclaredAppearanceSection(globalTable, 'spacing');
|
|
33382
|
+
this.hostDeclaredAppearanceTypography =
|
|
33383
|
+
this.hasDeclaredAppearanceSection(this.hostInputConfig, 'typography') ||
|
|
33384
|
+
this.hasDeclaredAppearanceSection(globalTable, 'typography');
|
|
33385
|
+
this.applyTableConfig(restoredConfig);
|
|
33235
33386
|
if (operationCount === 0) {
|
|
33236
33387
|
this.showResetSuccessFeedback(successTrigger);
|
|
33237
33388
|
}
|
|
@@ -34805,6 +34956,7 @@ class PraxisTable {
|
|
|
34805
34956
|
.subscribe({
|
|
34806
34957
|
next: () => {
|
|
34807
34958
|
acknowledged = true;
|
|
34959
|
+
this.persistedUserConfig = this.clonePlainObject(payload);
|
|
34808
34960
|
if (applyReconciledConfigOnSuccess) {
|
|
34809
34961
|
this.config = payload;
|
|
34810
34962
|
this.runColumnResizeLayoutMutation(() => this.setupColumns());
|
|
@@ -35104,7 +35256,11 @@ class PraxisTable {
|
|
|
35104
35256
|
this.config?.toolbar?.filters?.enabled !== false &&
|
|
35105
35257
|
(!this.config?.toolbar?.filters?.quickFilters || this.config.toolbar.filters.quickFilters.length === 0)) {
|
|
35106
35258
|
const toolbar = this.ensureToolbarConfigForRuntime();
|
|
35107
|
-
|
|
35259
|
+
const globalShowAdvanced = this.global?.getTable?.()?.toolbar?.filters?.showAdvancedButton;
|
|
35260
|
+
toolbar.filters = toolbar.filters || {
|
|
35261
|
+
enabled: true,
|
|
35262
|
+
showAdvancedButton: typeof globalShowAdvanced === 'boolean' ? globalShowAdvanced : true,
|
|
35263
|
+
};
|
|
35108
35264
|
toolbar.filters.quickFilters = [...discoveredQuickFilters];
|
|
35109
35265
|
if (toolbar.filters.enabled === undefined) {
|
|
35110
35266
|
toolbar.filters.enabled = true;
|
|
@@ -38306,8 +38462,56 @@ class PraxisTable {
|
|
|
38306
38462
|
}, { dedupeKey: 'praxis-table:expansion:virtualization-fail-closed' });
|
|
38307
38463
|
return false;
|
|
38308
38464
|
}
|
|
38465
|
+
if (!this.hasComplementarySchemaExpansionFields()) {
|
|
38466
|
+
return false;
|
|
38467
|
+
}
|
|
38309
38468
|
return true;
|
|
38310
38469
|
}
|
|
38470
|
+
hasComplementarySchemaExpansionFields() {
|
|
38471
|
+
const rawMode = String(this.getDetailConfig()?.source?.mode
|
|
38472
|
+
|| this.getExpansionConfig()?.source
|
|
38473
|
+
|| this.getExpansionConfig()?.mode
|
|
38474
|
+
|| (this.getExpansionConfig()?.enabled && !this.getDetailConfig()?.source?.inlineSchema ? 'schema' : 'inline')).trim();
|
|
38475
|
+
if (rawMode !== 'schema')
|
|
38476
|
+
return true;
|
|
38477
|
+
if (this.getExpansionFallbackMode() !== 'none')
|
|
38478
|
+
return true;
|
|
38479
|
+
const schemaFields = this.schemaColumnFieldsSnapshot && this.schemaColumnFieldsSnapshot.length > 0
|
|
38480
|
+
? this.schemaColumnFieldsSnapshot
|
|
38481
|
+
: this.schemaFieldsSnapshot && this.schemaFieldsSnapshot.length > 0
|
|
38482
|
+
? this.schemaFieldsSnapshot
|
|
38483
|
+
: null;
|
|
38484
|
+
if (!schemaFields || schemaFields.length === 0)
|
|
38485
|
+
return true;
|
|
38486
|
+
const visibleFieldNames = new Set();
|
|
38487
|
+
const activeColumns = this.visibleColumns && this.visibleColumns.length > 0
|
|
38488
|
+
? this.visibleColumns
|
|
38489
|
+
: (this.config?.columns || []).filter((col) => col && col.visible !== false);
|
|
38490
|
+
for (const col of activeColumns) {
|
|
38491
|
+
if (col?.field)
|
|
38492
|
+
visibleFieldNames.add(col.field);
|
|
38493
|
+
}
|
|
38494
|
+
const idField = this.getIdField();
|
|
38495
|
+
if (idField)
|
|
38496
|
+
visibleFieldNames.add(idField);
|
|
38497
|
+
return schemaFields.some((f) => {
|
|
38498
|
+
const name = String(f?.name || '').trim();
|
|
38499
|
+
if (!name)
|
|
38500
|
+
return false;
|
|
38501
|
+
if (visibleFieldNames.has(name))
|
|
38502
|
+
return false;
|
|
38503
|
+
if (name.startsWith('_')
|
|
38504
|
+
|| name === 'id'
|
|
38505
|
+
|| name === '__v'
|
|
38506
|
+
|| name === 'version'
|
|
38507
|
+
|| name === 'resourceVersion') {
|
|
38508
|
+
return false;
|
|
38509
|
+
}
|
|
38510
|
+
if (this.isSensitiveAiAssistantField(name))
|
|
38511
|
+
return false;
|
|
38512
|
+
return true;
|
|
38513
|
+
});
|
|
38514
|
+
}
|
|
38311
38515
|
enforceAppearanceSchemaGuards() {
|
|
38312
38516
|
const appearance = (this.config?.appearance || {});
|
|
38313
38517
|
if (!appearance || typeof appearance !== 'object')
|
|
@@ -42272,7 +42476,7 @@ class PraxisTable {
|
|
|
42272
42476
|
this.removeViewportChangeListeners = null;
|
|
42273
42477
|
}
|
|
42274
42478
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisTable, deps: [{ token: i0.ChangeDetectorRef }, { token: i3$2.SettingsPanelService }, { token: i1.GenericCrudService }, { token: TableDefaultsProvider }, { token: FilterConfigService }, { token: DataFormattingService }, { token: i6$1.PraxisDialog }, { token: i4$2.MatSnackBar }, { token: ASYNC_CONFIG_STORAGE }, { token: CONNECTION_STORAGE }, { token: i0.ElementRef }, { token: i1.GlobalConfigService }, { token: i0.Injector }, { token: i1.ComponentKeyService }, { token: i1.LoadingOrchestrator }, { token: i1.GlobalActionService }, { token: i1.EnterpriseRuntimeContextService, optional: true }, { token: PRAXIS_LOADING_RENDERER, optional: true }, { token: i8$1.ActivatedRoute, optional: true }, { token: i1.LoggerService, optional: true }, { token: AnalyticsTableStatsApiService, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
42275
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisTable, isStandalone: true, selector: "praxis-table", inputs: { config: "config", resourcePath: "resourcePath", data: "data", tableId: "tableId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", title: "title", subtitle: "subtitle", icon: "icon", autoDelete: "autoDelete", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", crudContext: "crudContext", filterCriteria: "filterCriteria", filterTeleport: ["filterTeleport", "filterTeleport", booleanAttribute], widgetId: "widgetId", queryContext: "queryContext", aiContext: "aiContext", aiAssistantVoiceInputMode: "aiAssistantVoiceInputMode", aiAssistantVoiceLanguage: "aiAssistantVoiceLanguage", horizontalScroll: "horizontalScroll", enableCustomization: ["enableCustomization", "enableCustomization", booleanAttribute], authoringCapability: "authoringCapability", dense: "dense" }, outputs: { queryContextClear: "queryContextClear", queryContextChange: "queryContextChange", rowClick: "rowClick", widgetEvent: "widgetEvent", resourceEvent: "resourceEvent", rowDoubleClick: "rowDoubleClick", rowExpansionChange: "rowExpansionChange", rowAction: "rowAction", toolbarAction: "toolbarAction", bulkAction: "bulkAction", exportAction: "exportAction", columnReorder: "columnReorder", columnReorderAttempt: "columnReorderAttempt", columnResize: "columnResize", beforeDelete: "beforeDelete", afterDelete: "afterDelete", deleteError: "deleteError", beforeBulkDelete: "beforeBulkDelete", afterBulkDelete: "afterBulkDelete", bulkDeleteError: "bulkDeleteError", schemaStatusChange: "schemaStatusChange", configChange: "configChange", metadataChange: "metadataChange", loadingStateChange: "loadingStateChange", collectionLinksChange: "collectionLinksChange", selectionChange: "selectionChange", drawerOpen: "drawerOpen", drawerClose: "drawerClose", drawerTabChange: "drawerTabChange" }, host: { properties: { "class.density-compact": "this.hostDensityCompactClass", "class.density-comfortable": "this.hostDensityComfortableClass", "class.density-spacious": "this.hostDensitySpaciousClass", "class.row-borders": "this.hostRowBordersClass", "class.col-borders": "this.hostColumnBordersClass" } }, providers: [
|
|
42479
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisTable, isStandalone: true, selector: "praxis-table", inputs: { config: "config", resourcePath: "resourcePath", data: "data", tableId: "tableId", componentInstanceId: "componentInstanceId", configPersistenceStrategy: "configPersistenceStrategy", title: "title", subtitle: "subtitle", icon: "icon", autoDelete: "autoDelete", notifyIfOutdated: "notifyIfOutdated", snoozeMs: "snoozeMs", autoOpenSettingsOnOutdated: "autoOpenSettingsOnOutdated", crudContext: "crudContext", filterCriteria: "filterCriteria", filterTeleport: ["filterTeleport", "filterTeleport", booleanAttribute], widgetId: "widgetId", queryContext: "queryContext", aiContext: "aiContext", aiAssistantVoiceInputMode: "aiAssistantVoiceInputMode", aiAssistantVoiceLanguage: "aiAssistantVoiceLanguage", horizontalScroll: "horizontalScroll", enableCustomization: ["enableCustomization", "enableCustomization", booleanAttribute], authoringCapability: "authoringCapability", dense: "dense" }, outputs: { filterCriteriaChange: "filterCriteriaChange", queryContextClear: "queryContextClear", queryContextChange: "queryContextChange", rowClick: "rowClick", widgetEvent: "widgetEvent", resourceEvent: "resourceEvent", rowDoubleClick: "rowDoubleClick", rowExpansionChange: "rowExpansionChange", rowAction: "rowAction", toolbarAction: "toolbarAction", bulkAction: "bulkAction", exportAction: "exportAction", columnReorder: "columnReorder", columnReorderAttempt: "columnReorderAttempt", columnResize: "columnResize", beforeDelete: "beforeDelete", afterDelete: "afterDelete", deleteError: "deleteError", beforeBulkDelete: "beforeBulkDelete", afterBulkDelete: "afterBulkDelete", bulkDeleteError: "bulkDeleteError", schemaStatusChange: "schemaStatusChange", configChange: "configChange", metadataChange: "metadataChange", loadingStateChange: "loadingStateChange", collectionLinksChange: "collectionLinksChange", selectionChange: "selectionChange", drawerOpen: "drawerOpen", drawerClose: "drawerClose", drawerTabChange: "drawerTabChange" }, host: { properties: { "class.density-compact": "this.hostDensityCompactClass", "class.density-comfortable": "this.hostDensityComfortableClass", "class.density-spacious": "this.hostDensitySpaciousClass", "class.row-borders": "this.hostRowBordersClass", "class.col-borders": "this.hostColumnBordersClass" } }, providers: [
|
|
42276
42480
|
providePraxisI18nConfig(RESOURCE_DISCOVERY_I18N_CONFIG),
|
|
42277
42481
|
providePraxisI18nConfig(PRAXIS_TABLE_RUNTIME_I18N_CONFIG),
|
|
42278
42482
|
MatPaginatorIntl,
|
|
@@ -42371,6 +42575,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
42371
42575
|
type: Input
|
|
42372
42576
|
}], filterCriteria: [{
|
|
42373
42577
|
type: Input
|
|
42578
|
+
}], filterCriteriaChange: [{
|
|
42579
|
+
type: Output
|
|
42374
42580
|
}], filterTeleport: [{
|
|
42375
42581
|
type: Input,
|
|
42376
42582
|
args: [{ transform: booleanAttribute }]
|
|
@@ -73685,7 +73891,7 @@ class PraxisTableConfigEditor {
|
|
|
73685
73891
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisTableConfigEditor, isStandalone: true, selector: "praxis-table-config-editor", providers: [
|
|
73686
73892
|
TableConfigService,
|
|
73687
73893
|
providePraxisI18nConfig(PRAXIS_TABLE_EDITOR_I18N_CONFIG),
|
|
73688
|
-
], viewQueries: [{ propertyName: "filterSettingsEditor", first: true, predicate: ["tableFilterSettingsRef"], descendants: true }, { propertyName: "behaviorEditor", first: true, predicate: BehaviorConfigEditorComponent, descendants: true }, { propertyName: "detailEditor", first: true, predicate: TableDetailEditorComponent, descendants: true }, { propertyName: "rulesEditor", first: true, predicate: TableRulesEditorComponent, descendants: true }, { propertyName: "crudEditorSetter", first: true, predicate: ["crudEditorRef"], descendants: true }], ngImport: i0, template: "<div class=\"editor-section-selector\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('sections.selector', 'Editor section') }}</mat-label>\n <mat-select [(ngModel)]=\"activeSectionIndex\" data-testid=\"table-config-editor-sections\">\n @for (section of sections; track section.id; let index = $index) {\n <mat-option [value]=\"index\">{{ section.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" [(selectedIndex)]=\"activeSectionIndex\">\n @for (section of sections; track section.id) {\n <mat-tab>\n <ng-template mat-tab-label>\n @if (section.icon) { <mat-icon [praxisIcon]=\"section.icon\"></mat-icon> }\n <span [attr.data-testid]=\"'config-tab-' + section.id\">{{ section.label }}</span>\n </ng-template>\n <div class=\"tab-content\">\n @switch (section.id) {\n @case ('connect') {\n <div class=\"connect-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.resource', 'Resource') }}</mat-label>\n <input matInput [(ngModel)]=\"resourcePath\" (ngModelChange)=\"onResourcePathChange($event)\" [placeholder]=\"tx('connect.resource.placeholder', 'e.g. employees')\" />\n <mat-icon matSuffix>link</mat-icon>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.primaryKey', 'Primary key') }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"idField\"\n (ngModelChange)=\"onIdFieldChange($event)\"\n [matAutocomplete]=\"idFieldPicker\"\n [placeholder]=\"tx('connect.primaryKey.placeholder', 'e.g. id, uuid, code')\"\n />\n <mat-icon matSuffix>fingerprint</mat-icon>\n <mat-autocomplete\n #idFieldPicker=\"matAutocomplete\"\n (optionSelected)=\"onIdFieldOptionSelected($event.option.value)\"\n >\n @for (option of filteredIdFieldOptions; track option.name) {\n <mat-option [value]=\"option.name\">\n <span>{{ option.name }}</span>\n @if (option.label && option.label !== option.name) {\n <small> - {{ option.label }}</small>\n }\n </mat-option>\n }\n @if (filteredIdFieldOptions.length === 0) {\n <mat-option disabled>\n {{ tx('connect.primaryKey.empty', 'No matching field found.') }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n <p class=\"connect-note\">{{ tx('connect.note', 'Define the API resource and, when needed, the primary key.') }}</p>\n <!-- Diverg\u00EAncia: idField -->\n @if (idFieldDiverges) { <div class=\"alert alert--warning connect-alert\">\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.serverPrimaryKeyDiverges', 'The primary key on the server differs from the current configuration.') }}\n <span class=\"connect-alert__meta\">(config: {{ idField || 'id' }} | servidor: {{ serverIdField || 'id' }})</span>\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onReconcileIdField()\">{{ tx('connect.reconcile', 'Reconcile') }}</button>\n </div> }\n <!-- Diverg\u00EAncia: serverHash -->\n @if (schemaHashDiverges) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotDiverges', 'The saved schema snapshot differs from the current server schema.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.updateMetadata', 'Update metadata') }}</button>\n </div> }\n @if (!schemaHashDiverges && schemaSnapshotMissing) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotMissing', 'A current schema exists on the server, but there is still no persisted snapshot for reconciliation.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.saveSnapshot', 'Save snapshot') }}</button>\n </div> }\n </div>\n }\n @case ('overview') {\n <div class=\"overview-grid\">\n <section class=\"responsive-settings\" aria-labelledby=\"table-responsive-title\">\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">devices</mat-icon>\n <h3 id=\"table-responsive-title\">{{ tx('overview.responsive.title', 'Narrow screens') }}</h3>\n </div>\n <p>{{ tx('overview.responsive.description', 'Choose how records appear when the table has less space.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.mode', 'Record layout') }}</mat-label>\n <mat-select [ngModel]=\"mobileCardMode\" (ngModelChange)=\"onMobileCardModeChange($event)\">\n <mat-option [value]=\"false\">{{ tx('overview.responsive.table', 'Table') }}</mat-option>\n <mat-option [value]=\"true\">{{ tx('overview.responsive.cards', 'Cards') }}</mat-option>\n </mat-select>\n </mat-form-field>\n @if (mobileCardMode) {\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.cardsHint', 'Each record becomes a card with its visible columns. Selection and row actions remain available. Wider areas keep the table layout.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.breakpoint', 'Show cards at widths up to') }}</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" required\n [ngModel]=\"mobileBreakpoint\" (ngModelChange)=\"onMobileBreakpointChange($event)\"\n [attr.aria-invalid]=\"mobileBreakpointInvalid\"\n aria-describedby=\"table-responsive-width-help\" />\n <span matTextSuffix>px</span>\n </mat-form-field>\n @if (mobileBreakpointInvalid) {\n <p class=\"responsive-settings__error\" role=\"alert\">{{ tx('overview.responsive.invalidWidth', 'Enter a positive whole number.') }}</p>\n }\n <p id=\"table-responsive-width-help\" class=\"responsive-settings__hint\">{{ tx('overview.responsive.widthHint', 'Uses the smaller width of the screen and the table area. Default: 768 px.') }}</p>\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.virtualizationHint', 'Cards require standard rows. With virtual scrolling enabled, records remain in a table.') }}</p>\n }\n </section>\n <div class=\"overview-row\">\n <mat-form-field appearance=\"outline\" class=\"hs-field\">\n <mat-label>{{ tx('overview.horizontalScroll', 'Horizontal scroll') }}</mat-label>\n <mat-select [(ngModel)]=\"horizontalScroll\" (ngModelChange)=\"onHorizontalScrollChange($event)\">\n <mat-option value=\"auto\">{{ tx('overview.horizontalScroll.auto', 'Auto (default)') }}</mat-option>\n <mat-option value=\"wrap\">{{ tx('overview.horizontalScroll.wrap', 'Wrap') }}</mat-option>\n <mat-option value=\"none\">{{ tx('overview.horizontalScroll.none', 'Host controls') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"help small\">{{ tx('overview.horizontalScroll.help', 'Controls how the table handles horizontal width and scrollbar behavior.') }}</div>\n </div>\n @if (isEffectiveLocalMode()) { <div class=\"alert alert--info overview-mode-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text\">\n {{ tx('overview.localModeActive', 'Effective local mode is active: server pagination and sorting strategies are blocked and persisted as client mode.') }}\n </div>\n </div> }\n <behavior-config-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n [forceClientStrategies]=\"isEffectiveLocalMode()\"\n (configChange)=\"onBehaviorConfigChange($event)\"\n (behaviorChange)=\"onBehaviorChange($event)\"\n ></behavior-config-editor>\n </div>\n }\n @case ('columns') {\n <columns-config-editor\n [config]=\"editedConfig\"\n [fieldMetadata]=\"getColumnAuthoringMetas()\"\n (configChange)=\"onColumnsConfigChange($event)\"\n (columnChange)=\"onColumnChange($event)\"\n ></columns-config-editor>\n }\n @case ('detail') {\n <praxis-table-detail-editor [config]=\"editedConfig\"\n (configChange)=\"onDetailConfigChange($event)\"\n (draftStateChange)=\"onDetailDraftStateChange($event)\"\n ></praxis-table-detail-editor>\n }\n @case ('rules') {\n <table-rules-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n (configChange)=\"onRulesConfigChange($event)\"\n ></table-rules-editor>\n }\n @case ('header') {\n <header-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n ></header-appearance-editor>\n }\n @case ('toolbar') {\n <toolbar-actions-editor\n [config]=\"editedConfig\"\n (configChange)=\"onToolbarActionsConfigChange($event)\"\n (toolbarActionsChange)=\"onToolbarActionsChange($event)\"\n (validationChange)=\"onSurfaceDraftValidationChange($event)\"\n ></toolbar-actions-editor>\n }\n <!-- Aba extra para integra\u00E7\u00F5es CRUD (vis\u00EDvel quando em contexto CRUD) -->\n @case ('crud') {\n <crud-integration-editor\n #crudEditorRef\n [tableId]=\"crudContext?.tableId || 'default'\"\n [crudContext]=\"crudContext\"\n [componentKeyId]=\"crudContext?.componentKeyId\"\n ></crud-integration-editor>\n }\n @case ('filters') {\n <div class=\"filters-authoring-stack\">\n <section\n class=\"responsive-settings toolbar-filters-region\"\n data-testid=\"table-unified-filter-region-section\"\n aria-labelledby=\"table-unified-filter-region-title\"\n >\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">filter_list</mat-icon>\n <h3 id=\"table-unified-filter-region-title\">\n {{ tx('filters.region.title', 'Regi\u00E3o \u00FAnica de filtros e escopos da toolbar') }}\n </h3>\n </div>\n <p class=\"responsive-settings__hint\">\n {{\n tx(\n 'filters.region.description',\n 'Centralize escopos r\u00E1pidos (Todos / Ativos / Inativos), busca e gaveta avan\u00E7ada na toolbar da tabela sem controles duplicados.'\n )\n }}\n </p>\n\n <div class=\"toolbar-filters-toggles\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.enabled', 'Regi\u00E3o de filtros na toolbar') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarFiltersEnabled\"\n (ngModelChange)=\"onToolbarFiltersEnabledChange($event)\"\n data-testid=\"table-toolbar-filters-enabled-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.enabled', 'Ativada') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.disabled', 'Desativada') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showQuickFilters', 'Exibir escopos r\u00E1pidos') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowQuickFilters\"\n (ngModelChange)=\"onToolbarShowQuickFiltersChange($event)\"\n data-testid=\"table-toolbar-show-quick-filters-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAdvancedButton', 'Bot\u00E3o de gaveta avan\u00E7ada') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowAdvancedButton\"\n (ngModelChange)=\"onToolbarShowAdvancedButtonChange($event)\"\n data-testid=\"table-toolbar-show-advanced-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAddButton', 'Bot\u00E3o \"Gerenciar campos\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowAddButton\"\n (ngModelChange)=\"onAdvancedFilterShowAddButtonChange($event)\"\n data-testid=\"table-toolbar-show-add-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showFilterSettings', 'Bot\u00E3o \"Configura\u00E7\u00F5es do filtro\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowFilterSettings\"\n (ngModelChange)=\"onAdvancedFilterShowFilterSettingsChange($event)\"\n data-testid=\"table-toolbar-show-filter-settings-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (duplicatedQuickFilterInlineFields.length > 0) {\n <div\n class=\"alert alert--warning connect-alert\"\n data-testid=\"table-filter-duplicate-scope-warning\"\n >\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{\n tx(\n 'filters.region.duplicateWarning',\n 'Os campos abaixo j\u00E1 possuem escopos r\u00E1pidos na toolbar e tamb\u00E9m est\u00E3o nos filtros inline:'\n )\n }}\n <strong>{{ duplicatedQuickFilterInlineFields.join(', ') }}</strong>\n </div>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-filter-consolidate-duplicates-btn\"\n (click)=\"consolidateDuplicateInlineFilterFields()\"\n >\n {{ tx('filters.region.consolidateBtn', 'Consolidar nos escopos r\u00E1pidos') }}\n </button>\n </div>\n }\n\n <div class=\"quick-filters-header\">\n <strong>{{ tx('filters.quickFilters.heading', 'Escopos r\u00E1pidos (quickFilters)') }}</strong>\n <div class=\"quick-filters-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"table-quick-filters-preset-boolean-btn\"\n (click)=\"applyBooleanQuickFilterPreset()\"\n >\n {{ tx('filters.quickFilters.presetBoolean', 'Preset Todos / Ativos / Inativos') }}\n </button>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-quick-filters-add-btn\"\n (click)=\"addQuickFilterScope()\"\n >\n {{ tx('filters.quickFilters.add', 'Adicionar escopo') }}\n </button>\n </div>\n </div>\n\n @if (toolbarQuickFilters.length > 0) {\n <div class=\"quick-filters-list\" data-testid=\"table-quick-filters-list\">\n @for (qf of toolbarQuickFilters; track $index; let idx = $index) {\n <div class=\"quick-filter-row\" [attr.data-testid]=\"'table-quick-filter-row-' + idx\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.id', 'ID') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.id\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { id: $event })\"\n [attr.data-testid]=\"'table-quick-filter-id-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.label', 'R\u00F3tulo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.label\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { label: $event })\"\n [attr.data-testid]=\"'table-quick-filter-label-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.mode', 'Tipo de escopo') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterMode(qf)\"\n (ngModelChange)=\"onQuickFilterModeChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-mode-' + idx\"\n >\n <mat-option value=\"all\">{{ tx('filters.quickFilters.mode.all', 'Todos (limpar filtro)') }}</mat-option>\n <mat-option value=\"boolean\">{{ tx('filters.quickFilters.mode.boolean', 'Status booleano (Sim/N\u00E3o)') }}</mat-option>\n <mat-option value=\"equals\">{{ tx('filters.quickFilters.mode.equals', 'Campo igual a valor') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) !== 'all') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.field', 'Campo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterField(qf)\"\n (ngModelChange)=\"onQuickFilterFieldChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-field-' + idx\"\n />\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) === 'boolean') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-bool-value-' + idx\"\n >\n <mat-option [value]=\"true\">{{ tx('common.boolean.true', 'Verdadeiro (true)') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.boolean.false', 'Falso (false)') }}</mat-option>\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-value-' + idx\"\n />\n </mat-form-field>\n }\n }\n\n <button\n mat-stroked-button\n color=\"warn\"\n type=\"button\"\n [attr.data-testid]=\"'table-quick-filter-remove-' + idx\"\n (click)=\"removeQuickFilterScope(idx)\"\n >\n {{ tx('common.remove', 'Remover') }}\n </button>\n </div>\n }\n </div>\n }\n </section>\n\n <filter-settings\n #tableFilterSettingsRef\n [metadata]=\"getFilterSettingsMetas()\"\n [metadataSource]=\"isUsingFilterDtoMetas() ? 'filter-dto' : 'columns'\"\n [metadataLoading]=\"filterDtoMetasLoading\"\n [metadataErrorMsg]=\"filterDtoMetasErrorMsg\"\n [settings]=\"\n editedConfig.behavior?.filtering?.advancedFilters?.settings\n \"\n (settingsChange)=\"onFilterSettingsChange($event)\"\n ></filter-settings>\n </div>\n }\n @case ('messages') {\n <messages-localization-editor\n [config]=\"editedConfig\"\n (configChange)=\"onMessagesLocalizationConfigChange($event)\"\n (messagesLocalizationChange)=\"\n onMessagesLocalizationChange($event)\n \"\n ></messages-localization-editor>\n }\n @case ('dialogs') {\n <confirm-dialog-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n ></confirm-dialog-appearance-editor>\n }\n @case ('json') {\n <json-config-editor\n [document]=\"buildJsonAuthoringDocument()\"\n (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\"\n (editorEvent)=\"onJsonEditorEvent($event)\"\n ></json-config-editor>\n }\n }\n </div>\n </mat-tab>\n }\n</mat-tab-group>\n@if (statusMessage) { <div class=\"config-editor-status\">\n <span\n class=\"status-text\"\n [class.error]=\"hasErrors\"\n [class.success]=\"hasSuccess\"\n >{{ statusMessage }}</span\n >\n</div> }\n", styles: ["@charset \"UTF-8\";:host{display:block;min-width:0;container:praxis-authoring-editor/inline-size}.editor-section-selector{display:none;padding:var(--pfx-spacing-2, 8px)}.editor-section-selector mat-form-field{width:100%}@container praxis-authoring-editor (max-width: 768px){.editor-section-selector{display:block}::ng-deep .config-tabs>.mat-mdc-tab-header{display:none}}.config-tabs{flex:1 1 auto;display:flex;flex-direction:column}.config-tabs .mat-mdc-tab{min-width:120px}.config-tabs .mat-mdc-tab-body-wrapper,.config-tabs .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.config-tabs .mat-mdc-tab-body-content{height:100%;min-height:0;overflow:visible}.tab-content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:8px 8px 56px;box-sizing:border-box;overflow:visible}.overview-grid{display:grid;min-width:0;grid-template-columns:minmax(0,1fr);gap:12px}.overview-grid .overview-row{display:grid;grid-template-columns:280px 1fr;align-items:end;gap:12px}.overview-grid .overview-row .help.small{opacity:.75;font-size:12px}.overview-mode-alert{align-items:center}.connect-grid{display:grid;gap:12px;padding:8px;grid-template-columns:minmax(0,1fr);align-items:start}.connect-note{grid-column:1/-1;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.connect-alert{grid-column:1/-1;align-items:center}.connect-alert__text{flex:1}.connect-alert__meta{opacity:.85}.educational-card{margin-bottom:24px;background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);flex-shrink:0}.config-editor-status{padding:12px 16px;margin-top:auto;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);flex-shrink:0;position:relative}.status-text{font-size:.875rem;line-height:1.2}.status-text.error{color:var(--md-sys-color-error)}.status-text.success{color:var(--md-sys-color-primary)}@media(max-width:768px){.tab-content{padding:8px 8px 72px}.config-editor-status{padding:12px 16px}.connect-grid{grid-template-columns:1fr}.overview-grid .overview-row{grid-template-columns:1fr;align-items:start}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}}.responsive-settings{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;min-width:0;padding:16px;border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low)}.responsive-settings__heading{display:flex;align-items:center;gap:8px}.responsive-settings h3,.responsive-settings p{margin:0}.responsive-settings h3{font-size:1rem;font-weight:600}.responsive-settings p{font-size:.875rem;line-height:1.5}.responsive-settings__hint{color:var(--md-sys-color-on-surface-variant)}.responsive-settings__error{color:var(--md-sys-color-error)}.responsive-settings mat-form-field{width:100%;min-width:0}.filters-authoring-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:16px}.toolbar-filters-toggles{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}.quick-filters-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.quick-filters-actions{display:flex;flex-wrap:wrap;gap:8px}.quick-filters-list{display:grid;gap:10px}.quick-filter-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));align-items:center;gap:8px;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i4$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i4$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i17$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i17$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: JsonConfigEditorComponent, selector: "json-config-editor", inputs: ["document"], outputs: ["documentChange", "validationChange", "editorEvent"] }, { kind: "component", type: ColumnsConfigEditorComponent, selector: "columns-config-editor", inputs: ["config", "readonly", "fieldMetadata"], outputs: ["configChange", "columnChange"] }, { kind: "component", type: BehaviorConfigEditorComponent, selector: "behavior-config-editor", inputs: ["config", "resourcePath", "forceClientStrategies"], outputs: ["configChange", "behaviorChange"] }, { kind: "component", type: HeaderAppearanceEditorComponent, selector: "header-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: ToolbarActionsEditorComponent, selector: "toolbar-actions-editor", inputs: ["config"], outputs: ["configChange", "validationChange", "toolbarActionsChange"] }, { kind: "component", type: MessagesLocalizationEditorComponent, selector: "messages-localization-editor", inputs: ["config"], outputs: ["configChange", "messagesLocalizationChange"] }, { kind: "component", type: FilterSettingsComponent, selector: "filter-settings", inputs: ["metadata", "metadataSource", "metadataLoading", "metadataErrorMsg", "settings", "configKey"], outputs: ["settingsChange"] }, { kind: "component", type: CrudIntegrationEditorComponent, selector: "crud-integration-editor", inputs: ["tableId", "crudContext", "componentKeyId"] }, { kind: "component", type: ConfirmDialogAppearanceEditorComponent, selector: "confirm-dialog-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: TableRulesEditorComponent, selector: "table-rules-editor", inputs: ["config", "resourcePath", "fields", "i18nRules", "debugLogs", "debugLevel"], outputs: ["configChange"] }, { kind: "component", type: TableDetailEditorComponent, selector: "praxis-table-detail-editor", inputs: ["config"], outputs: ["configChange", "draftStateChange"] }] });
|
|
73894
|
+
], viewQueries: [{ propertyName: "filterSettingsEditor", first: true, predicate: ["tableFilterSettingsRef"], descendants: true }, { propertyName: "behaviorEditor", first: true, predicate: BehaviorConfigEditorComponent, descendants: true }, { propertyName: "detailEditor", first: true, predicate: TableDetailEditorComponent, descendants: true }, { propertyName: "rulesEditor", first: true, predicate: TableRulesEditorComponent, descendants: true }, { propertyName: "crudEditorSetter", first: true, predicate: ["crudEditorRef"], descendants: true }], ngImport: i0, template: "<div class=\"editor-section-selector\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('sections.selector', 'Editor section') }}</mat-label>\n <mat-select [(ngModel)]=\"activeSectionIndex\" data-testid=\"table-config-editor-sections\">\n @for (section of sections; track section.id; let index = $index) {\n <mat-option [value]=\"index\">{{ section.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" [(selectedIndex)]=\"activeSectionIndex\">\n @for (section of sections; track section.id) {\n <mat-tab>\n <ng-template mat-tab-label>\n @if (section.icon) { <mat-icon [praxisIcon]=\"section.icon\"></mat-icon> }\n <span [attr.data-testid]=\"'config-tab-' + section.id\">{{ section.label }}</span>\n </ng-template>\n <div class=\"tab-content\">\n @switch (section.id) {\n @case ('connect') {\n <div class=\"connect-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.resource', 'Resource') }}</mat-label>\n <input matInput [(ngModel)]=\"resourcePath\" (ngModelChange)=\"onResourcePathChange($event)\" [placeholder]=\"tx('connect.resource.placeholder', 'e.g. employees')\" />\n <mat-icon matSuffix>link</mat-icon>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.primaryKey', 'Primary key') }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"idField\"\n (ngModelChange)=\"onIdFieldChange($event)\"\n [matAutocomplete]=\"idFieldPicker\"\n [placeholder]=\"tx('connect.primaryKey.placeholder', 'e.g. id, uuid, code')\"\n />\n <mat-icon matSuffix>fingerprint</mat-icon>\n <mat-autocomplete\n #idFieldPicker=\"matAutocomplete\"\n (optionSelected)=\"onIdFieldOptionSelected($event.option.value)\"\n >\n @for (option of filteredIdFieldOptions; track option.name) {\n <mat-option [value]=\"option.name\">\n <span>{{ option.name }}</span>\n @if (option.label && option.label !== option.name) {\n <small> - {{ option.label }}</small>\n }\n </mat-option>\n }\n @if (filteredIdFieldOptions.length === 0) {\n <mat-option disabled>\n {{ tx('connect.primaryKey.empty', 'No matching field found.') }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n <p class=\"connect-note\">{{ tx('connect.note', 'Define the API resource and, when needed, the primary key.') }}</p>\n <!-- Diverg\u00EAncia: idField -->\n @if (idFieldDiverges) { <div class=\"alert alert--warning connect-alert\">\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.serverPrimaryKeyDiverges', 'The primary key on the server differs from the current configuration.') }}\n <span class=\"connect-alert__meta\">(config: {{ idField || 'id' }} | servidor: {{ serverIdField || 'id' }})</span>\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onReconcileIdField()\">{{ tx('connect.reconcile', 'Reconcile') }}</button>\n </div> }\n <!-- Diverg\u00EAncia: serverHash -->\n @if (schemaHashDiverges) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotDiverges', 'The saved schema snapshot differs from the current server schema.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.updateMetadata', 'Update metadata') }}</button>\n </div> }\n @if (!schemaHashDiverges && schemaSnapshotMissing) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotMissing', 'A current schema exists on the server, but there is still no persisted snapshot for reconciliation.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.saveSnapshot', 'Save snapshot') }}</button>\n </div> }\n </div>\n }\n @case ('overview') {\n <div class=\"overview-grid\">\n <section class=\"responsive-settings\" aria-labelledby=\"table-responsive-title\">\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">devices</mat-icon>\n <h3 id=\"table-responsive-title\">{{ tx('overview.responsive.title', 'Narrow screens') }}</h3>\n </div>\n <p>{{ tx('overview.responsive.description', 'Choose how records appear when the table has less space.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.mode', 'Record layout') }}</mat-label>\n <mat-select [ngModel]=\"mobileCardMode\" (ngModelChange)=\"onMobileCardModeChange($event)\">\n <mat-option [value]=\"false\">{{ tx('overview.responsive.table', 'Table') }}</mat-option>\n <mat-option [value]=\"true\">{{ tx('overview.responsive.cards', 'Cards') }}</mat-option>\n </mat-select>\n </mat-form-field>\n @if (mobileCardMode) {\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.cardsHint', 'Each record becomes a card with its visible columns. Selection and row actions remain available. Wider areas keep the table layout.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.breakpoint', 'Show cards at widths up to') }}</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" required\n [ngModel]=\"mobileBreakpoint\" (ngModelChange)=\"onMobileBreakpointChange($event)\"\n [attr.aria-invalid]=\"mobileBreakpointInvalid\"\n aria-describedby=\"table-responsive-width-help\" />\n <span matTextSuffix>px</span>\n </mat-form-field>\n @if (mobileBreakpointInvalid) {\n <p class=\"responsive-settings__error\" role=\"alert\">{{ tx('overview.responsive.invalidWidth', 'Enter a positive whole number.') }}</p>\n }\n <p id=\"table-responsive-width-help\" class=\"responsive-settings__hint\">{{ tx('overview.responsive.widthHint', 'Uses the smaller width of the screen and the table area. Default: 768 px.') }}</p>\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.virtualizationHint', 'Cards require standard rows. With virtual scrolling enabled, records remain in a table.') }}</p>\n }\n </section>\n <div class=\"overview-row\">\n <mat-form-field appearance=\"outline\" class=\"hs-field\">\n <mat-label>{{ tx('overview.horizontalScroll', 'Horizontal scroll') }}</mat-label>\n <mat-select [(ngModel)]=\"horizontalScroll\" (ngModelChange)=\"onHorizontalScrollChange($event)\">\n <mat-option value=\"auto\">{{ tx('overview.horizontalScroll.auto', 'Auto (default)') }}</mat-option>\n <mat-option value=\"wrap\">{{ tx('overview.horizontalScroll.wrap', 'Wrap') }}</mat-option>\n <mat-option value=\"none\">{{ tx('overview.horizontalScroll.none', 'Host controls') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"help small\">{{ tx('overview.horizontalScroll.help', 'Controls how the table handles horizontal width and scrollbar behavior.') }}</div>\n </div>\n @if (isEffectiveLocalMode()) { <div class=\"alert alert--info overview-mode-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text\">\n {{ tx('overview.localModeActive', 'Effective local mode is active: server pagination and sorting strategies are blocked and persisted as client mode.') }}\n </div>\n </div> }\n <behavior-config-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n [forceClientStrategies]=\"isEffectiveLocalMode()\"\n (configChange)=\"onBehaviorConfigChange($event)\"\n (behaviorChange)=\"onBehaviorChange($event)\"\n ></behavior-config-editor>\n </div>\n }\n @case ('columns') {\n <columns-config-editor\n [config]=\"editedConfig\"\n [fieldMetadata]=\"getColumnAuthoringMetas()\"\n (configChange)=\"onColumnsConfigChange($event)\"\n (columnChange)=\"onColumnChange($event)\"\n ></columns-config-editor>\n }\n @case ('detail') {\n <praxis-table-detail-editor [config]=\"editedConfig\"\n (configChange)=\"onDetailConfigChange($event)\"\n (draftStateChange)=\"onDetailDraftStateChange($event)\"\n ></praxis-table-detail-editor>\n }\n @case ('rules') {\n <table-rules-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n (configChange)=\"onRulesConfigChange($event)\"\n ></table-rules-editor>\n }\n @case ('header') {\n <header-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n ></header-appearance-editor>\n }\n @case ('toolbar') {\n <toolbar-actions-editor\n [config]=\"editedConfig\"\n (configChange)=\"onToolbarActionsConfigChange($event)\"\n (toolbarActionsChange)=\"onToolbarActionsChange($event)\"\n (validationChange)=\"onSurfaceDraftValidationChange($event)\"\n ></toolbar-actions-editor>\n }\n <!-- Aba extra para integra\u00E7\u00F5es CRUD (vis\u00EDvel quando em contexto CRUD) -->\n @case ('crud') {\n <crud-integration-editor\n #crudEditorRef\n [tableId]=\"crudContext?.tableId || 'default'\"\n [crudContext]=\"crudContext\"\n [componentKeyId]=\"crudContext?.componentKeyId\"\n ></crud-integration-editor>\n }\n @case ('filters') {\n <div class=\"filters-authoring-stack\">\n <section\n class=\"responsive-settings toolbar-filters-region\"\n data-testid=\"table-unified-filter-region-section\"\n aria-labelledby=\"table-unified-filter-region-title\"\n >\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">filter_list</mat-icon>\n <h3 id=\"table-unified-filter-region-title\">\n {{ tx('filters.region.title', 'Regi\u00E3o \u00FAnica de filtros e escopos da toolbar') }}\n </h3>\n </div>\n <p class=\"responsive-settings__hint\">\n {{\n tx(\n 'filters.region.description',\n 'Centralize escopos r\u00E1pidos (Todos / Ativos / Inativos), busca e gaveta avan\u00E7ada na toolbar da tabela sem controles duplicados.'\n )\n }}\n </p>\n\n <div class=\"toolbar-filters-toggles\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.enabled', 'Regi\u00E3o de filtros na toolbar') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarFiltersEnabled\"\n (ngModelChange)=\"onToolbarFiltersEnabledChange($event)\"\n data-testid=\"table-toolbar-filters-enabled-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.enabled', 'Ativada') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.disabled', 'Desativada') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showQuickFilters', 'Exibir escopos r\u00E1pidos') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowQuickFilters\"\n (ngModelChange)=\"onToolbarShowQuickFiltersChange($event)\"\n data-testid=\"table-toolbar-show-quick-filters-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAdvancedButton', 'Bot\u00E3o de gaveta avan\u00E7ada') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowAdvancedButton\"\n (ngModelChange)=\"onToolbarShowAdvancedButtonChange($event)\"\n data-testid=\"table-toolbar-show-advanced-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAddButton', 'Bot\u00E3o \"Gerenciar campos\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowAddButton\"\n (ngModelChange)=\"onAdvancedFilterShowAddButtonChange($event)\"\n data-testid=\"table-toolbar-show-add-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showFilterSettings', 'Bot\u00E3o \"Configura\u00E7\u00F5es do filtro\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowFilterSettings\"\n (ngModelChange)=\"onAdvancedFilterShowFilterSettingsChange($event)\"\n data-testid=\"table-toolbar-show-filter-settings-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (duplicatedQuickFilterInlineFields.length > 0) {\n <div\n class=\"alert alert--warning connect-alert\"\n data-testid=\"table-filter-duplicate-scope-warning\"\n >\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{\n tx(\n 'filters.region.duplicateWarning',\n 'Os campos abaixo j\u00E1 possuem escopos r\u00E1pidos na toolbar e tamb\u00E9m est\u00E3o nos filtros inline:'\n )\n }}\n <strong>{{ duplicatedQuickFilterInlineFields.join(', ') }}</strong>\n </div>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-filter-consolidate-duplicates-btn\"\n (click)=\"consolidateDuplicateInlineFilterFields()\"\n >\n {{ tx('filters.region.consolidateBtn', 'Consolidar nos escopos r\u00E1pidos') }}\n </button>\n </div>\n }\n\n <div class=\"quick-filters-header\">\n <strong>{{ tx('filters.quickFilters.heading', 'Escopos r\u00E1pidos (quickFilters)') }}</strong>\n <div class=\"quick-filters-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"table-quick-filters-preset-boolean-btn\"\n (click)=\"applyBooleanQuickFilterPreset()\"\n >\n {{ tx('filters.quickFilters.presetBoolean', 'Preset Todos / Ativos / Inativos') }}\n </button>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-quick-filters-add-btn\"\n (click)=\"addQuickFilterScope()\"\n >\n {{ tx('filters.quickFilters.add', 'Adicionar escopo') }}\n </button>\n </div>\n </div>\n\n @if (toolbarQuickFilters.length > 0) {\n <div class=\"quick-filters-list\" data-testid=\"table-quick-filters-list\">\n @for (qf of toolbarQuickFilters; track $index; let idx = $index) {\n <div class=\"quick-filter-row\" [attr.data-testid]=\"'table-quick-filter-row-' + idx\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.id', 'ID') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.id\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { id: $event })\"\n [attr.data-testid]=\"'table-quick-filter-id-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.label', 'R\u00F3tulo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.label\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { label: $event })\"\n [attr.data-testid]=\"'table-quick-filter-label-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.mode', 'Tipo de escopo') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterMode(qf)\"\n (ngModelChange)=\"onQuickFilterModeChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-mode-' + idx\"\n >\n <mat-option value=\"all\">{{ tx('filters.quickFilters.mode.all', 'Todos (limpar filtro)') }}</mat-option>\n <mat-option value=\"boolean\">{{ tx('filters.quickFilters.mode.boolean', 'Status booleano (Sim/N\u00E3o)') }}</mat-option>\n <mat-option value=\"equals\">{{ tx('filters.quickFilters.mode.equals', 'Campo igual a valor') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) !== 'all') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.field', 'Campo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterField(qf)\"\n (ngModelChange)=\"onQuickFilterFieldChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-field-' + idx\"\n />\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) === 'boolean') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-bool-value-' + idx\"\n >\n <mat-option [value]=\"true\">{{ tx('common.boolean.true', 'Verdadeiro (true)') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.boolean.false', 'Falso (false)') }}</mat-option>\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-value-' + idx\"\n />\n </mat-form-field>\n }\n }\n\n <button\n mat-stroked-button\n color=\"warn\"\n type=\"button\"\n [attr.data-testid]=\"'table-quick-filter-remove-' + idx\"\n (click)=\"removeQuickFilterScope(idx)\"\n >\n {{ tx('common.remove', 'Remover') }}\n </button>\n </div>\n }\n </div>\n }\n </section>\n\n <filter-settings\n #tableFilterSettingsRef\n [metadata]=\"getFilterSettingsMetas()\"\n [metadataSource]=\"isUsingFilterDtoMetas() ? 'filter-dto' : 'columns'\"\n [metadataLoading]=\"filterDtoMetasLoading\"\n [metadataErrorMsg]=\"filterDtoMetasErrorMsg\"\n [settings]=\"\n editedConfig.behavior?.filtering?.advancedFilters?.settings\n \"\n (settingsChange)=\"onFilterSettingsChange($event)\"\n ></filter-settings>\n </div>\n }\n @case ('messages') {\n <messages-localization-editor\n [config]=\"editedConfig\"\n (configChange)=\"onMessagesLocalizationConfigChange($event)\"\n (messagesLocalizationChange)=\"\n onMessagesLocalizationChange($event)\n \"\n ></messages-localization-editor>\n }\n @case ('dialogs') {\n <confirm-dialog-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n ></confirm-dialog-appearance-editor>\n }\n @case ('json') {\n <json-config-editor\n [document]=\"buildJsonAuthoringDocument()\"\n (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\"\n (editorEvent)=\"onJsonEditorEvent($event)\"\n ></json-config-editor>\n }\n }\n </div>\n </mat-tab>\n }\n</mat-tab-group>\n@if (statusMessage) { <div class=\"config-editor-status\">\n <span\n class=\"status-text\"\n [class.error]=\"hasErrors\"\n [class.success]=\"hasSuccess\"\n >{{ statusMessage }}</span\n >\n</div> }\n", styles: ["@charset \"UTF-8\";:host{display:block;min-width:0;container:praxis-authoring-editor/inline-size}.editor-section-selector{display:block;padding:var(--pfx-spacing-2, 8px)}.editor-section-selector mat-form-field{width:100%}@container praxis-authoring-editor (max-width: 768px){.editor-section-selector{display:block}::ng-deep .config-tabs>.mat-mdc-tab-header{display:none}}.config-tabs{flex:1 1 auto;display:flex;flex-direction:column}.config-tabs .mat-mdc-tab{min-width:120px}.config-tabs .mat-mdc-tab-body-wrapper,.config-tabs .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.config-tabs .mat-mdc-tab-body-content{height:100%;min-height:0;overflow:visible}.tab-content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:8px 8px 56px;box-sizing:border-box;overflow:visible}.overview-grid{display:grid;min-width:0;grid-template-columns:minmax(0,1fr);gap:12px}.overview-grid .overview-row{display:grid;grid-template-columns:280px 1fr;align-items:end;gap:12px}.overview-grid .overview-row .help.small{opacity:.75;font-size:12px}.overview-mode-alert{align-items:center}.connect-grid{display:grid;gap:12px;padding:8px;grid-template-columns:minmax(0,1fr);align-items:start}.connect-note{grid-column:1/-1;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.connect-alert{grid-column:1/-1;align-items:center}.connect-alert__text{flex:1}.connect-alert__meta{opacity:.85}.educational-card{margin-bottom:24px;background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);flex-shrink:0}.config-editor-status{padding:12px 16px;margin-top:auto;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);flex-shrink:0;position:relative}.status-text{font-size:.875rem;line-height:1.2}.status-text.error{color:var(--md-sys-color-error)}.status-text.success{color:var(--md-sys-color-primary)}@media(max-width:768px){.tab-content{padding:8px 8px 72px}.config-editor-status{padding:12px 16px}.connect-grid{grid-template-columns:1fr}.overview-grid .overview-row{grid-template-columns:1fr;align-items:start}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}}.responsive-settings{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;min-width:0;padding:16px;border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low)}.responsive-settings__heading{display:flex;align-items:center;gap:8px}.responsive-settings h3,.responsive-settings p{margin:0}.responsive-settings h3{font-size:1rem;font-weight:600}.responsive-settings p{font-size:.875rem;line-height:1.5}.responsive-settings__hint{color:var(--md-sys-color-on-surface-variant)}.responsive-settings__error{color:var(--md-sys-color-error)}.responsive-settings mat-form-field{width:100%;min-width:0}.filters-authoring-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:16px}.toolbar-filters-toggles{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}.quick-filters-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.quick-filters-actions{display:flex;flex-wrap:wrap;gap:8px}.quick-filters-list{display:grid;gap:10px}.quick-filter-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));align-items:center;gap:8px;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}\n"], dependencies: [{ kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "directive", type: i4$1.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i4$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i4$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MatAutocompleteModule }, { kind: "component", type: i17$1.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i17$1.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2$1.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2$1.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2$1.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3$1.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "directive", type: PraxisIconDirective, selector: "mat-icon[praxisIcon]", inputs: ["praxisIcon"] }, { kind: "component", type: JsonConfigEditorComponent, selector: "json-config-editor", inputs: ["document"], outputs: ["documentChange", "validationChange", "editorEvent"] }, { kind: "component", type: ColumnsConfigEditorComponent, selector: "columns-config-editor", inputs: ["config", "readonly", "fieldMetadata"], outputs: ["configChange", "columnChange"] }, { kind: "component", type: BehaviorConfigEditorComponent, selector: "behavior-config-editor", inputs: ["config", "resourcePath", "forceClientStrategies"], outputs: ["configChange", "behaviorChange"] }, { kind: "component", type: HeaderAppearanceEditorComponent, selector: "header-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: ToolbarActionsEditorComponent, selector: "toolbar-actions-editor", inputs: ["config"], outputs: ["configChange", "validationChange", "toolbarActionsChange"] }, { kind: "component", type: MessagesLocalizationEditorComponent, selector: "messages-localization-editor", inputs: ["config"], outputs: ["configChange", "messagesLocalizationChange"] }, { kind: "component", type: FilterSettingsComponent, selector: "filter-settings", inputs: ["metadata", "metadataSource", "metadataLoading", "metadataErrorMsg", "settings", "configKey"], outputs: ["settingsChange"] }, { kind: "component", type: CrudIntegrationEditorComponent, selector: "crud-integration-editor", inputs: ["tableId", "crudContext", "componentKeyId"] }, { kind: "component", type: ConfirmDialogAppearanceEditorComponent, selector: "confirm-dialog-appearance-editor", inputs: ["config"], outputs: ["configChange"] }, { kind: "component", type: TableRulesEditorComponent, selector: "table-rules-editor", inputs: ["config", "resourcePath", "fields", "i18nRules", "debugLogs", "debugLevel"], outputs: ["configChange"] }, { kind: "component", type: TableDetailEditorComponent, selector: "praxis-table-detail-editor", inputs: ["config"], outputs: ["configChange", "draftStateChange"] }] });
|
|
73689
73895
|
}
|
|
73690
73896
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisTableConfigEditor, decorators: [{
|
|
73691
73897
|
type: Component,
|
|
@@ -73713,7 +73919,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
|
|
|
73713
73919
|
], providers: [
|
|
73714
73920
|
TableConfigService,
|
|
73715
73921
|
providePraxisI18nConfig(PRAXIS_TABLE_EDITOR_I18N_CONFIG),
|
|
73716
|
-
], template: "<div class=\"editor-section-selector\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('sections.selector', 'Editor section') }}</mat-label>\n <mat-select [(ngModel)]=\"activeSectionIndex\" data-testid=\"table-config-editor-sections\">\n @for (section of sections; track section.id; let index = $index) {\n <mat-option [value]=\"index\">{{ section.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" [(selectedIndex)]=\"activeSectionIndex\">\n @for (section of sections; track section.id) {\n <mat-tab>\n <ng-template mat-tab-label>\n @if (section.icon) { <mat-icon [praxisIcon]=\"section.icon\"></mat-icon> }\n <span [attr.data-testid]=\"'config-tab-' + section.id\">{{ section.label }}</span>\n </ng-template>\n <div class=\"tab-content\">\n @switch (section.id) {\n @case ('connect') {\n <div class=\"connect-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.resource', 'Resource') }}</mat-label>\n <input matInput [(ngModel)]=\"resourcePath\" (ngModelChange)=\"onResourcePathChange($event)\" [placeholder]=\"tx('connect.resource.placeholder', 'e.g. employees')\" />\n <mat-icon matSuffix>link</mat-icon>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.primaryKey', 'Primary key') }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"idField\"\n (ngModelChange)=\"onIdFieldChange($event)\"\n [matAutocomplete]=\"idFieldPicker\"\n [placeholder]=\"tx('connect.primaryKey.placeholder', 'e.g. id, uuid, code')\"\n />\n <mat-icon matSuffix>fingerprint</mat-icon>\n <mat-autocomplete\n #idFieldPicker=\"matAutocomplete\"\n (optionSelected)=\"onIdFieldOptionSelected($event.option.value)\"\n >\n @for (option of filteredIdFieldOptions; track option.name) {\n <mat-option [value]=\"option.name\">\n <span>{{ option.name }}</span>\n @if (option.label && option.label !== option.name) {\n <small> - {{ option.label }}</small>\n }\n </mat-option>\n }\n @if (filteredIdFieldOptions.length === 0) {\n <mat-option disabled>\n {{ tx('connect.primaryKey.empty', 'No matching field found.') }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n <p class=\"connect-note\">{{ tx('connect.note', 'Define the API resource and, when needed, the primary key.') }}</p>\n <!-- Diverg\u00EAncia: idField -->\n @if (idFieldDiverges) { <div class=\"alert alert--warning connect-alert\">\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.serverPrimaryKeyDiverges', 'The primary key on the server differs from the current configuration.') }}\n <span class=\"connect-alert__meta\">(config: {{ idField || 'id' }} | servidor: {{ serverIdField || 'id' }})</span>\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onReconcileIdField()\">{{ tx('connect.reconcile', 'Reconcile') }}</button>\n </div> }\n <!-- Diverg\u00EAncia: serverHash -->\n @if (schemaHashDiverges) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotDiverges', 'The saved schema snapshot differs from the current server schema.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.updateMetadata', 'Update metadata') }}</button>\n </div> }\n @if (!schemaHashDiverges && schemaSnapshotMissing) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotMissing', 'A current schema exists on the server, but there is still no persisted snapshot for reconciliation.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.saveSnapshot', 'Save snapshot') }}</button>\n </div> }\n </div>\n }\n @case ('overview') {\n <div class=\"overview-grid\">\n <section class=\"responsive-settings\" aria-labelledby=\"table-responsive-title\">\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">devices</mat-icon>\n <h3 id=\"table-responsive-title\">{{ tx('overview.responsive.title', 'Narrow screens') }}</h3>\n </div>\n <p>{{ tx('overview.responsive.description', 'Choose how records appear when the table has less space.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.mode', 'Record layout') }}</mat-label>\n <mat-select [ngModel]=\"mobileCardMode\" (ngModelChange)=\"onMobileCardModeChange($event)\">\n <mat-option [value]=\"false\">{{ tx('overview.responsive.table', 'Table') }}</mat-option>\n <mat-option [value]=\"true\">{{ tx('overview.responsive.cards', 'Cards') }}</mat-option>\n </mat-select>\n </mat-form-field>\n @if (mobileCardMode) {\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.cardsHint', 'Each record becomes a card with its visible columns. Selection and row actions remain available. Wider areas keep the table layout.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.breakpoint', 'Show cards at widths up to') }}</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" required\n [ngModel]=\"mobileBreakpoint\" (ngModelChange)=\"onMobileBreakpointChange($event)\"\n [attr.aria-invalid]=\"mobileBreakpointInvalid\"\n aria-describedby=\"table-responsive-width-help\" />\n <span matTextSuffix>px</span>\n </mat-form-field>\n @if (mobileBreakpointInvalid) {\n <p class=\"responsive-settings__error\" role=\"alert\">{{ tx('overview.responsive.invalidWidth', 'Enter a positive whole number.') }}</p>\n }\n <p id=\"table-responsive-width-help\" class=\"responsive-settings__hint\">{{ tx('overview.responsive.widthHint', 'Uses the smaller width of the screen and the table area. Default: 768 px.') }}</p>\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.virtualizationHint', 'Cards require standard rows. With virtual scrolling enabled, records remain in a table.') }}</p>\n }\n </section>\n <div class=\"overview-row\">\n <mat-form-field appearance=\"outline\" class=\"hs-field\">\n <mat-label>{{ tx('overview.horizontalScroll', 'Horizontal scroll') }}</mat-label>\n <mat-select [(ngModel)]=\"horizontalScroll\" (ngModelChange)=\"onHorizontalScrollChange($event)\">\n <mat-option value=\"auto\">{{ tx('overview.horizontalScroll.auto', 'Auto (default)') }}</mat-option>\n <mat-option value=\"wrap\">{{ tx('overview.horizontalScroll.wrap', 'Wrap') }}</mat-option>\n <mat-option value=\"none\">{{ tx('overview.horizontalScroll.none', 'Host controls') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"help small\">{{ tx('overview.horizontalScroll.help', 'Controls how the table handles horizontal width and scrollbar behavior.') }}</div>\n </div>\n @if (isEffectiveLocalMode()) { <div class=\"alert alert--info overview-mode-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text\">\n {{ tx('overview.localModeActive', 'Effective local mode is active: server pagination and sorting strategies are blocked and persisted as client mode.') }}\n </div>\n </div> }\n <behavior-config-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n [forceClientStrategies]=\"isEffectiveLocalMode()\"\n (configChange)=\"onBehaviorConfigChange($event)\"\n (behaviorChange)=\"onBehaviorChange($event)\"\n ></behavior-config-editor>\n </div>\n }\n @case ('columns') {\n <columns-config-editor\n [config]=\"editedConfig\"\n [fieldMetadata]=\"getColumnAuthoringMetas()\"\n (configChange)=\"onColumnsConfigChange($event)\"\n (columnChange)=\"onColumnChange($event)\"\n ></columns-config-editor>\n }\n @case ('detail') {\n <praxis-table-detail-editor [config]=\"editedConfig\"\n (configChange)=\"onDetailConfigChange($event)\"\n (draftStateChange)=\"onDetailDraftStateChange($event)\"\n ></praxis-table-detail-editor>\n }\n @case ('rules') {\n <table-rules-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n (configChange)=\"onRulesConfigChange($event)\"\n ></table-rules-editor>\n }\n @case ('header') {\n <header-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n ></header-appearance-editor>\n }\n @case ('toolbar') {\n <toolbar-actions-editor\n [config]=\"editedConfig\"\n (configChange)=\"onToolbarActionsConfigChange($event)\"\n (toolbarActionsChange)=\"onToolbarActionsChange($event)\"\n (validationChange)=\"onSurfaceDraftValidationChange($event)\"\n ></toolbar-actions-editor>\n }\n <!-- Aba extra para integra\u00E7\u00F5es CRUD (vis\u00EDvel quando em contexto CRUD) -->\n @case ('crud') {\n <crud-integration-editor\n #crudEditorRef\n [tableId]=\"crudContext?.tableId || 'default'\"\n [crudContext]=\"crudContext\"\n [componentKeyId]=\"crudContext?.componentKeyId\"\n ></crud-integration-editor>\n }\n @case ('filters') {\n <div class=\"filters-authoring-stack\">\n <section\n class=\"responsive-settings toolbar-filters-region\"\n data-testid=\"table-unified-filter-region-section\"\n aria-labelledby=\"table-unified-filter-region-title\"\n >\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">filter_list</mat-icon>\n <h3 id=\"table-unified-filter-region-title\">\n {{ tx('filters.region.title', 'Regi\u00E3o \u00FAnica de filtros e escopos da toolbar') }}\n </h3>\n </div>\n <p class=\"responsive-settings__hint\">\n {{\n tx(\n 'filters.region.description',\n 'Centralize escopos r\u00E1pidos (Todos / Ativos / Inativos), busca e gaveta avan\u00E7ada na toolbar da tabela sem controles duplicados.'\n )\n }}\n </p>\n\n <div class=\"toolbar-filters-toggles\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.enabled', 'Regi\u00E3o de filtros na toolbar') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarFiltersEnabled\"\n (ngModelChange)=\"onToolbarFiltersEnabledChange($event)\"\n data-testid=\"table-toolbar-filters-enabled-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.enabled', 'Ativada') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.disabled', 'Desativada') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showQuickFilters', 'Exibir escopos r\u00E1pidos') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowQuickFilters\"\n (ngModelChange)=\"onToolbarShowQuickFiltersChange($event)\"\n data-testid=\"table-toolbar-show-quick-filters-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAdvancedButton', 'Bot\u00E3o de gaveta avan\u00E7ada') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowAdvancedButton\"\n (ngModelChange)=\"onToolbarShowAdvancedButtonChange($event)\"\n data-testid=\"table-toolbar-show-advanced-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAddButton', 'Bot\u00E3o \"Gerenciar campos\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowAddButton\"\n (ngModelChange)=\"onAdvancedFilterShowAddButtonChange($event)\"\n data-testid=\"table-toolbar-show-add-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showFilterSettings', 'Bot\u00E3o \"Configura\u00E7\u00F5es do filtro\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowFilterSettings\"\n (ngModelChange)=\"onAdvancedFilterShowFilterSettingsChange($event)\"\n data-testid=\"table-toolbar-show-filter-settings-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (duplicatedQuickFilterInlineFields.length > 0) {\n <div\n class=\"alert alert--warning connect-alert\"\n data-testid=\"table-filter-duplicate-scope-warning\"\n >\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{\n tx(\n 'filters.region.duplicateWarning',\n 'Os campos abaixo j\u00E1 possuem escopos r\u00E1pidos na toolbar e tamb\u00E9m est\u00E3o nos filtros inline:'\n )\n }}\n <strong>{{ duplicatedQuickFilterInlineFields.join(', ') }}</strong>\n </div>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-filter-consolidate-duplicates-btn\"\n (click)=\"consolidateDuplicateInlineFilterFields()\"\n >\n {{ tx('filters.region.consolidateBtn', 'Consolidar nos escopos r\u00E1pidos') }}\n </button>\n </div>\n }\n\n <div class=\"quick-filters-header\">\n <strong>{{ tx('filters.quickFilters.heading', 'Escopos r\u00E1pidos (quickFilters)') }}</strong>\n <div class=\"quick-filters-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"table-quick-filters-preset-boolean-btn\"\n (click)=\"applyBooleanQuickFilterPreset()\"\n >\n {{ tx('filters.quickFilters.presetBoolean', 'Preset Todos / Ativos / Inativos') }}\n </button>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-quick-filters-add-btn\"\n (click)=\"addQuickFilterScope()\"\n >\n {{ tx('filters.quickFilters.add', 'Adicionar escopo') }}\n </button>\n </div>\n </div>\n\n @if (toolbarQuickFilters.length > 0) {\n <div class=\"quick-filters-list\" data-testid=\"table-quick-filters-list\">\n @for (qf of toolbarQuickFilters; track $index; let idx = $index) {\n <div class=\"quick-filter-row\" [attr.data-testid]=\"'table-quick-filter-row-' + idx\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.id', 'ID') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.id\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { id: $event })\"\n [attr.data-testid]=\"'table-quick-filter-id-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.label', 'R\u00F3tulo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.label\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { label: $event })\"\n [attr.data-testid]=\"'table-quick-filter-label-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.mode', 'Tipo de escopo') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterMode(qf)\"\n (ngModelChange)=\"onQuickFilterModeChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-mode-' + idx\"\n >\n <mat-option value=\"all\">{{ tx('filters.quickFilters.mode.all', 'Todos (limpar filtro)') }}</mat-option>\n <mat-option value=\"boolean\">{{ tx('filters.quickFilters.mode.boolean', 'Status booleano (Sim/N\u00E3o)') }}</mat-option>\n <mat-option value=\"equals\">{{ tx('filters.quickFilters.mode.equals', 'Campo igual a valor') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) !== 'all') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.field', 'Campo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterField(qf)\"\n (ngModelChange)=\"onQuickFilterFieldChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-field-' + idx\"\n />\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) === 'boolean') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-bool-value-' + idx\"\n >\n <mat-option [value]=\"true\">{{ tx('common.boolean.true', 'Verdadeiro (true)') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.boolean.false', 'Falso (false)') }}</mat-option>\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-value-' + idx\"\n />\n </mat-form-field>\n }\n }\n\n <button\n mat-stroked-button\n color=\"warn\"\n type=\"button\"\n [attr.data-testid]=\"'table-quick-filter-remove-' + idx\"\n (click)=\"removeQuickFilterScope(idx)\"\n >\n {{ tx('common.remove', 'Remover') }}\n </button>\n </div>\n }\n </div>\n }\n </section>\n\n <filter-settings\n #tableFilterSettingsRef\n [metadata]=\"getFilterSettingsMetas()\"\n [metadataSource]=\"isUsingFilterDtoMetas() ? 'filter-dto' : 'columns'\"\n [metadataLoading]=\"filterDtoMetasLoading\"\n [metadataErrorMsg]=\"filterDtoMetasErrorMsg\"\n [settings]=\"\n editedConfig.behavior?.filtering?.advancedFilters?.settings\n \"\n (settingsChange)=\"onFilterSettingsChange($event)\"\n ></filter-settings>\n </div>\n }\n @case ('messages') {\n <messages-localization-editor\n [config]=\"editedConfig\"\n (configChange)=\"onMessagesLocalizationConfigChange($event)\"\n (messagesLocalizationChange)=\"\n onMessagesLocalizationChange($event)\n \"\n ></messages-localization-editor>\n }\n @case ('dialogs') {\n <confirm-dialog-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n ></confirm-dialog-appearance-editor>\n }\n @case ('json') {\n <json-config-editor\n [document]=\"buildJsonAuthoringDocument()\"\n (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\"\n (editorEvent)=\"onJsonEditorEvent($event)\"\n ></json-config-editor>\n }\n }\n </div>\n </mat-tab>\n }\n</mat-tab-group>\n@if (statusMessage) { <div class=\"config-editor-status\">\n <span\n class=\"status-text\"\n [class.error]=\"hasErrors\"\n [class.success]=\"hasSuccess\"\n >{{ statusMessage }}</span\n >\n</div> }\n", styles: ["@charset \"UTF-8\";:host{display:block;min-width:0;container:praxis-authoring-editor/inline-size}.editor-section-selector{display:none;padding:var(--pfx-spacing-2, 8px)}.editor-section-selector mat-form-field{width:100%}@container praxis-authoring-editor (max-width: 768px){.editor-section-selector{display:block}::ng-deep .config-tabs>.mat-mdc-tab-header{display:none}}.config-tabs{flex:1 1 auto;display:flex;flex-direction:column}.config-tabs .mat-mdc-tab{min-width:120px}.config-tabs .mat-mdc-tab-body-wrapper,.config-tabs .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.config-tabs .mat-mdc-tab-body-content{height:100%;min-height:0;overflow:visible}.tab-content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:8px 8px 56px;box-sizing:border-box;overflow:visible}.overview-grid{display:grid;min-width:0;grid-template-columns:minmax(0,1fr);gap:12px}.overview-grid .overview-row{display:grid;grid-template-columns:280px 1fr;align-items:end;gap:12px}.overview-grid .overview-row .help.small{opacity:.75;font-size:12px}.overview-mode-alert{align-items:center}.connect-grid{display:grid;gap:12px;padding:8px;grid-template-columns:minmax(0,1fr);align-items:start}.connect-note{grid-column:1/-1;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.connect-alert{grid-column:1/-1;align-items:center}.connect-alert__text{flex:1}.connect-alert__meta{opacity:.85}.educational-card{margin-bottom:24px;background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);flex-shrink:0}.config-editor-status{padding:12px 16px;margin-top:auto;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);flex-shrink:0;position:relative}.status-text{font-size:.875rem;line-height:1.2}.status-text.error{color:var(--md-sys-color-error)}.status-text.success{color:var(--md-sys-color-primary)}@media(max-width:768px){.tab-content{padding:8px 8px 72px}.config-editor-status{padding:12px 16px}.connect-grid{grid-template-columns:1fr}.overview-grid .overview-row{grid-template-columns:1fr;align-items:start}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}}.responsive-settings{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;min-width:0;padding:16px;border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low)}.responsive-settings__heading{display:flex;align-items:center;gap:8px}.responsive-settings h3,.responsive-settings p{margin:0}.responsive-settings h3{font-size:1rem;font-weight:600}.responsive-settings p{font-size:.875rem;line-height:1.5}.responsive-settings__hint{color:var(--md-sys-color-on-surface-variant)}.responsive-settings__error{color:var(--md-sys-color-error)}.responsive-settings mat-form-field{width:100%;min-width:0}.filters-authoring-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:16px}.toolbar-filters-toggles{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}.quick-filters-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.quick-filters-actions{display:flex;flex-wrap:wrap;gap:8px}.quick-filters-list{display:grid;gap:10px}.quick-filter-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));align-items:center;gap:8px;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}\n"] }]
|
|
73922
|
+
], template: "<div class=\"editor-section-selector\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('sections.selector', 'Editor section') }}</mat-label>\n <mat-select [(ngModel)]=\"activeSectionIndex\" data-testid=\"table-config-editor-sections\">\n @for (section of sections; track section.id; let index = $index) {\n <mat-option [value]=\"index\">{{ section.label }}</mat-option>\n }\n </mat-select>\n </mat-form-field>\n</div>\n<mat-tab-group [preserveContent]=\"true\" class=\"config-tabs\" [(selectedIndex)]=\"activeSectionIndex\">\n @for (section of sections; track section.id) {\n <mat-tab>\n <ng-template mat-tab-label>\n @if (section.icon) { <mat-icon [praxisIcon]=\"section.icon\"></mat-icon> }\n <span [attr.data-testid]=\"'config-tab-' + section.id\">{{ section.label }}</span>\n </ng-template>\n <div class=\"tab-content\">\n @switch (section.id) {\n @case ('connect') {\n <div class=\"connect-grid\">\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.resource', 'Resource') }}</mat-label>\n <input matInput [(ngModel)]=\"resourcePath\" (ngModelChange)=\"onResourcePathChange($event)\" [placeholder]=\"tx('connect.resource.placeholder', 'e.g. employees')\" />\n <mat-icon matSuffix>link</mat-icon>\n </mat-form-field>\n <mat-form-field appearance=\"outline\">\n <mat-label>{{ tx('connect.primaryKey', 'Primary key') }}</mat-label>\n <input\n matInput\n [(ngModel)]=\"idField\"\n (ngModelChange)=\"onIdFieldChange($event)\"\n [matAutocomplete]=\"idFieldPicker\"\n [placeholder]=\"tx('connect.primaryKey.placeholder', 'e.g. id, uuid, code')\"\n />\n <mat-icon matSuffix>fingerprint</mat-icon>\n <mat-autocomplete\n #idFieldPicker=\"matAutocomplete\"\n (optionSelected)=\"onIdFieldOptionSelected($event.option.value)\"\n >\n @for (option of filteredIdFieldOptions; track option.name) {\n <mat-option [value]=\"option.name\">\n <span>{{ option.name }}</span>\n @if (option.label && option.label !== option.name) {\n <small> - {{ option.label }}</small>\n }\n </mat-option>\n }\n @if (filteredIdFieldOptions.length === 0) {\n <mat-option disabled>\n {{ tx('connect.primaryKey.empty', 'No matching field found.') }}\n </mat-option>\n }\n </mat-autocomplete>\n </mat-form-field>\n <p class=\"connect-note\">{{ tx('connect.note', 'Define the API resource and, when needed, the primary key.') }}</p>\n <!-- Diverg\u00EAncia: idField -->\n @if (idFieldDiverges) { <div class=\"alert alert--warning connect-alert\">\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.serverPrimaryKeyDiverges', 'The primary key on the server differs from the current configuration.') }}\n <span class=\"connect-alert__meta\">(config: {{ idField || 'id' }} | servidor: {{ serverIdField || 'id' }})</span>\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onReconcileIdField()\">{{ tx('connect.reconcile', 'Reconcile') }}</button>\n </div> }\n <!-- Diverg\u00EAncia: serverHash -->\n @if (schemaHashDiverges) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotDiverges', 'The saved schema snapshot differs from the current server schema.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.updateMetadata', 'Update metadata') }}</button>\n </div> }\n @if (!schemaHashDiverges && schemaSnapshotMissing) { <div class=\"alert alert--info connect-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{ tx('connect.schemaSnapshotMissing', 'A current schema exists on the server, but there is still no persisted snapshot for reconciliation.') }}\n </div>\n <button mat-stroked-button color=\"primary\" type=\"button\" (click)=\"onAcceptServerHash()\">{{ tx('connect.saveSnapshot', 'Save snapshot') }}</button>\n </div> }\n </div>\n }\n @case ('overview') {\n <div class=\"overview-grid\">\n <section class=\"responsive-settings\" aria-labelledby=\"table-responsive-title\">\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">devices</mat-icon>\n <h3 id=\"table-responsive-title\">{{ tx('overview.responsive.title', 'Narrow screens') }}</h3>\n </div>\n <p>{{ tx('overview.responsive.description', 'Choose how records appear when the table has less space.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.mode', 'Record layout') }}</mat-label>\n <mat-select [ngModel]=\"mobileCardMode\" (ngModelChange)=\"onMobileCardModeChange($event)\">\n <mat-option [value]=\"false\">{{ tx('overview.responsive.table', 'Table') }}</mat-option>\n <mat-option [value]=\"true\">{{ tx('overview.responsive.cards', 'Cards') }}</mat-option>\n </mat-select>\n </mat-form-field>\n @if (mobileCardMode) {\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.cardsHint', 'Each record becomes a card with its visible columns. Selection and row actions remain available. Wider areas keep the table layout.') }}</p>\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('overview.responsive.breakpoint', 'Show cards at widths up to') }}</mat-label>\n <input matInput type=\"number\" min=\"1\" step=\"1\" required\n [ngModel]=\"mobileBreakpoint\" (ngModelChange)=\"onMobileBreakpointChange($event)\"\n [attr.aria-invalid]=\"mobileBreakpointInvalid\"\n aria-describedby=\"table-responsive-width-help\" />\n <span matTextSuffix>px</span>\n </mat-form-field>\n @if (mobileBreakpointInvalid) {\n <p class=\"responsive-settings__error\" role=\"alert\">{{ tx('overview.responsive.invalidWidth', 'Enter a positive whole number.') }}</p>\n }\n <p id=\"table-responsive-width-help\" class=\"responsive-settings__hint\">{{ tx('overview.responsive.widthHint', 'Uses the smaller width of the screen and the table area. Default: 768 px.') }}</p>\n <p class=\"responsive-settings__hint\">{{ tx('overview.responsive.virtualizationHint', 'Cards require standard rows. With virtual scrolling enabled, records remain in a table.') }}</p>\n }\n </section>\n <div class=\"overview-row\">\n <mat-form-field appearance=\"outline\" class=\"hs-field\">\n <mat-label>{{ tx('overview.horizontalScroll', 'Horizontal scroll') }}</mat-label>\n <mat-select [(ngModel)]=\"horizontalScroll\" (ngModelChange)=\"onHorizontalScrollChange($event)\">\n <mat-option value=\"auto\">{{ tx('overview.horizontalScroll.auto', 'Auto (default)') }}</mat-option>\n <mat-option value=\"wrap\">{{ tx('overview.horizontalScroll.wrap', 'Wrap') }}</mat-option>\n <mat-option value=\"none\">{{ tx('overview.horizontalScroll.none', 'Host controls') }}</mat-option>\n </mat-select>\n </mat-form-field>\n <div class=\"help small\">{{ tx('overview.horizontalScroll.help', 'Controls how the table handles horizontal width and scrollbar behavior.') }}</div>\n </div>\n @if (isEffectiveLocalMode()) { <div class=\"alert alert--info overview-mode-alert\">\n <mat-icon class=\"alert__icon\">info</mat-icon>\n <div class=\"alert__text\">\n {{ tx('overview.localModeActive', 'Effective local mode is active: server pagination and sorting strategies are blocked and persisted as client mode.') }}\n </div>\n </div> }\n <behavior-config-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n [forceClientStrategies]=\"isEffectiveLocalMode()\"\n (configChange)=\"onBehaviorConfigChange($event)\"\n (behaviorChange)=\"onBehaviorChange($event)\"\n ></behavior-config-editor>\n </div>\n }\n @case ('columns') {\n <columns-config-editor\n [config]=\"editedConfig\"\n [fieldMetadata]=\"getColumnAuthoringMetas()\"\n (configChange)=\"onColumnsConfigChange($event)\"\n (columnChange)=\"onColumnChange($event)\"\n ></columns-config-editor>\n }\n @case ('detail') {\n <praxis-table-detail-editor [config]=\"editedConfig\"\n (configChange)=\"onDetailConfigChange($event)\"\n (draftStateChange)=\"onDetailDraftStateChange($event)\"\n ></praxis-table-detail-editor>\n }\n @case ('rules') {\n <table-rules-editor\n [config]=\"editedConfig\"\n [resourcePath]=\"resourcePath\"\n (configChange)=\"onRulesConfigChange($event)\"\n ></table-rules-editor>\n }\n @case ('header') {\n <header-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onColumnsConfigChange($event)\"\n ></header-appearance-editor>\n }\n @case ('toolbar') {\n <toolbar-actions-editor\n [config]=\"editedConfig\"\n (configChange)=\"onToolbarActionsConfigChange($event)\"\n (toolbarActionsChange)=\"onToolbarActionsChange($event)\"\n (validationChange)=\"onSurfaceDraftValidationChange($event)\"\n ></toolbar-actions-editor>\n }\n <!-- Aba extra para integra\u00E7\u00F5es CRUD (vis\u00EDvel quando em contexto CRUD) -->\n @case ('crud') {\n <crud-integration-editor\n #crudEditorRef\n [tableId]=\"crudContext?.tableId || 'default'\"\n [crudContext]=\"crudContext\"\n [componentKeyId]=\"crudContext?.componentKeyId\"\n ></crud-integration-editor>\n }\n @case ('filters') {\n <div class=\"filters-authoring-stack\">\n <section\n class=\"responsive-settings toolbar-filters-region\"\n data-testid=\"table-unified-filter-region-section\"\n aria-labelledby=\"table-unified-filter-region-title\"\n >\n <div class=\"responsive-settings__heading\">\n <mat-icon aria-hidden=\"true\">filter_list</mat-icon>\n <h3 id=\"table-unified-filter-region-title\">\n {{ tx('filters.region.title', 'Regi\u00E3o \u00FAnica de filtros e escopos da toolbar') }}\n </h3>\n </div>\n <p class=\"responsive-settings__hint\">\n {{\n tx(\n 'filters.region.description',\n 'Centralize escopos r\u00E1pidos (Todos / Ativos / Inativos), busca e gaveta avan\u00E7ada na toolbar da tabela sem controles duplicados.'\n )\n }}\n </p>\n\n <div class=\"toolbar-filters-toggles\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.enabled', 'Regi\u00E3o de filtros na toolbar') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarFiltersEnabled\"\n (ngModelChange)=\"onToolbarFiltersEnabledChange($event)\"\n data-testid=\"table-toolbar-filters-enabled-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.enabled', 'Ativada') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.disabled', 'Desativada') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showQuickFilters', 'Exibir escopos r\u00E1pidos') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowQuickFilters\"\n (ngModelChange)=\"onToolbarShowQuickFiltersChange($event)\"\n data-testid=\"table-toolbar-show-quick-filters-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAdvancedButton', 'Bot\u00E3o de gaveta avan\u00E7ada') }}</mat-label>\n <mat-select\n [ngModel]=\"toolbarShowAdvancedButton\"\n (ngModelChange)=\"onToolbarShowAdvancedButtonChange($event)\"\n data-testid=\"table-toolbar-show-advanced-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showAddButton', 'Bot\u00E3o \"Gerenciar campos\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowAddButton\"\n (ngModelChange)=\"onAdvancedFilterShowAddButtonChange($event)\"\n data-testid=\"table-toolbar-show-add-button-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.region.showFilterSettings', 'Bot\u00E3o \"Configura\u00E7\u00F5es do filtro\"') }}</mat-label>\n <mat-select\n [ngModel]=\"advancedFilterShowFilterSettings\"\n (ngModelChange)=\"onAdvancedFilterShowFilterSettingsChange($event)\"\n data-testid=\"table-toolbar-show-filter-settings-select\"\n >\n <mat-option [value]=\"true\">{{ tx('common.yes', 'Sim') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.no', 'N\u00E3o') }}</mat-option>\n </mat-select>\n </mat-form-field>\n </div>\n\n @if (duplicatedQuickFilterInlineFields.length > 0) {\n <div\n class=\"alert alert--warning connect-alert\"\n data-testid=\"table-filter-duplicate-scope-warning\"\n >\n <mat-icon class=\"alert__icon\">warning</mat-icon>\n <div class=\"alert__text connect-alert__text\">\n {{\n tx(\n 'filters.region.duplicateWarning',\n 'Os campos abaixo j\u00E1 possuem escopos r\u00E1pidos na toolbar e tamb\u00E9m est\u00E3o nos filtros inline:'\n )\n }}\n <strong>{{ duplicatedQuickFilterInlineFields.join(', ') }}</strong>\n </div>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-filter-consolidate-duplicates-btn\"\n (click)=\"consolidateDuplicateInlineFilterFields()\"\n >\n {{ tx('filters.region.consolidateBtn', 'Consolidar nos escopos r\u00E1pidos') }}\n </button>\n </div>\n }\n\n <div class=\"quick-filters-header\">\n <strong>{{ tx('filters.quickFilters.heading', 'Escopos r\u00E1pidos (quickFilters)') }}</strong>\n <div class=\"quick-filters-actions\">\n <button\n mat-stroked-button\n type=\"button\"\n data-testid=\"table-quick-filters-preset-boolean-btn\"\n (click)=\"applyBooleanQuickFilterPreset()\"\n >\n {{ tx('filters.quickFilters.presetBoolean', 'Preset Todos / Ativos / Inativos') }}\n </button>\n <button\n mat-stroked-button\n color=\"primary\"\n type=\"button\"\n data-testid=\"table-quick-filters-add-btn\"\n (click)=\"addQuickFilterScope()\"\n >\n {{ tx('filters.quickFilters.add', 'Adicionar escopo') }}\n </button>\n </div>\n </div>\n\n @if (toolbarQuickFilters.length > 0) {\n <div class=\"quick-filters-list\" data-testid=\"table-quick-filters-list\">\n @for (qf of toolbarQuickFilters; track $index; let idx = $index) {\n <div class=\"quick-filter-row\" [attr.data-testid]=\"'table-quick-filter-row-' + idx\">\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.id', 'ID') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.id\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { id: $event })\"\n [attr.data-testid]=\"'table-quick-filter-id-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.label', 'R\u00F3tulo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"qf.label\"\n (ngModelChange)=\"updateQuickFilterMeta(idx, { label: $event })\"\n [attr.data-testid]=\"'table-quick-filter-label-' + idx\"\n />\n </mat-form-field>\n\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.mode', 'Tipo de escopo') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterMode(qf)\"\n (ngModelChange)=\"onQuickFilterModeChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-mode-' + idx\"\n >\n <mat-option value=\"all\">{{ tx('filters.quickFilters.mode.all', 'Todos (limpar filtro)') }}</mat-option>\n <mat-option value=\"boolean\">{{ tx('filters.quickFilters.mode.boolean', 'Status booleano (Sim/N\u00E3o)') }}</mat-option>\n <mat-option value=\"equals\">{{ tx('filters.quickFilters.mode.equals', 'Campo igual a valor') }}</mat-option>\n </mat-select>\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) !== 'all') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.field', 'Campo') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterField(qf)\"\n (ngModelChange)=\"onQuickFilterFieldChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-field-' + idx\"\n />\n </mat-form-field>\n\n @if (getQuickFilterMode(qf) === 'boolean') {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <mat-select\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-bool-value-' + idx\"\n >\n <mat-option [value]=\"true\">{{ tx('common.boolean.true', 'Verdadeiro (true)') }}</mat-option>\n <mat-option [value]=\"false\">{{ tx('common.boolean.false', 'Falso (false)') }}</mat-option>\n </mat-select>\n </mat-form-field>\n } @else {\n <mat-form-field appearance=\"outline\" subscriptSizing=\"dynamic\">\n <mat-label>{{ tx('filters.quickFilters.value', 'Valor') }}</mat-label>\n <input\n matInput\n [ngModel]=\"getQuickFilterValue(qf)\"\n (ngModelChange)=\"onQuickFilterValueChange(idx, $event)\"\n [attr.data-testid]=\"'table-quick-filter-value-' + idx\"\n />\n </mat-form-field>\n }\n }\n\n <button\n mat-stroked-button\n color=\"warn\"\n type=\"button\"\n [attr.data-testid]=\"'table-quick-filter-remove-' + idx\"\n (click)=\"removeQuickFilterScope(idx)\"\n >\n {{ tx('common.remove', 'Remover') }}\n </button>\n </div>\n }\n </div>\n }\n </section>\n\n <filter-settings\n #tableFilterSettingsRef\n [metadata]=\"getFilterSettingsMetas()\"\n [metadataSource]=\"isUsingFilterDtoMetas() ? 'filter-dto' : 'columns'\"\n [metadataLoading]=\"filterDtoMetasLoading\"\n [metadataErrorMsg]=\"filterDtoMetasErrorMsg\"\n [settings]=\"\n editedConfig.behavior?.filtering?.advancedFilters?.settings\n \"\n (settingsChange)=\"onFilterSettingsChange($event)\"\n ></filter-settings>\n </div>\n }\n @case ('messages') {\n <messages-localization-editor\n [config]=\"editedConfig\"\n (configChange)=\"onMessagesLocalizationConfigChange($event)\"\n (messagesLocalizationChange)=\"\n onMessagesLocalizationChange($event)\n \"\n ></messages-localization-editor>\n }\n @case ('dialogs') {\n <confirm-dialog-appearance-editor\n [config]=\"editedConfig\"\n (configChange)=\"onJsonConfigChange($event)\"\n ></confirm-dialog-appearance-editor>\n }\n @case ('json') {\n <json-config-editor\n [document]=\"buildJsonAuthoringDocument()\"\n (documentChange)=\"onJsonConfigChange($event)\"\n (validationChange)=\"onJsonValidationChange($event)\"\n (editorEvent)=\"onJsonEditorEvent($event)\"\n ></json-config-editor>\n }\n }\n </div>\n </mat-tab>\n }\n</mat-tab-group>\n@if (statusMessage) { <div class=\"config-editor-status\">\n <span\n class=\"status-text\"\n [class.error]=\"hasErrors\"\n [class.success]=\"hasSuccess\"\n >{{ statusMessage }}</span\n >\n</div> }\n", styles: ["@charset \"UTF-8\";:host{display:block;min-width:0;container:praxis-authoring-editor/inline-size}.editor-section-selector{display:block;padding:var(--pfx-spacing-2, 8px)}.editor-section-selector mat-form-field{width:100%}@container praxis-authoring-editor (max-width: 768px){.editor-section-selector{display:block}::ng-deep .config-tabs>.mat-mdc-tab-header{display:none}}.config-tabs{flex:1 1 auto;display:flex;flex-direction:column}.config-tabs .mat-mdc-tab{min-width:120px}.config-tabs .mat-mdc-tab-body-wrapper,.config-tabs .mat-mdc-tab-group-container{flex:1 1 auto;min-height:0}.config-tabs .mat-mdc-tab-body-content{height:100%;min-height:0;overflow:visible}.tab-content{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;padding:8px 8px 56px;box-sizing:border-box;overflow:visible}.overview-grid{display:grid;min-width:0;grid-template-columns:minmax(0,1fr);gap:12px}.overview-grid .overview-row{display:grid;grid-template-columns:280px 1fr;align-items:end;gap:12px}.overview-grid .overview-row .help.small{opacity:.75;font-size:12px}.overview-mode-alert{align-items:center}.connect-grid{display:grid;gap:12px;padding:8px;grid-template-columns:minmax(0,1fr);align-items:start}.connect-note{grid-column:1/-1;margin:0;font-size:12px;color:var(--md-sys-color-on-surface-variant)}.connect-alert{grid-column:1/-1;align-items:center}.connect-alert__text{flex:1}.connect-alert__meta{opacity:.85}.educational-card{margin-bottom:24px;background:var(--md-sys-color-surface-container-low);border-left:4px solid var(--md-sys-color-primary);flex-shrink:0}.config-editor-status{padding:12px 16px;margin-top:auto;border-top:1px solid var(--md-sys-color-outline-variant);background:var(--md-sys-color-surface-container);flex-shrink:0;position:relative}.status-text{font-size:.875rem;line-height:1.2}.status-text.error{color:var(--md-sys-color-error)}.status-text.success{color:var(--md-sys-color-primary)}@media(max-width:768px){.tab-content{padding:8px 8px 72px}.config-editor-status{padding:12px 16px}.connect-grid{grid-template-columns:1fr}.overview-grid .overview-row{grid-template-columns:1fr;align-items:start}:host{display:flex;flex-direction:column;flex:1 1 auto;min-height:0}}.responsive-settings{display:grid;grid-template-columns:minmax(0,1fr);gap:12px;min-width:0;padding:16px;border:1px solid var(--md-sys-color-outline-variant);border-radius:var(--md-sys-shape-corner-medium, 12px);background:var(--md-sys-color-surface-container-low)}.responsive-settings__heading{display:flex;align-items:center;gap:8px}.responsive-settings h3,.responsive-settings p{margin:0}.responsive-settings h3{font-size:1rem;font-weight:600}.responsive-settings p{font-size:.875rem;line-height:1.5}.responsive-settings__hint{color:var(--md-sys-color-on-surface-variant)}.responsive-settings__error{color:var(--md-sys-color-error)}.responsive-settings mat-form-field{width:100%;min-width:0}.filters-authoring-stack{display:grid;grid-template-columns:minmax(0,1fr);gap:16px}.toolbar-filters-toggles{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:12px}.quick-filters-header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.quick-filters-actions{display:flex;flex-wrap:wrap;gap:8px}.quick-filters-list{display:grid;gap:10px}.quick-filter-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));align-items:center;gap:8px;padding:10px;border:1px solid var(--md-sys-color-outline-variant);border-radius:8px;background:var(--md-sys-color-surface)}\n"] }]
|
|
73717
73923
|
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.TableConfigService }], propDecorators: { filterSettingsEditor: [{
|
|
73718
73924
|
type: ViewChild,
|
|
73719
73925
|
args: ['tableFilterSettingsRef']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Observable, firstValueFrom } from 'rxjs';
|
|
2
2
|
import { withAuthoringScopePolicy } from '@praxisui/ai';
|
|
3
|
-
import { ar as setTableActionGlobalActionRef } from './praxisui-table-praxisui-table-
|
|
3
|
+
import { ar as setTableActionGlobalActionRef } from './praxisui-table-praxisui-table-CWOg6JDN.mjs';
|
|
4
4
|
|
|
5
5
|
class TableAgenticAuthoringTurnFlow {
|
|
6
6
|
adapter;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { firstValueFrom } from 'rxjs';
|
|
2
2
|
import { BaseAiAdapter, sanitizePraxisAssistantText, createComponentAuthoringContext } from '@praxisui/ai';
|
|
3
3
|
import { PRAXIS_GLOBAL_ACTION_CATALOG, deepMerge } from '@praxisui/core';
|
|
4
|
-
import { W as TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS, p as PRAXIS_TABLE_AUTHORING_MANIFEST, T as TABLE_AI_CAPABILITIES, a6 as coerceTableComponentEditPlans, a8 as compileTableComponentEditPlans, Y as TASK_PRESETS, ae as getTableComponentEditPlanCapabilities, R as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, O as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, U as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, X as TABLE_COMPONENT_EDIT_PLAN_VERSION, Q as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, V as TABLE_COMPONENT_EDIT_PLAN_KIND } from './praxisui-table-praxisui-table-
|
|
4
|
+
import { W as TABLE_COMPONENT_EDIT_PLAN_OPERATION_IDS, p as PRAXIS_TABLE_AUTHORING_MANIFEST, T as TABLE_AI_CAPABILITIES, a6 as coerceTableComponentEditPlans, a8 as compileTableComponentEditPlans, Y as TASK_PRESETS, ae as getTableComponentEditPlanCapabilities, R as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, O as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, U as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, X as TABLE_COMPONENT_EDIT_PLAN_VERSION, Q as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, V as TABLE_COMPONENT_EDIT_PLAN_KIND } from './praxisui-table-praxisui-table-CWOg6JDN.mjs';
|
|
5
5
|
|
|
6
6
|
const TABLE_ROW_EXPRESSION_CONTEXT_OPTION = {
|
|
7
7
|
mode: 'expression',
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { A as ANALYTICS_TABLE_ROW_KEY_FIELD, a as AnalyticalDrawerRegistryService, b as AnalyticsTableConfigAdapterService, c as AnalyticsTableContractService, d as AnalyticsTableStatsApiService, B as BOOLEAN_PRESETS, e as BehaviorConfigEditorComponent, C as CURRENCY_PRESETS, f as ColumnsConfigEditorComponent, D as DATE_PRESETS, g as DataFormatterComponent, h as DataFormattingService, F as FORMULA_TEMPLATES, i as FilterConfigService, j as FilterSettingsComponent, k as FormulaGeneratorService, J as JsonConfigEditorComponent, M as MessagesLocalizationEditorComponent, N as NUMBER_PRESETS, P as PERCENTAGE_PRESETS, l as PRAXIS_ANALYTICAL_DRAWER_SCHEMAS, m as PRAXIS_FILTER_AUTHORING_MANIFEST, n as PRAXIS_FILTER_COMPONENT_METADATA, o as PRAXIS_FILTER_VIEW_CONTEXT_SCHEMA_VERSION, p as PRAXIS_TABLE_AUTHORING_MANIFEST, q as PRAXIS_TABLE_COMPONENT_METADATA, r as PRAXIS_TABLE_TOOLBAR_APPEARANCE_PRESETS, s as PRAXIS_TABLE_TOOLBAR_DEFAULT_APPEARANCE, t as PRAXIS_TABLE_TOOLBAR_TOKEN_PRESETS, u as PraxisAnalyticalDrawerComponent, v as PraxisFilter, w as PraxisFilterOutletComponent, x as PraxisFilterOutletDirective, y as PraxisFilterWidgetConfigEditor, z as PraxisScopeBarComponent, E as PraxisTable, G as PraxisTableConfigEditor, H as PraxisTableInlineAuthoringEditorComponent, I as PraxisTableToolbar, K as PraxisTableWidgetConfigEditor, S as STRING_PRESETS, T as TABLE_AI_CAPABILITIES, L as TABLE_COMPONENT_AI_CAPABILITIES, O as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, Q as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, R as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, U as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, V as TABLE_COMPONENT_EDIT_PLAN_KIND, X as TABLE_COMPONENT_EDIT_PLAN_VERSION, Y as TASK_PRESETS, Z as TableDefaultsProvider, _ as TableRulesEditorComponent, $ as ToolbarActionsEditorComponent, a0 as ValueMappingEditorComponent, a1 as VisualFormulaBuilderComponent, a2 as analyticsComparisonMetricField, a3 as applyComputedFieldsToRows, a4 as buildTableApplyPlan, a5 as coerceTableComponentEditPlan, a6 as coerceTableComponentEditPlans, a7 as compileTableComponentEditPlan, a8 as compileTableComponentEditPlans, a9 as createTableAuthoringDocument, aa as formatComputedFieldValue, ab as getActionId, ac as getEnum, ad as getTableCapabilities, ae as getTableComponentEditPlanCapabilities, af as interpolateRelationEndpoint, ag as isAnalyticalDrawerSchema, ah as isTableRendererSupportedByRichContentP0, ai as mapTableRendererToRichContentP0, aj as normalizeComputedFieldDefinition, ak as normalizeTableAuthoringDocument, al as parseLegacyOrTableDocument, am as providePraxisAnalyticalDrawerSchemas, an as providePraxisFilterMetadata, ao as providePraxisTableMetadata, ap as providePraxisTableToolbarAppearance, aq as serializeTableAuthoringDocument, as as toCanonicalTableConfig, at as validateTableAuthoringDocument } from './praxisui-table-praxisui-table-
|
|
1
|
+
export { A as ANALYTICS_TABLE_ROW_KEY_FIELD, a as AnalyticalDrawerRegistryService, b as AnalyticsTableConfigAdapterService, c as AnalyticsTableContractService, d as AnalyticsTableStatsApiService, B as BOOLEAN_PRESETS, e as BehaviorConfigEditorComponent, C as CURRENCY_PRESETS, f as ColumnsConfigEditorComponent, D as DATE_PRESETS, g as DataFormatterComponent, h as DataFormattingService, F as FORMULA_TEMPLATES, i as FilterConfigService, j as FilterSettingsComponent, k as FormulaGeneratorService, J as JsonConfigEditorComponent, M as MessagesLocalizationEditorComponent, N as NUMBER_PRESETS, P as PERCENTAGE_PRESETS, l as PRAXIS_ANALYTICAL_DRAWER_SCHEMAS, m as PRAXIS_FILTER_AUTHORING_MANIFEST, n as PRAXIS_FILTER_COMPONENT_METADATA, o as PRAXIS_FILTER_VIEW_CONTEXT_SCHEMA_VERSION, p as PRAXIS_TABLE_AUTHORING_MANIFEST, q as PRAXIS_TABLE_COMPONENT_METADATA, r as PRAXIS_TABLE_TOOLBAR_APPEARANCE_PRESETS, s as PRAXIS_TABLE_TOOLBAR_DEFAULT_APPEARANCE, t as PRAXIS_TABLE_TOOLBAR_TOKEN_PRESETS, u as PraxisAnalyticalDrawerComponent, v as PraxisFilter, w as PraxisFilterOutletComponent, x as PraxisFilterOutletDirective, y as PraxisFilterWidgetConfigEditor, z as PraxisScopeBarComponent, E as PraxisTable, G as PraxisTableConfigEditor, H as PraxisTableInlineAuthoringEditorComponent, I as PraxisTableToolbar, K as PraxisTableWidgetConfigEditor, S as STRING_PRESETS, T as TABLE_AI_CAPABILITIES, L as TABLE_COMPONENT_AI_CAPABILITIES, O as TABLE_COMPONENT_EDIT_PLAN_ALLOWED_CHANGE_KINDS, Q as TABLE_COMPONENT_EDIT_PLAN_BATCH_KIND, R as TABLE_COMPONENT_EDIT_PLAN_EXPECTED_PATHS, U as TABLE_COMPONENT_EDIT_PLAN_JSON_SCHEMA, V as TABLE_COMPONENT_EDIT_PLAN_KIND, X as TABLE_COMPONENT_EDIT_PLAN_VERSION, Y as TASK_PRESETS, Z as TableDefaultsProvider, _ as TableRulesEditorComponent, $ as ToolbarActionsEditorComponent, a0 as ValueMappingEditorComponent, a1 as VisualFormulaBuilderComponent, a2 as analyticsComparisonMetricField, a3 as applyComputedFieldsToRows, a4 as buildTableApplyPlan, a5 as coerceTableComponentEditPlan, a6 as coerceTableComponentEditPlans, a7 as compileTableComponentEditPlan, a8 as compileTableComponentEditPlans, a9 as createTableAuthoringDocument, aa as formatComputedFieldValue, ab as getActionId, ac as getEnum, ad as getTableCapabilities, ae as getTableComponentEditPlanCapabilities, af as interpolateRelationEndpoint, ag as isAnalyticalDrawerSchema, ah as isTableRendererSupportedByRichContentP0, ai as mapTableRendererToRichContentP0, aj as normalizeComputedFieldDefinition, ak as normalizeTableAuthoringDocument, al as parseLegacyOrTableDocument, am as providePraxisAnalyticalDrawerSchemas, an as providePraxisFilterMetadata, ao as providePraxisTableMetadata, ap as providePraxisTableToolbarAppearance, aq as serializeTableAuthoringDocument, as as toCanonicalTableConfig, at as validateTableAuthoringDocument } from './praxisui-table-praxisui-table-CWOg6JDN.mjs';
|
|
2
2
|
export { createDynamicRecord, extractRecordId, isDynamicDataRecord, resolveDataField } from '@praxisui/core';
|
package/package.json
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@praxisui/table",
|
|
3
|
-
"version": "10.0.0-rc.
|
|
3
|
+
"version": "10.0.0-rc.32",
|
|
4
4
|
"description": "Advanced data table for Angular (Praxis UI) with editing, filtering, sorting, virtualization, and settings panel integration.",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^21.0.0",
|
|
7
7
|
"@angular/core": "^21.0.0",
|
|
8
8
|
"@angular/platform-browser": "^21.0.0",
|
|
9
|
-
"@praxisui/ai": "^10.0.0-rc.
|
|
10
|
-
"@praxisui/core": "^10.0.0-rc.
|
|
11
|
-
"@praxisui/dynamic-fields": "^10.0.0-rc.
|
|
12
|
-
"@praxisui/dynamic-form": "^10.0.0-rc.
|
|
13
|
-
"@praxisui/metadata-editor": "^10.0.0-rc.
|
|
14
|
-
"@praxisui/rich-content": "^10.0.0-rc.
|
|
15
|
-
"@praxisui/settings-panel": "^10.0.0-rc.
|
|
16
|
-
"@praxisui/table-rule-builder": "^10.0.0-rc.
|
|
9
|
+
"@praxisui/ai": "^10.0.0-rc.32",
|
|
10
|
+
"@praxisui/core": "^10.0.0-rc.32",
|
|
11
|
+
"@praxisui/dynamic-fields": "^10.0.0-rc.32",
|
|
12
|
+
"@praxisui/dynamic-form": "^10.0.0-rc.32",
|
|
13
|
+
"@praxisui/metadata-editor": "^10.0.0-rc.32",
|
|
14
|
+
"@praxisui/rich-content": "^10.0.0-rc.32",
|
|
15
|
+
"@praxisui/settings-panel": "^10.0.0-rc.32",
|
|
16
|
+
"@praxisui/table-rule-builder": "^10.0.0-rc.32",
|
|
17
17
|
"@angular/cdk": "^21.0.0",
|
|
18
18
|
"@angular/forms": "^21.0.0",
|
|
19
19
|
"@angular/material": "^21.0.0",
|
|
20
20
|
"@angular/router": "^21.0.0",
|
|
21
|
-
"@praxisui/dialog": "^10.0.0-rc.
|
|
21
|
+
"@praxisui/dialog": "^10.0.0-rc.32",
|
|
22
22
|
"rxjs": "~7.8.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, AfterViewInit, OnDestroy, EventEmitter, ElementRef, Provider, OnInit, OnChanges, DoCheck, DestroyRef, ChangeDetectorRef, NgZone, SimpleChanges, ComponentRef, AfterViewChecked, AfterContentInit, TemplateRef, Injector, Type } from '@angular/core';
|
|
3
1
|
import * as _praxisui_core from '@praxisui/core';
|
|
4
|
-
import { BulkExecutionContract, ResourceDiscoveryRequestOptions, BulkWireId, RestApiLinks, BulkSyncSession, BulkFieldChange, TableToolbarAppearanceConfig, TableConfig, TableToolbarAppearanceDensity, ToolbarActionEvent, PraxisExportScope, LoggerService, PraxisI18nService, TableToolbarAppearanceVariant, TableToolbarAppearanceShape, TableToolbarAppearanceDivider, TableToolbarTokenName, ToolbarAction as ToolbarAction$1, GlobalConfigService, FilterPresentationConfig, AsyncConfigStorage, LocalStorageConfigService, ApiUrlEntry, FieldMetadata, SchemaIdParams, FormConfig, GenericCrudService, DynamicFormService, SchemaNormalizerService, ComponentKeyService, ComponentDocMeta, PraxisTextValue, PraxisAnalyticsProjection, PraxisDataQueryContext, ApiUrlConfig, DynamicDataRecord, MaterializedResourceIdentity, PraxisQueryFilterExpression, RecordRelatedSurfaceContextPack, PraxisResourceEvent, LoadingState, ColumnDefinition, RichBlockNode, ResourceCapabilityDigest, ConnectionStorage, LoadingOrchestrator, GlobalActionService, EnterpriseRuntimeContextService, PraxisLoadingRenderer, PraxisRuntimeComponentObservationEnvelope, TableDetailRichListNode, TableDetailListNode, TableDetailCardGridNode, TableDetailCardGridCardNode, TableDetailTimelineNode, JsonLogicDataRecord, TableDetailListItemAction, TableDetailActionBarNode, TableDetailActionBarAction, TableDetailRefNode, TableDetailTemplateRefNode, TableDetailDiagramEmbedNode, TableDetailEmbedAction, RichContentDocument, RichBlockHostCapabilities, GlobalActionRef, PraxisRuntimeGlobalActionEffect, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, ResourceCapabilityOperation, JsonLogicExpression, PraxisPresentationVisualizationKind, PraxisTableCellVisualizationConstraint, PraxisPresentationVisualizationThreshold, PraxisPresentationVisualizationTone, GlobalActionCatalogEntry, IconPickerService, SurfaceOpenPayload, GlobalActionField, FieldDefinition, PraxisRuntimeConditionalEffectRule, PraxisJsonLogicService, TableConfigService, SettingsValueProvider as SettingsValueProvider$1, ResourceQuickConnectComponent, AnalyticsSchemaContractService, AnalyticsPresentationResolver, RichPresenterNode, RichComposeNode, ComponentAuthoringManifest, AiCapability, AiCapabilityCategory, AiValueKind, AiCapabilityCatalog, TableDrawerConfig, PraxisAnalyticalDrawerTab, PraxisPresentationVisualizationConfig, PraxisAnalyticalDrawerSchema, SafeExpressionEvaluator, PraxisComputedFieldsConfig, PraxisComputedFieldDefinition } from '@praxisui/core';
|
|
2
|
+
import { BulkExecutionContract, ResourceDiscoveryRequestOptions, BulkWireId, RestApiLinks, BulkSyncSession, BulkFieldChange, TableToolbarAppearanceConfig, TableConfig, TableToolbarAppearanceDensity, ToolbarActionEvent, PraxisExportScope, LoggerService, PraxisI18nService, TableToolbarAppearanceVariant, TableToolbarAppearanceShape, TableToolbarAppearanceDivider, TableToolbarTokenName, ToolbarAction as ToolbarAction$1, GlobalConfigService, FilterPresentationConfig, AsyncConfigStorage, LocalStorageConfigService, ApiUrlEntry, FieldMetadata, SchemaIdParams, FormConfig, GenericCrudService, DynamicFormService, SchemaNormalizerService, ComponentKeyService, ComponentDocMeta, PraxisTextValue, PraxisAnalyticsProjection, PraxisDataQueryContext, ApiUrlConfig, DynamicDataRecord, MaterializedResourceIdentity, TableConfigInput, PraxisQueryFilterExpression, RecordRelatedSurfaceContextPack, PraxisResourceEvent, LoadingState, ColumnDefinition, RichBlockNode, ResourceCapabilityDigest, ConnectionStorage, LoadingOrchestrator, GlobalActionService, EnterpriseRuntimeContextService, PraxisLoadingRenderer, PraxisRuntimeComponentObservationEnvelope, TableDetailRichListNode, TableDetailListNode, TableDetailCardGridNode, TableDetailCardGridCardNode, TableDetailTimelineNode, JsonLogicDataRecord, TableDetailListItemAction, TableDetailActionBarNode, TableDetailActionBarAction, TableDetailRefNode, TableDetailTemplateRefNode, TableDetailDiagramEmbedNode, TableDetailEmbedAction, RichContentDocument, RichBlockHostCapabilities, GlobalActionRef, PraxisRuntimeGlobalActionEffect, ResourceActionCatalogItem, ResourceSurfaceCatalogItem, ResourceCapabilityOperation, JsonLogicExpression, PraxisPresentationVisualizationKind, PraxisTableCellVisualizationConstraint, PraxisPresentationVisualizationThreshold, PraxisPresentationVisualizationTone, GlobalActionCatalogEntry, IconPickerService, SurfaceOpenPayload, GlobalActionField, FieldDefinition, PraxisRuntimeConditionalEffectRule, PraxisJsonLogicService, TableConfigService, SettingsValueProvider as SettingsValueProvider$1, ResourceQuickConnectComponent, AnalyticsSchemaContractService, AnalyticsPresentationResolver, RichPresenterNode, RichComposeNode, ComponentAuthoringManifest, AiCapability, AiCapabilityCategory, AiValueKind, AiCapabilityCatalog, TableDrawerConfig, PraxisAnalyticalDrawerTab, PraxisPresentationVisualizationConfig, PraxisAnalyticalDrawerSchema, SafeExpressionEvaluator, PraxisComputedFieldsConfig, PraxisComputedFieldDefinition } from '@praxisui/core';
|
|
5
3
|
export { DynamicDataCollection, DynamicDataRecord, DynamicRecordMeta, ResourceLinkItem, ResourceLinks, createDynamicRecord, extractRecordId, isDynamicDataRecord, resolveDataField } from '@praxisui/core';
|
|
4
|
+
import * as i0 from '@angular/core';
|
|
5
|
+
import { InjectionToken, AfterViewInit, OnDestroy, EventEmitter, ElementRef, Provider, OnInit, OnChanges, DoCheck, DestroyRef, ChangeDetectorRef, NgZone, SimpleChanges, ComponentRef, AfterViewChecked, AfterContentInit, TemplateRef, Injector, Type } from '@angular/core';
|
|
6
6
|
import { ActivatedRoute } from '@angular/router';
|
|
7
7
|
import { SafeHtml } from '@angular/platform-browser';
|
|
8
8
|
import { MatTable, MatTableDataSource } from '@angular/material/table';
|
|
@@ -454,6 +454,7 @@ declare class TableDefaultsProvider {
|
|
|
454
454
|
constructor(global: GlobalConfigService);
|
|
455
455
|
/**
|
|
456
456
|
* Returns default configuration for a given table identifier.
|
|
457
|
+
* Precedence inside defaults: GlobalConfig.table > createDefaultTableConfig().
|
|
457
458
|
* @param tableId Table identifier
|
|
458
459
|
*/
|
|
459
460
|
getDefaults(_tableId: string): TableConfig;
|
|
@@ -1428,7 +1429,10 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterView
|
|
|
1428
1429
|
readonly paginatorSelectConfig: MatPaginatorSelectConfig;
|
|
1429
1430
|
private static readonly ROW_ANIMATION_PRESETS;
|
|
1430
1431
|
private static readonly ROW_ANIMATION_PRESET_ALIASES;
|
|
1432
|
+
static ngAcceptInputType_config: TableConfigInput;
|
|
1431
1433
|
config: TableConfig;
|
|
1434
|
+
private hostInputConfig?;
|
|
1435
|
+
private persistedUserConfig?;
|
|
1432
1436
|
resourcePath: string;
|
|
1433
1437
|
data: any[] | null;
|
|
1434
1438
|
tableId: string;
|
|
@@ -1443,9 +1447,15 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterView
|
|
|
1443
1447
|
autoOpenSettingsOnOutdated: boolean;
|
|
1444
1448
|
crudContext: any;
|
|
1445
1449
|
filterCriteria: Record<string, any>;
|
|
1446
|
-
|
|
1450
|
+
readonly filterCriteriaChange: EventEmitter<Record<string, any>>;
|
|
1451
|
+
private _filterTeleport;
|
|
1452
|
+
set filterTeleport(value: boolean);
|
|
1453
|
+
get filterTeleport(): boolean;
|
|
1447
1454
|
widgetId?: string;
|
|
1448
|
-
|
|
1455
|
+
readonly filterTemplateSignal: i0.WritableSignal<TemplateRef<unknown> | undefined>;
|
|
1456
|
+
private _filterBarTemplate?;
|
|
1457
|
+
set filterBarTemplate(tpl: TemplateRef<unknown> | undefined);
|
|
1458
|
+
get filterBarTemplate(): TemplateRef<unknown> | undefined;
|
|
1449
1459
|
get filterTemplate(): TemplateRef<unknown> | undefined;
|
|
1450
1460
|
private readonly widgetEventBus;
|
|
1451
1461
|
queryContext: PraxisDataQueryContextBridge | null;
|
|
@@ -1854,6 +1864,7 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterView
|
|
|
1854
1864
|
private tableConfigKey;
|
|
1855
1865
|
private filterConfigKey;
|
|
1856
1866
|
private ensureConfigDefaults;
|
|
1867
|
+
private recomposeEffectiveTableConfig;
|
|
1857
1868
|
private hasDeclaredAppearanceDensity;
|
|
1858
1869
|
private hasDeclaredAppearanceSection;
|
|
1859
1870
|
private shouldApplyAppearanceDefaultValue;
|
|
@@ -2372,6 +2383,7 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterView
|
|
|
2372
2383
|
private syncQuickFilterStateFromEffectiveCriteria;
|
|
2373
2384
|
private clearQuickFilterRuntimeState;
|
|
2374
2385
|
private hasEquivalentFilterCriteria;
|
|
2386
|
+
private lastAppliedFilterCriteria;
|
|
2375
2387
|
applyAdvancedFilterCriteria(criteria: Record<string, any> | null | undefined, reason?: string): void;
|
|
2376
2388
|
private setAdvancedFilterCriteria;
|
|
2377
2389
|
private syncAdvancedFilterValueFromCriteria;
|
|
@@ -2755,6 +2767,7 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterView
|
|
|
2755
2767
|
private isColumnFiltersSupported;
|
|
2756
2768
|
private isRowDraggingSupported;
|
|
2757
2769
|
private isRowExpansionSupported;
|
|
2770
|
+
private hasComplementarySchemaExpansionFields;
|
|
2758
2771
|
private enforceAppearanceSchemaGuards;
|
|
2759
2772
|
private enforceUnsupportedFeatureGuards;
|
|
2760
2773
|
getToolbarEvaluationContext(): Record<string, any>;
|
|
@@ -3065,7 +3078,7 @@ declare class PraxisTable implements OnInit, OnChanges, AfterViewInit, AfterView
|
|
|
3065
3078
|
private scheduleRowDiscoveryMarkForCheck;
|
|
3066
3079
|
ngOnDestroy(): void;
|
|
3067
3080
|
static ɵfac: i0.ɵɵFactoryDeclaration<PraxisTable, [null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }, { optional: true; }]>;
|
|
3068
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisTable, "praxis-table", never, { "config": { "alias": "config"; "required": false; }; "resourcePath": { "alias": "resourcePath"; "required": false; }; "data": { "alias": "data"; "required": false; }; "tableId": { "alias": "tableId"; "required": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "configPersistenceStrategy": { "alias": "configPersistenceStrategy"; "required": false; }; "title": { "alias": "title"; "required": false; }; "subtitle": { "alias": "subtitle"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "autoDelete": { "alias": "autoDelete"; "required": false; }; "notifyIfOutdated": { "alias": "notifyIfOutdated"; "required": false; }; "snoozeMs": { "alias": "snoozeMs"; "required": false; }; "autoOpenSettingsOnOutdated": { "alias": "autoOpenSettingsOnOutdated"; "required": false; }; "crudContext": { "alias": "crudContext"; "required": false; }; "filterCriteria": { "alias": "filterCriteria"; "required": false; }; "filterTeleport": { "alias": "filterTeleport"; "required": false; }; "widgetId": { "alias": "widgetId"; "required": false; }; "queryContext": { "alias": "queryContext"; "required": false; }; "aiContext": { "alias": "aiContext"; "required": false; }; "aiAssistantVoiceInputMode": { "alias": "aiAssistantVoiceInputMode"; "required": false; }; "aiAssistantVoiceLanguage": { "alias": "aiAssistantVoiceLanguage"; "required": false; }; "horizontalScroll": { "alias": "horizontalScroll"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "authoringCapability": { "alias": "authoringCapability"; "required": false; }; "dense": { "alias": "dense"; "required": false; }; }, { "queryContextClear": "queryContextClear"; "queryContextChange": "queryContextChange"; "rowClick": "rowClick"; "widgetEvent": "widgetEvent"; "resourceEvent": "resourceEvent"; "rowDoubleClick": "rowDoubleClick"; "rowExpansionChange": "rowExpansionChange"; "rowAction": "rowAction"; "toolbarAction": "toolbarAction"; "bulkAction": "bulkAction"; "exportAction": "exportAction"; "columnReorder": "columnReorder"; "columnReorderAttempt": "columnReorderAttempt"; "columnResize": "columnResize"; "beforeDelete": "beforeDelete"; "afterDelete": "afterDelete"; "deleteError": "deleteError"; "beforeBulkDelete": "beforeBulkDelete"; "afterBulkDelete": "afterBulkDelete"; "bulkDeleteError": "bulkDeleteError"; "schemaStatusChange": "schemaStatusChange"; "configChange": "configChange"; "metadataChange": "metadataChange"; "loadingStateChange": "loadingStateChange"; "collectionLinksChange": "collectionLinksChange"; "selectionChange": "selectionChange"; "drawerOpen": "drawerOpen"; "drawerClose": "drawerClose"; "drawerTabChange": "drawerTabChange"; }, ["toolbar", "projectedFilter"], ["[advancedFilter]", "[toolbar]", "[advancedFilter]", "[toolbar]", "[advancedFilter]", "[toolbar]"], true, never>;
|
|
3081
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<PraxisTable, "praxis-table", never, { "config": { "alias": "config"; "required": false; }; "resourcePath": { "alias": "resourcePath"; "required": false; }; "data": { "alias": "data"; "required": false; }; "tableId": { "alias": "tableId"; "required": true; }; "componentInstanceId": { "alias": "componentInstanceId"; "required": false; }; "configPersistenceStrategy": { "alias": "configPersistenceStrategy"; "required": false; }; "title": { "alias": "title"; "required": false; }; "subtitle": { "alias": "subtitle"; "required": false; }; "icon": { "alias": "icon"; "required": false; }; "autoDelete": { "alias": "autoDelete"; "required": false; }; "notifyIfOutdated": { "alias": "notifyIfOutdated"; "required": false; }; "snoozeMs": { "alias": "snoozeMs"; "required": false; }; "autoOpenSettingsOnOutdated": { "alias": "autoOpenSettingsOnOutdated"; "required": false; }; "crudContext": { "alias": "crudContext"; "required": false; }; "filterCriteria": { "alias": "filterCriteria"; "required": false; }; "filterTeleport": { "alias": "filterTeleport"; "required": false; }; "widgetId": { "alias": "widgetId"; "required": false; }; "queryContext": { "alias": "queryContext"; "required": false; }; "aiContext": { "alias": "aiContext"; "required": false; }; "aiAssistantVoiceInputMode": { "alias": "aiAssistantVoiceInputMode"; "required": false; }; "aiAssistantVoiceLanguage": { "alias": "aiAssistantVoiceLanguage"; "required": false; }; "horizontalScroll": { "alias": "horizontalScroll"; "required": false; }; "enableCustomization": { "alias": "enableCustomization"; "required": false; }; "authoringCapability": { "alias": "authoringCapability"; "required": false; }; "dense": { "alias": "dense"; "required": false; }; }, { "filterCriteriaChange": "filterCriteriaChange"; "queryContextClear": "queryContextClear"; "queryContextChange": "queryContextChange"; "rowClick": "rowClick"; "widgetEvent": "widgetEvent"; "resourceEvent": "resourceEvent"; "rowDoubleClick": "rowDoubleClick"; "rowExpansionChange": "rowExpansionChange"; "rowAction": "rowAction"; "toolbarAction": "toolbarAction"; "bulkAction": "bulkAction"; "exportAction": "exportAction"; "columnReorder": "columnReorder"; "columnReorderAttempt": "columnReorderAttempt"; "columnResize": "columnResize"; "beforeDelete": "beforeDelete"; "afterDelete": "afterDelete"; "deleteError": "deleteError"; "beforeBulkDelete": "beforeBulkDelete"; "afterBulkDelete": "afterBulkDelete"; "bulkDeleteError": "bulkDeleteError"; "schemaStatusChange": "schemaStatusChange"; "configChange": "configChange"; "metadataChange": "metadataChange"; "loadingStateChange": "loadingStateChange"; "collectionLinksChange": "collectionLinksChange"; "selectionChange": "selectionChange"; "drawerOpen": "drawerOpen"; "drawerClose": "drawerClose"; "drawerTabChange": "drawerTabChange"; }, ["toolbar", "projectedFilter"], ["[advancedFilter]", "[toolbar]", "[advancedFilter]", "[toolbar]", "[advancedFilter]", "[toolbar]"], true, never>;
|
|
3069
3082
|
static ngAcceptInputType_filterTeleport: unknown;
|
|
3070
3083
|
static ngAcceptInputType_enableCustomization: unknown;
|
|
3071
3084
|
}
|