@meshmakers/octo-meshboard 3.5.700 → 3.5.720
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.
|
@@ -4,7 +4,7 @@ import * as i0 from '@angular/core';
|
|
|
4
4
|
import { Injectable, inject, EventEmitter, forwardRef, Output, Input, ViewChild, ChangeDetectionStrategy, Component, input, Directive, model, computed, ElementRef, Injector, EnvironmentInjector, ApplicationRef, signal, effect, untracked, InjectionToken, isSignal, LOCALE_ID, NgZone, DestroyRef, ChangeDetectorRef, ViewChildren, createEnvironmentInjector, ViewContainerRef, makeEnvironmentProviders, provideAppInitializer, output, viewChild } from '@angular/core';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
6
|
import { NG_VALUE_ACCESSOR, FormsModule, NG_VALIDATORS } from '@angular/forms';
|
|
7
|
-
import { firstValueFrom, from, map, Observable, of, switchMap as switchMap$1, forkJoin, catchError, NEVER, interval, Subject, BehaviorSubject, filter as filter$1, combineLatest, defer
|
|
7
|
+
import { firstValueFrom, from, map, Observable, of, switchMap as switchMap$1, forkJoin, catchError, EMPTY, NEVER, interval, Subject, BehaviorSubject, filter as filter$1, combineLatest, defer } from 'rxjs';
|
|
8
8
|
import * as i1$8 from '@meshmakers/shared-ui';
|
|
9
9
|
import { EntitySelectInputComponent, MM_ACTION_ICONS, WindowStateService, TimeRangeUtils, MmDialogActionsDirective, ListViewComponent, FetchResultTyped, DataSourceBase, ConfirmationService, TimeRangePickerComponent, ImportStrategyDialogService, HAS_UNSAVED_CHANGES, UnsavedChangesDirective } from '@meshmakers/shared-ui';
|
|
10
10
|
import * as i1 from 'apollo-angular';
|
|
@@ -10929,6 +10929,12 @@ class TableWidgetDataSourceDirective extends OctoGraphQlDataSource {
|
|
|
10929
10929
|
stateService = inject(MeshBoardStateService);
|
|
10930
10930
|
variableService = inject(MeshBoardVariableService);
|
|
10931
10931
|
_config = null;
|
|
10932
|
+
/**
|
|
10933
|
+
* Signature of the query inputs outside the grid state (data source, resolved
|
|
10934
|
+
* widget filters, time filter, entity-selector scope) of the last fetch.
|
|
10935
|
+
* `null` until the first fetch. See {@link refetch}.
|
|
10936
|
+
*/
|
|
10937
|
+
_lastQueryInputs = null;
|
|
10932
10938
|
/** Signal for dynamically derived columns from persistent query */
|
|
10933
10939
|
_queryColumns = signal([], /* @ts-ignore */
|
|
10934
10940
|
...(ngDevMode ? [{ debugName: "_queryColumns" }] : /* istanbul ignore next */ []));
|
|
@@ -10955,7 +10961,43 @@ class TableWidgetDataSourceDirective extends OctoGraphQlDataSource {
|
|
|
10955
10961
|
const listViewComponent = inject(ListViewComponent);
|
|
10956
10962
|
super(listViewComponent);
|
|
10957
10963
|
}
|
|
10964
|
+
/**
|
|
10965
|
+
* Refetches the widget data (board refresh, auto-refresh, config change).
|
|
10966
|
+
*
|
|
10967
|
+
* When a query input outside the grid state changed since the last fetch — a
|
|
10968
|
+
* MeshBoard variable or widget filter, the time filter, the entity-selector
|
|
10969
|
+
* scope or the data source itself — the result set is a different one, so the
|
|
10970
|
+
* list returns to page 1 before the query is sent (AB#8801). Otherwise the old
|
|
10971
|
+
* page offset could point past the end of the new result (asset repository:
|
|
10972
|
+
* ASSET1002 / INCOMPLETE_SLICE). A plain refresh with unchanged inputs keeps
|
|
10973
|
+
* the current page.
|
|
10974
|
+
*/
|
|
10975
|
+
refetch() {
|
|
10976
|
+
const previous = this._lastQueryInputs;
|
|
10977
|
+
const resetSkip = previous !== null && previous !== this.queryInputsSignature();
|
|
10978
|
+
this.fetchAgain(resetSkip ? { resetSkip: true } : undefined);
|
|
10979
|
+
}
|
|
10980
|
+
/**
|
|
10981
|
+
* Page-out-of-range detection for both error shapes: the inherited check reads
|
|
10982
|
+
* `graphQLErrors` (Apollo 3 `ApolloError`); Apollo 4 rejects with
|
|
10983
|
+
* `CombinedGraphQLErrors`, which carries the same entries in `errors`.
|
|
10984
|
+
*/
|
|
10985
|
+
isPageOutOfRangeError(error) {
|
|
10986
|
+
if (super.isPageOutOfRangeError(error)) {
|
|
10987
|
+
return true;
|
|
10988
|
+
}
|
|
10989
|
+
const errors = error?.errors;
|
|
10990
|
+
if (!Array.isArray(errors)) {
|
|
10991
|
+
return false;
|
|
10992
|
+
}
|
|
10993
|
+
return errors.some((e) => {
|
|
10994
|
+
const extensions = e?.extensions;
|
|
10995
|
+
const codes = Array.isArray(extensions?.['codes']) ? extensions['codes'] : [];
|
|
10996
|
+
return codes.includes('INCOMPLETE_SLICE') || extensions?.['code'] === 'INCOMPLETE_SLICE';
|
|
10997
|
+
});
|
|
10998
|
+
}
|
|
10958
10999
|
fetchData(queryOptions) {
|
|
11000
|
+
this._lastQueryInputs = this.queryInputsSignature();
|
|
10959
11001
|
if (!this._config) {
|
|
10960
11002
|
return of(new FetchResultTyped([], 0));
|
|
10961
11003
|
}
|
|
@@ -11018,10 +11060,52 @@ class TableWidgetDataSourceDirective extends OctoGraphQlDataSource {
|
|
|
11018
11060
|
return record;
|
|
11019
11061
|
});
|
|
11020
11062
|
return new FetchResultTyped(data, totalCount);
|
|
11021
|
-
}), catchError$1(err =>
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11063
|
+
}), catchError$1(err => this.handleFetchError(err, queryOptions, 'Error fetching table data:')));
|
|
11064
|
+
}
|
|
11065
|
+
/**
|
|
11066
|
+
* Error path of both fetch paths. A page offset beyond the result set
|
|
11067
|
+
* (ASSET1002 / INCOMPLETE_SLICE, e.g. the data shrank since the last load)
|
|
11068
|
+
* is not shown as an empty list: the list returns to page 1 and refetches
|
|
11069
|
+
* once (AB#8801). The refetch runs on a microtask so the list binding's
|
|
11070
|
+
* current subscription has ended first; skip 0 cannot be out of range, so
|
|
11071
|
+
* this cannot loop. Any other error keeps today's behaviour (logged, no rows).
|
|
11072
|
+
*/
|
|
11073
|
+
handleFetchError(err, queryOptions, logMessage) {
|
|
11074
|
+
const skip = queryOptions.state.skip ?? 0;
|
|
11075
|
+
if (skip > 0 && this.isPageOutOfRangeError(err)) {
|
|
11076
|
+
console.warn(`octo-meshboard: table widget page offset ${skip} lies beyond the result; returning to page 1`);
|
|
11077
|
+
queueMicrotask(() => this.fetchAgain({ resetSkip: true }));
|
|
11078
|
+
return EMPTY;
|
|
11079
|
+
}
|
|
11080
|
+
console.error(logMessage, err);
|
|
11081
|
+
return of(new FetchResultTyped([], 0));
|
|
11082
|
+
}
|
|
11083
|
+
/**
|
|
11084
|
+
* Signature of every query input outside the grid state (paging, sort, grid
|
|
11085
|
+
* filter): the data source, the widget filters with MeshBoard variables
|
|
11086
|
+
* resolved, the time filter selection and the entity-selector scope. The time
|
|
11087
|
+
* filter enters as its selection, not as resolved instants, so a relative
|
|
11088
|
+
* range ("last 24 hours") does not look changed on every auto-refresh. The
|
|
11089
|
+
* board's time-zone mode enters with an active selection (no host period),
|
|
11090
|
+
* because the selection's window is resolved in that zone.
|
|
11091
|
+
*/
|
|
11092
|
+
queryInputsSignature() {
|
|
11093
|
+
const config = this._config;
|
|
11094
|
+
if (!config) {
|
|
11095
|
+
return 'none';
|
|
11096
|
+
}
|
|
11097
|
+
const dataSource = config.dataSource;
|
|
11098
|
+
const filters = this.convertFiltersToDto(config.filters) ?? null;
|
|
11099
|
+
if (dataSource.type !== 'persistentQuery') {
|
|
11100
|
+
return JSON.stringify({ dataSource, filters });
|
|
11101
|
+
}
|
|
11102
|
+
const timeFilter = dataSource.ignoreTimeFilter ? null : (this.stateService.getConfig().timeFilter ?? null);
|
|
11103
|
+
const host = dataSource.ignoreTimeFilter ? null : this.stateService.hostTimeRange();
|
|
11104
|
+
// Host periods are absolute instants (no zone conversion), so the zone only
|
|
11105
|
+
// matters for the board's own selection.
|
|
11106
|
+
const timeZone = timeFilter?.enabled && timeFilter.selection && !host ? this.stateService.timeZoneMode() : null;
|
|
11107
|
+
const scope = this.stateService.resolveStreamDataScope(dataSource.entitySelectorId, dataSource.queryFamily, dataSource.ignoreTimeFilter);
|
|
11108
|
+
return JSON.stringify({ dataSource, filters, timeFilter, timeZone, host, scope });
|
|
11025
11109
|
}
|
|
11026
11110
|
/**
|
|
11027
11111
|
* Recursively flattens attributes into the record using dot notation for nested attributes.
|
|
@@ -11103,7 +11187,11 @@ class TableWidgetDataSourceDirective extends OctoGraphQlDataSource {
|
|
|
11103
11187
|
fieldFilter: fieldFilter ?? undefined,
|
|
11104
11188
|
streamDataArgs,
|
|
11105
11189
|
// Runtime queries: `rtId IN` field filter (AB#7725); stream data: arg.rtIds.
|
|
11106
|
-
scopeRtIds: scope.kind === 'scoped' ? scope.rtIds : undefined
|
|
11190
|
+
scopeRtIds: scope.kind === 'scoped' ? scope.rtIds : undefined,
|
|
11191
|
+
// A refetch (board refresh, changed inputs, page-1 recovery) bypasses the
|
|
11192
|
+
// Apollo cache like the runtime-entity path does, so a cached page with a
|
|
11193
|
+
// stale total count is never shown again (AB#8801).
|
|
11194
|
+
forceRefresh: queryOptions.forceRefresh ?? false
|
|
11107
11195
|
}).pipe(map$1(result => {
|
|
11108
11196
|
// Extract columns from query response and update signal.
|
|
11109
11197
|
// Replace dots with underscores for grid compatibility (Kendo treats dots as nested paths).
|
|
@@ -11120,10 +11208,7 @@ class TableWidgetDataSourceDirective extends OctoGraphQlDataSource {
|
|
|
11120
11208
|
.filter(row => TableWidgetDataSourceDirective.SUPPORTED_ROW_TYPES.has(row.__typename ?? ''))
|
|
11121
11209
|
.map((row, index) => this.queryRowToRecord(row, columns, hasRtIdColumn, hasCkTypeIdColumn, index));
|
|
11122
11210
|
return new FetchResultTyped(data, result.totalCount);
|
|
11123
|
-
}), catchError$1(err =>
|
|
11124
|
-
console.error('Error fetching query data:', err);
|
|
11125
|
-
return of(new FetchResultTyped([], 0));
|
|
11126
|
-
}));
|
|
11211
|
+
}), catchError$1(err => this.handleFetchError(err, queryOptions, 'Error fetching query data:')));
|
|
11127
11212
|
}
|
|
11128
11213
|
/**
|
|
11129
11214
|
* Flattens a unified `QueryResultRow` into a Kendo-grid-friendly record.
|
|
@@ -12019,7 +12104,8 @@ class TableWidgetComponent {
|
|
|
12019
12104
|
if (this.dataSource) {
|
|
12020
12105
|
// Clear query columns in directive before fetching new data
|
|
12021
12106
|
this.dataSource.clearQueryColumns();
|
|
12022
|
-
|
|
12107
|
+
// Returns to page 1 when a variable, filter, time filter or scope changed (AB#8801).
|
|
12108
|
+
this.dataSource.refetch();
|
|
12023
12109
|
}
|
|
12024
12110
|
}
|
|
12025
12111
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.5", ngImport: i0, type: TableWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|