@quadrel-enterprise-ui/framework 20.11.2 → 20.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, Directive, InjectionToken, HostBinding, Input, ViewEncapsulation, Component, Injectable, Injector, HostListener, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, NgModule, EventEmitter, Output, Renderer2, Pipe, ViewContainerRef, NO_ERRORS_SCHEMA, SecurityContext, NgZone, ViewChildren, forwardRef,
|
|
2
|
+
import { inject, ElementRef, Directive, InjectionToken, HostBinding, Input, ViewEncapsulation, Component, Injectable, Injector, HostListener, ChangeDetectionStrategy, ChangeDetectorRef, ViewChild, NgModule, EventEmitter, Output, Renderer2, Pipe, ViewContainerRef, NO_ERRORS_SCHEMA, DestroyRef, SecurityContext, NgZone, ViewChildren, forwardRef, ContentChildren, ContentChild, isDevMode, QueryList, CUSTOM_ELEMENTS_SCHEMA, provideAppInitializer, TemplateRef } from '@angular/core';
|
|
3
3
|
import { Dialog, DialogRef, DialogModule } from '@angular/cdk/dialog';
|
|
4
4
|
import * as i1 from '@angular/common';
|
|
5
5
|
import { CommonModule, NgFor, NgIf, NgClass, NgTemplateOutlet, AsyncPipe } from '@angular/common';
|
|
6
|
-
import { BehaviorSubject, pairwise, from, switchMap, map as map$1, Subject, throwError, of, ReplaySubject, merge, fromEvent, isObservable, NEVER, Observable, EMPTY, shareReplay, Subscription, distinctUntilChanged as distinctUntilChanged$1, debounce, timer, startWith as startWith$1, debounceTime as debounceTime$1, takeUntil as takeUntil$1, firstValueFrom, combineLatest, concat, take as take$1, delay, tap as tap$1, first, scan, queueScheduler, filter as filter$1, concatMap as concatMap$1, exhaustMap, finalize,
|
|
7
|
-
import { map, takeUntil, take, filter, catchError, debounceTime, startWith, distinctUntilChanged, concatMap, tap, skip, auditTime, observeOn, switchMap as switchMap$1, pairwise as pairwise$1, mergeMap, delay as delay$1 } from 'rxjs/operators';
|
|
6
|
+
import { BehaviorSubject, pairwise, from, switchMap, map as map$1, Subject, throwError, of, ReplaySubject, merge, fromEvent, isObservable, NEVER, Observable, EMPTY, shareReplay, Subscription, distinctUntilChanged as distinctUntilChanged$1, debounce, timer, startWith as startWith$1, debounceTime as debounceTime$1, takeUntil as takeUntil$1, firstValueFrom, combineLatest, concat, take as take$1, delay, tap as tap$1, first, scan, queueScheduler, filter as filter$1, concatMap as concatMap$1, exhaustMap, finalize, forkJoin, delayWhen, combineLatestWith, withLatestFrom as withLatestFrom$1, async } from 'rxjs';
|
|
7
|
+
import { map, takeUntil, take, filter, catchError, debounceTime, startWith, distinctUntilChanged, concatMap, tap, skip, auditTime, withLatestFrom, observeOn, switchMap as switchMap$1, pairwise as pairwise$1, mergeMap, delay as delay$1 } from 'rxjs/operators';
|
|
8
8
|
import { v4 } from 'uuid';
|
|
9
9
|
import * as i3 from '@ngx-translate/core';
|
|
10
10
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
11
11
|
import * as i2$1 from '@angular/router';
|
|
12
|
-
import { Router, ActivationEnd, RouterModule, ActivatedRoute,
|
|
12
|
+
import { Router, ActivationEnd, RouterModule, ActivatedRoute, NavigationEnd, NavigationCancel, NavigationError, NavigationStart } from '@angular/router';
|
|
13
13
|
import { HttpStatusCode, HttpEventType, HttpClient, HttpParams, HTTP_INTERCEPTORS } from '@angular/common/http';
|
|
14
14
|
import * as _ from 'lodash';
|
|
15
15
|
import { upperCase, lowerFirst, isEqual, range, get as get$1, cloneDeep, union, isNumber as isNumber$1 } from 'lodash';
|
|
@@ -19,6 +19,7 @@ import { ComponentPortal } from '@angular/cdk/portal';
|
|
|
19
19
|
import { OverlayPositionBuilder, Overlay } from '@angular/cdk/overlay';
|
|
20
20
|
import isNumber from 'lodash/isNumber';
|
|
21
21
|
import { EventSourcePolyfill } from 'event-source-polyfill';
|
|
22
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
22
23
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
23
24
|
import * as i3$1 from 'ngx-editor';
|
|
24
25
|
import { Editor, NgxEditorModule } from 'ngx-editor';
|
|
@@ -31,7 +32,6 @@ import 'moment/locale/fr';
|
|
|
31
32
|
import 'moment/locale/it';
|
|
32
33
|
import moment$1 from 'moment/moment';
|
|
33
34
|
import { ActiveDescendantKeyManager } from '@angular/cdk/a11y';
|
|
34
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
35
35
|
import * as i1$1 from '@ngrx/store';
|
|
36
36
|
import { createAction, props, createReducer, on, createSelector, createFeatureSelector, Store, StoreModule } from '@ngrx/store';
|
|
37
37
|
import { diff } from 'deep-object-diff';
|
|
@@ -7115,6 +7115,295 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
7115
7115
|
}]
|
|
7116
7116
|
}] });
|
|
7117
7117
|
|
|
7118
|
+
/**
|
|
7119
|
+
* Framework-wide funnel for syncing application state with the URL `?key=value` query string.
|
|
7120
|
+
*
|
|
7121
|
+
* Several Quadrel features mirror their state to the URL via per-feature adapters. Without
|
|
7122
|
+
* coordination they each call `router.navigate(...)` directly, which produces two failure modes:
|
|
7123
|
+
*
|
|
7124
|
+
* 1. **Race**: two navigates issued in the same JS turn cancel each other. Only the last writer
|
|
7125
|
+
* wins; the URL silently loses the cancelled feature's params.
|
|
7126
|
+
* 2. **History pollution**: a single user action that changes two features (e.g. clicking a sort
|
|
7127
|
+
* header resets the page index) ends up as two history entries. Browser-back only undoes one.
|
|
7128
|
+
*
|
|
7129
|
+
* `QdRouterQueryParamHubService` is the single funnel through which features run their query-param
|
|
7130
|
+
* reads and writes. It does three jobs:
|
|
7131
|
+
*
|
|
7132
|
+
* - **Ownership** — `claim()` / `release()` enforce one writer per param key, app-wide.
|
|
7133
|
+
* - **Shared reads** — `queryParams()` and `snapshotQueryParam()` expose the route state without
|
|
7134
|
+
* each feature needing its own `ActivatedRoute` subscription.
|
|
7135
|
+
* - **Coordinated writes** — `write()` buffers param updates within a microtask and serializes
|
|
7136
|
+
* navigations via a Promise chain, so two writes in the same JS turn become one history entry
|
|
7137
|
+
* and concurrent writes never race.
|
|
7138
|
+
*
|
|
7139
|
+
* The hub is feature-agnostic. Per-feature adapters (e.g. `QdTableSortRouterConnectorService`)
|
|
7140
|
+
* own their parsing/serialization and delegate the URL plumbing to the hub.
|
|
7141
|
+
*
|
|
7142
|
+
* ### Usage
|
|
7143
|
+
*
|
|
7144
|
+
* ```ts
|
|
7145
|
+
* @Injectable()
|
|
7146
|
+
* export class FilterRouterAdapterService {
|
|
7147
|
+
* private readonly _hub = inject(QdRouterQueryParamHubService);
|
|
7148
|
+
* private readonly _destroyRef = inject(DestroyRef);
|
|
7149
|
+
*
|
|
7150
|
+
* connect(state$: Observable<FilterState>, dispatch: (state: FilterState) => void): void {
|
|
7151
|
+
* if (!this._hub.isAvailable()) return;
|
|
7152
|
+
* if (!this._hub.claim(['filter'], this, this._destroyRef, { name: 'Filter', plural: 'filters' })) return;
|
|
7153
|
+
*
|
|
7154
|
+
* this._hub
|
|
7155
|
+
* .queryParams()
|
|
7156
|
+
* .pipe(takeUntilDestroyed(this._destroyRef))
|
|
7157
|
+
* .subscribe(params => dispatch(parseFilter(params['filter'])));
|
|
7158
|
+
*
|
|
7159
|
+
* state$
|
|
7160
|
+
* .pipe(takeUntilDestroyed(this._destroyRef))
|
|
7161
|
+
* .subscribe(state => this._hub.write({ filter: serializeFilter(state) }, { replaceUrl: false }));
|
|
7162
|
+
* }
|
|
7163
|
+
* }
|
|
7164
|
+
* ```
|
|
7165
|
+
*/
|
|
7166
|
+
class QdRouterQueryParamHubService {
|
|
7167
|
+
/**
|
|
7168
|
+
* Replays whenever the router has finished a navigation (`NavigationEnd`, `NavigationCancel`
|
|
7169
|
+
* or `NavigationError` — every event that ends a navigation, regardless of outcome).
|
|
7170
|
+
* Adapters that want to delay a write until any in-flight navigation has settled can take(1)
|
|
7171
|
+
* on this stream before calling `write()`.
|
|
7172
|
+
*
|
|
7173
|
+
* Late subscribers receive the most recent settling event immediately, so an adapter that
|
|
7174
|
+
* mounts after the initial route navigation can observe the route as already-settled. The
|
|
7175
|
+
* first replayed tick may represent that initial route navigation rather than a user-driven
|
|
7176
|
+
* settling event — adapters that need to distinguish "the route just changed" should compare
|
|
7177
|
+
* `ActivatedRoute.snapshot` themselves.
|
|
7178
|
+
*
|
|
7179
|
+
* **When the hub is unavailable** (no `Router` / `ActivatedRoute` in the injector — see
|
|
7180
|
+
* `isAvailable()`) this observable never emits. Adapters that compose `navigationSettled$`
|
|
7181
|
+
* via operators like `switchMap` or `concat` must guard with `isAvailable()` first, otherwise
|
|
7182
|
+
* their pipelines hang silently.
|
|
7183
|
+
*/
|
|
7184
|
+
navigationSettled$;
|
|
7185
|
+
_router = inject(Router, { optional: true });
|
|
7186
|
+
_activatedRoute = inject(ActivatedRoute, { optional: true });
|
|
7187
|
+
_destroyRef = inject(DestroyRef);
|
|
7188
|
+
_ownership = new Map();
|
|
7189
|
+
_ownerLabels = new WeakMap();
|
|
7190
|
+
_destroyClaims = new WeakMap();
|
|
7191
|
+
_navigationSettledSubject = new ReplaySubject(1);
|
|
7192
|
+
_pendingParams = {};
|
|
7193
|
+
_pendingReplaceUrl = false;
|
|
7194
|
+
_flushScheduled = false;
|
|
7195
|
+
_navigationChain = Promise.resolve();
|
|
7196
|
+
constructor() {
|
|
7197
|
+
this.navigationSettled$ = this._navigationSettledSubject.asObservable();
|
|
7198
|
+
if (!this._router || !this._activatedRoute)
|
|
7199
|
+
return;
|
|
7200
|
+
this.replayCurrentRouterStateForLateSubscribers(this._router);
|
|
7201
|
+
this.forwardSettlingRouterEventsToNavigationSettled(this._router);
|
|
7202
|
+
}
|
|
7203
|
+
/**
|
|
7204
|
+
* Returns whether the hub can sync at all. False when the consuming injector has neither a
|
|
7205
|
+
* `Router` nor an `ActivatedRoute` available — for example in unit tests that omit
|
|
7206
|
+
* `RouterTestingModule`. Adapters should bail out early when this returns false.
|
|
7207
|
+
*/
|
|
7208
|
+
isAvailable() {
|
|
7209
|
+
return !!this._router && !!this._activatedRoute;
|
|
7210
|
+
}
|
|
7211
|
+
/**
|
|
7212
|
+
* Reserves exclusive write access to the given query-param keys for `owner`.
|
|
7213
|
+
*
|
|
7214
|
+
* The same `owner` may claim the same keys repeatedly without conflict — claims are idempotent
|
|
7215
|
+
* per owner. A different owner attempting to claim an already-claimed key fails: the hub logs
|
|
7216
|
+
* a `console.error` listing every contested key and returns `false`. The original owner keeps
|
|
7217
|
+
* the keys until it calls `release()` (or until its `DestroyRef` fires, if a `destroyRef` is
|
|
7218
|
+
* passed here).
|
|
7219
|
+
*
|
|
7220
|
+
* Atomicity: when the call fails, no keys are claimed, even partially. The hub checks every
|
|
7221
|
+
* requested key against the registry before mutating anything.
|
|
7222
|
+
*
|
|
7223
|
+
* **Pass `destroyRef` to opt into auto-release.** Without it, the hub keeps a strong reference
|
|
7224
|
+
* to `owner` until `release()` is called manually — a destroyed adapter that forgets to release
|
|
7225
|
+
* pins itself in the registry. Passing the adapter's `DestroyRef` registers an `onDestroy`
|
|
7226
|
+
* callback that releases exactly the keys claimed via this call (and any later claims that
|
|
7227
|
+
* reuse the same `destroyRef`), which is the recommended path.
|
|
7228
|
+
*
|
|
7229
|
+
* Each `destroyRef` releases only the keys it owns. If the same owner uses two different
|
|
7230
|
+
* `DestroyRef`s in two `claim()` calls, each fires independently and only releases its own
|
|
7231
|
+
* keys — keys claimed via the still-alive `destroyRef` stay reserved.
|
|
7232
|
+
*
|
|
7233
|
+
* Re-claiming with the same `destroyRef` appends to the same destroy listener — no duplicate
|
|
7234
|
+
* listeners are registered, even when the second claim names a different owner. Each appended
|
|
7235
|
+
* entry carries its own owner, so when the `destroyRef` fires the hub releases each entry's
|
|
7236
|
+
* keys against that entry's owner. An empty `keys` array is a no-op even when `destroyRef`
|
|
7237
|
+
* is provided: no listener is attached, so the hub does not pin a destroy hook that would
|
|
7238
|
+
* release nothing.
|
|
7239
|
+
*
|
|
7240
|
+
* @param keys The query-param keys this adapter wants to own (e.g. `['sort']`, `['page', 'size']`).
|
|
7241
|
+
* @param owner Stable identity of the caller — usually `this`. Used as the registry key.
|
|
7242
|
+
* @param destroyRef Optional. If provided, the hub releases the keys automatically when the
|
|
7243
|
+
* `DestroyRef` fires. Pass the adapter's `inject(DestroyRef)` to make leaks impossible.
|
|
7244
|
+
* @param featureLabel Optional. User-facing display label for the adapter's owning feature. The
|
|
7245
|
+
* hub uses it to format ownership-conflict error messages so application developers see the
|
|
7246
|
+
* feature names they configured (e.g. `Filter`, `Page Tabs`, `Table`) instead of internal
|
|
7247
|
+
* adapter class names. When omitted, the hub falls back to a generic `another adapter` phrase.
|
|
7248
|
+
* @returns `true` if every requested key is now owned by `owner`. `false` if at least one key
|
|
7249
|
+
* was already owned by a different adapter; the registry is left untouched and `destroyRef`
|
|
7250
|
+
* is not registered.
|
|
7251
|
+
*/
|
|
7252
|
+
claim(keys, owner, destroyRef, featureLabel) {
|
|
7253
|
+
const conflicts = [];
|
|
7254
|
+
for (const key of keys) {
|
|
7255
|
+
const existing = this._ownership.get(key);
|
|
7256
|
+
if (existing && existing !== owner)
|
|
7257
|
+
conflicts.push(key);
|
|
7258
|
+
}
|
|
7259
|
+
if (conflicts.length > 0) {
|
|
7260
|
+
const existingOwner = this._ownership.get(conflicts[0]);
|
|
7261
|
+
const existingLabel = this._ownerLabels.get(existingOwner);
|
|
7262
|
+
console.error(this.formatOwnershipConflictMessage(conflicts, existingLabel));
|
|
7263
|
+
return false;
|
|
7264
|
+
}
|
|
7265
|
+
keys.forEach(key => this._ownership.set(key, owner));
|
|
7266
|
+
if (featureLabel)
|
|
7267
|
+
this._ownerLabels.set(owner, featureLabel);
|
|
7268
|
+
if (destroyRef && keys.length > 0)
|
|
7269
|
+
this.registerAutoRelease(owner, keys, destroyRef);
|
|
7270
|
+
return true;
|
|
7271
|
+
}
|
|
7272
|
+
formatOwnershipConflictMessage(conflicts, existingLabel) {
|
|
7273
|
+
const keysList = conflicts.map(key => `"${key}"`).join(', ');
|
|
7274
|
+
const paramHeader = conflicts.length === 1 ? 'Query param' : 'Query params';
|
|
7275
|
+
const verb = conflicts.length === 1 ? 'is' : 'are';
|
|
7276
|
+
const ownerPhrase = existingLabel?.name ?? 'another adapter';
|
|
7277
|
+
const lines = [
|
|
7278
|
+
`Quadrel Framework | Router Query Param Hub - ${paramHeader} ${keysList} ${verb} already owned by ${ownerPhrase}.`
|
|
7279
|
+
];
|
|
7280
|
+
if (existingLabel) {
|
|
7281
|
+
lines.push(`Only one router-connected ${existingLabel.name} is allowed per view.`, `Please set connectWithRouter: false on all additional ${existingLabel.plural}.`);
|
|
7282
|
+
}
|
|
7283
|
+
else {
|
|
7284
|
+
lines.push("Disable the conflicting feature's URL sync or move it to a different param key.");
|
|
7285
|
+
}
|
|
7286
|
+
return lines.join('\n');
|
|
7287
|
+
}
|
|
7288
|
+
/**
|
|
7289
|
+
* Drops `owner`'s claim on the given keys. Keys not owned by `owner` are left untouched —
|
|
7290
|
+
* a foreign release call cannot steal another adapter's ownership.
|
|
7291
|
+
*
|
|
7292
|
+
* Adapters typically release in their `DestroyRef.onDestroy` callback so a destroyed component
|
|
7293
|
+
* frees its keys for the next adapter that mounts.
|
|
7294
|
+
*/
|
|
7295
|
+
release(keys, owner) {
|
|
7296
|
+
keys.forEach(key => {
|
|
7297
|
+
if (this._ownership.get(key) === owner)
|
|
7298
|
+
this._ownership.delete(key);
|
|
7299
|
+
});
|
|
7300
|
+
}
|
|
7301
|
+
/**
|
|
7302
|
+
* Reactive view of `ActivatedRoute.queryParams`. Returns the empty observable if the hub is
|
|
7303
|
+
* not available (no Router/ActivatedRoute). Adapters subscribe here instead of injecting
|
|
7304
|
+
* `ActivatedRoute` themselves so the hub stays the single read funnel.
|
|
7305
|
+
*
|
|
7306
|
+
* The observable is hot — late subscribers receive the current params immediately.
|
|
7307
|
+
*/
|
|
7308
|
+
queryParams() {
|
|
7309
|
+
return this._activatedRoute?.queryParams ?? of({});
|
|
7310
|
+
}
|
|
7311
|
+
/**
|
|
7312
|
+
* Synchronous read of a single query param from the latest `ActivatedRoute` snapshot.
|
|
7313
|
+
* Adapters use this to detect "URL already matches the desired state" and skip a redundant
|
|
7314
|
+
* `write()`.
|
|
7315
|
+
*
|
|
7316
|
+
* @returns The param value, or `undefined` if the param is missing or the hub is unavailable.
|
|
7317
|
+
*/
|
|
7318
|
+
snapshotQueryParam(key) {
|
|
7319
|
+
return this._activatedRoute?.snapshot.queryParamMap.get(key) ?? undefined;
|
|
7320
|
+
}
|
|
7321
|
+
/**
|
|
7322
|
+
* Schedules a query-param update.
|
|
7323
|
+
*
|
|
7324
|
+
* Two coordination guarantees:
|
|
7325
|
+
*
|
|
7326
|
+
* - **Microtask batching** — every `write()` issued in the same JavaScript turn is merged into
|
|
7327
|
+
* a single `router.navigate(...)` call. A user action that changes two features at once
|
|
7328
|
+
* (e.g. sort change resets the page) becomes one history entry, not two. Note: batching is
|
|
7329
|
+
* per JS turn, not per logical user action — writes that fall into the next microtask after
|
|
7330
|
+
* a settled navigation produce a separate history entry, even when they belong to the same
|
|
7331
|
+
* conceptual gesture.
|
|
7332
|
+
* - **Serialized navigations** — flushes are chained on a Promise so a second flush only fires
|
|
7333
|
+
* after the previous `router.navigate` has settled. Concurrent navigates can therefore not
|
|
7334
|
+
* cancel each other. A rejected `router.navigate` (cancelled by a guard, redirected, or
|
|
7335
|
+
* failed) does not stop the chain — the next pending flush still runs. Rejections are not
|
|
7336
|
+
* logged here; consumers that need routing diagnostics should subscribe to `router.events`.
|
|
7337
|
+
*
|
|
7338
|
+
* Adapters are still responsible for skipping no-op writes (compare the desired value against
|
|
7339
|
+
* `snapshotQueryParam()` first), since the hub does not deduplicate identical values.
|
|
7340
|
+
*
|
|
7341
|
+
* Setting a param value to `undefined` removes the param from the URL via Angular Router's
|
|
7342
|
+
* `merge` behavior. Other params not mentioned in the call are preserved.
|
|
7343
|
+
*
|
|
7344
|
+
* @param params Partial map of query-param keys to their new values. Missing keys are not touched.
|
|
7345
|
+
* An empty object short-circuits and is a no-op.
|
|
7346
|
+
* @param options Write options — see `QdRouterQueryParamWriteOptions` for the `replaceUrl`
|
|
7347
|
+
* semantics and per-batch escalation rules.
|
|
7348
|
+
*/
|
|
7349
|
+
write(params, options) {
|
|
7350
|
+
const router = this._router;
|
|
7351
|
+
const activatedRoute = this._activatedRoute;
|
|
7352
|
+
if (!router || !activatedRoute)
|
|
7353
|
+
return;
|
|
7354
|
+
if (Object.keys(params).length === 0)
|
|
7355
|
+
return;
|
|
7356
|
+
Object.assign(this._pendingParams, params);
|
|
7357
|
+
this._pendingReplaceUrl = this._pendingReplaceUrl || options.replaceUrl;
|
|
7358
|
+
if (this._flushScheduled)
|
|
7359
|
+
return;
|
|
7360
|
+
this._flushScheduled = true;
|
|
7361
|
+
Promise.resolve().then(() => this.flush(router, activatedRoute));
|
|
7362
|
+
}
|
|
7363
|
+
replayCurrentRouterStateForLateSubscribers(router) {
|
|
7364
|
+
if (router.navigated)
|
|
7365
|
+
this._navigationSettledSubject.next();
|
|
7366
|
+
}
|
|
7367
|
+
forwardSettlingRouterEventsToNavigationSettled(router) {
|
|
7368
|
+
router.events
|
|
7369
|
+
.pipe(filter(event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError), takeUntilDestroyed(this._destroyRef))
|
|
7370
|
+
.subscribe(() => this._navigationSettledSubject.next());
|
|
7371
|
+
}
|
|
7372
|
+
registerAutoRelease(owner, keys, destroyRef) {
|
|
7373
|
+
const existingClaims = this._destroyClaims.get(destroyRef);
|
|
7374
|
+
if (existingClaims) {
|
|
7375
|
+
existingClaims.push({ owner, keys });
|
|
7376
|
+
return;
|
|
7377
|
+
}
|
|
7378
|
+
const claims = [{ owner, keys }];
|
|
7379
|
+
this._destroyClaims.set(destroyRef, claims);
|
|
7380
|
+
destroyRef.onDestroy(() => {
|
|
7381
|
+
for (const claim of claims)
|
|
7382
|
+
this.release(claim.keys, claim.owner);
|
|
7383
|
+
});
|
|
7384
|
+
}
|
|
7385
|
+
flush(router, activatedRoute) {
|
|
7386
|
+
const params = this._pendingParams;
|
|
7387
|
+
const replaceUrl = this._pendingReplaceUrl;
|
|
7388
|
+
this._pendingParams = {};
|
|
7389
|
+
this._pendingReplaceUrl = false;
|
|
7390
|
+
this._flushScheduled = false;
|
|
7391
|
+
const exec = () => router.navigate([], {
|
|
7392
|
+
relativeTo: activatedRoute,
|
|
7393
|
+
queryParams: params,
|
|
7394
|
+
queryParamsHandling: 'merge',
|
|
7395
|
+
replaceUrl
|
|
7396
|
+
});
|
|
7397
|
+
this._navigationChain = this._navigationChain.catch(() => undefined).then(exec);
|
|
7398
|
+
}
|
|
7399
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7400
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, providedIn: 'root' });
|
|
7401
|
+
}
|
|
7402
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, decorators: [{
|
|
7403
|
+
type: Injectable,
|
|
7404
|
+
args: [{ providedIn: 'root' }]
|
|
7405
|
+
}], ctorParameters: () => [] });
|
|
7406
|
+
|
|
7118
7407
|
const MAX_TOOLTIP_CHARACTER = 512;
|
|
7119
7408
|
const TOOLTIP_POSITIONS = [
|
|
7120
7409
|
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom' },
|
|
@@ -11418,6 +11707,8 @@ class QdDatepickerComponent {
|
|
|
11418
11707
|
timePicker;
|
|
11419
11708
|
_disabledDatesValidator;
|
|
11420
11709
|
_disabledTimesValidator;
|
|
11710
|
+
_boundDisabledDates;
|
|
11711
|
+
_boundDisabledTimes;
|
|
11421
11712
|
_subs = new Subscription();
|
|
11422
11713
|
_onChange = () => { };
|
|
11423
11714
|
_onTouched = () => { };
|
|
@@ -11429,17 +11720,17 @@ class QdDatepickerComponent {
|
|
|
11429
11720
|
this.updateConfiguration();
|
|
11430
11721
|
this.updateDisplayedDate();
|
|
11431
11722
|
this.updateDisplayedDateTime();
|
|
11432
|
-
this.validateDisabledDates();
|
|
11433
|
-
this.validateDisabledTimes();
|
|
11434
11723
|
this._subs.add(this.initOpModeSubscription());
|
|
11435
11724
|
}
|
|
11436
11725
|
ngOnChanges(changes) {
|
|
11437
11726
|
if (changes.config) {
|
|
11438
11727
|
this.updateConfiguration();
|
|
11439
|
-
this.validateDisabledDates();
|
|
11440
|
-
this.validateDisabledTimes();
|
|
11441
11728
|
}
|
|
11442
11729
|
}
|
|
11730
|
+
ngDoCheck() {
|
|
11731
|
+
this.rebindDisabledDatesValidatorIfChanged();
|
|
11732
|
+
this.rebindDisabledTimesValidatorIfChanged();
|
|
11733
|
+
}
|
|
11443
11734
|
ngOnDestroy() {
|
|
11444
11735
|
this._subs.unsubscribe();
|
|
11445
11736
|
}
|
|
@@ -11610,6 +11901,20 @@ class QdDatepickerComponent {
|
|
|
11610
11901
|
this.displayedDateTime = QdDateAdapter.formatToDateTimeLocaleString(currentValue, this.config?.enableSeconds);
|
|
11611
11902
|
this.displayedTime = QdDateAdapter.formatToTimeLocaleString(currentValue, this.config?.enableSeconds);
|
|
11612
11903
|
}
|
|
11904
|
+
rebindDisabledDatesValidatorIfChanged() {
|
|
11905
|
+
const current = this.config?.disabledDates;
|
|
11906
|
+
if (current === this._boundDisabledDates)
|
|
11907
|
+
return;
|
|
11908
|
+
this._boundDisabledDates = current;
|
|
11909
|
+
this.validateDisabledDates();
|
|
11910
|
+
}
|
|
11911
|
+
rebindDisabledTimesValidatorIfChanged() {
|
|
11912
|
+
const current = this.config?.timePicker?.disabledTimes;
|
|
11913
|
+
if (current === this._boundDisabledTimes)
|
|
11914
|
+
return;
|
|
11915
|
+
this._boundDisabledTimes = current;
|
|
11916
|
+
this.validateDisabledTimes();
|
|
11917
|
+
}
|
|
11613
11918
|
validateDisabledDates() {
|
|
11614
11919
|
if (!this.control)
|
|
11615
11920
|
return;
|
|
@@ -20913,99 +21218,86 @@ function unescape(escapedString) {
|
|
|
20913
21218
|
return escapedString.replace(new RegExp(`\\\\(${SERIALIZATION_SYMBOLS.map(s => '\\' + s).join('|')})`, 'g'), '$1');
|
|
20914
21219
|
}
|
|
20915
21220
|
|
|
20916
|
-
|
|
21221
|
+
const FILTER_PARAM_NAME = 'filter';
|
|
21222
|
+
const OWNED_PARAMS$4 = [FILTER_PARAM_NAME];
|
|
21223
|
+
const FEATURE_LABEL$4 = { name: 'Filter', plural: 'filters' };
|
|
21224
|
+
/**
|
|
21225
|
+
* Per-view adapter that syncs `QdFilterComponent` selection with the URL `?filter=` query
|
|
21226
|
+
* param via `QdRouterQueryParamHubService`. Reads/parses on activation, writes on selection
|
|
21227
|
+
* change. Coordination, ownership, and write batching are delegated to the hub — see its
|
|
21228
|
+
* JSDoc for details. Behavior contracts live in `filter-router-connector.service.spec.ts`
|
|
21229
|
+
* and `router-query-param-hub.integration.cy.ts`.
|
|
21230
|
+
*/
|
|
20917
21231
|
class QdFilterRouterConnectorService {
|
|
20918
|
-
|
|
20919
|
-
|
|
20920
|
-
|
|
21232
|
+
_filterService = inject(QdFilterService);
|
|
21233
|
+
_hub = inject(QdRouterQueryParamHubService);
|
|
21234
|
+
_destroyRef = inject(DestroyRef);
|
|
20921
21235
|
_connectedFilter;
|
|
20922
|
-
|
|
20923
|
-
|
|
20924
|
-
_navigationEnded$;
|
|
21236
|
+
_readSubscription;
|
|
21237
|
+
_writeSubscription;
|
|
20925
21238
|
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
20926
21239
|
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
20927
21240
|
constructor() {
|
|
20928
|
-
|
|
20929
|
-
return;
|
|
20930
|
-
const navigationPending$ = new ReplaySubject(1);
|
|
20931
|
-
this._navigationEnded$ = navigationPending$.pipe(filter(navigationPending => !navigationPending));
|
|
20932
|
-
if (this.router.navigated)
|
|
20933
|
-
navigationPending$.next(false);
|
|
20934
|
-
this.router.events.subscribe(event => {
|
|
20935
|
-
switch (event.constructor) {
|
|
20936
|
-
case NavigationStart:
|
|
20937
|
-
navigationPending$.next(true);
|
|
20938
|
-
break;
|
|
20939
|
-
case NavigationEnd:
|
|
20940
|
-
case NavigationCancel:
|
|
20941
|
-
case NavigationError:
|
|
20942
|
-
navigationPending$.next(false);
|
|
20943
|
-
break;
|
|
20944
|
-
}
|
|
20945
|
-
});
|
|
21241
|
+
this._destroyRef.onDestroy(() => this.tearDownConnection());
|
|
20946
21242
|
}
|
|
20947
21243
|
connectFilterWithRouter(filterComponent) {
|
|
20948
|
-
if (filterComponent.filterData?.connectWithRouter === false || !this.
|
|
21244
|
+
if (filterComponent.filterData?.connectWithRouter === false || !this._hub.isAvailable())
|
|
20949
21245
|
return of(false);
|
|
20950
|
-
|
|
20951
|
-
|
|
20952
|
-
|
|
20953
|
-
'Please set connectWithRouter to false except for one filter.');
|
|
21246
|
+
if (this._connectedFilter === filterComponent)
|
|
21247
|
+
return this._activatedRouteChecked$;
|
|
21248
|
+
if (!this._hub.claim(OWNED_PARAMS$4, this, this._destroyRef, FEATURE_LABEL$4))
|
|
20954
21249
|
return of(false);
|
|
20955
|
-
}
|
|
20956
21250
|
this._connectedFilter = filterComponent;
|
|
20957
|
-
this.
|
|
20958
|
-
this.
|
|
21251
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
21252
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
21253
|
+
this.subscribeToUrlChanges();
|
|
21254
|
+
this.subscribeToFilterChanges();
|
|
20959
21255
|
return this._activatedRouteChecked$;
|
|
20960
21256
|
}
|
|
20961
|
-
|
|
20962
|
-
this.
|
|
20963
|
-
|
|
20964
|
-
|
|
20965
|
-
|
|
20966
|
-
|
|
20967
|
-
|
|
20968
|
-
|
|
20969
|
-
|
|
20970
|
-
|
|
20971
|
-
|
|
20972
|
-
|
|
20973
|
-
|
|
21257
|
+
tearDownConnection() {
|
|
21258
|
+
this._connectedFilter = undefined;
|
|
21259
|
+
this._readSubscription?.unsubscribe();
|
|
21260
|
+
this._writeSubscription?.unsubscribe();
|
|
21261
|
+
}
|
|
21262
|
+
subscribeToUrlChanges() {
|
|
21263
|
+
let isFirstEmit = true;
|
|
21264
|
+
this._readSubscription = this._hub.navigationSettled$
|
|
21265
|
+
.pipe(switchMap(() => this._hub.queryParams()), map(queryParams => queryParams[FILTER_PARAM_NAME]), distinctUntilChanged(), switchMap(rawFilter => this._filterService.selectFilterDataById$(this._connectedFilter.filterId).pipe(take(1), map(filterData => ({ rawFilter, filterData })))), takeUntilDestroyed(this._destroyRef))
|
|
21266
|
+
.subscribe(({ rawFilter, filterData }) => {
|
|
21267
|
+
const emptySelection = filterData
|
|
21268
|
+
.map(category => ({ [category.category]: [] }))
|
|
21269
|
+
.reduce((accumulator, emptyCategory) => ({ ...accumulator, ...emptyCategory }), {});
|
|
21270
|
+
if (typeof rawFilter === 'string') {
|
|
21271
|
+
this._filterService.setFilterSelection(this._connectedFilter.filterId, {
|
|
21272
|
+
...emptySelection,
|
|
21273
|
+
...parseFilterUrlParameter(rawFilter)
|
|
20974
21274
|
});
|
|
20975
21275
|
}
|
|
20976
|
-
|
|
21276
|
+
else if (!isFirstEmit) {
|
|
21277
|
+
this._filterService.setFilterSelection(this._connectedFilter.filterId, emptySelection);
|
|
21278
|
+
}
|
|
21279
|
+
if (isFirstEmit) {
|
|
21280
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
21281
|
+
isFirstEmit = false;
|
|
21282
|
+
}
|
|
20977
21283
|
});
|
|
20978
21284
|
}
|
|
20979
|
-
|
|
20980
|
-
this.
|
|
21285
|
+
subscribeToFilterChanges() {
|
|
21286
|
+
this._writeSubscription = this._filterService
|
|
20981
21287
|
.getFilterUrlParameter$(this._connectedFilter.filterId)
|
|
20982
|
-
.pipe(switchMap(filterUrlParameter => this.
|
|
21288
|
+
.pipe(distinctUntilChanged(), switchMap(filterUrlParameter => this._hub.navigationSettled$.pipe(take(1), map(() => filterUrlParameter))), takeUntilDestroyed(this._destroyRef))
|
|
20983
21289
|
.subscribe(filterUrlParameter => {
|
|
20984
|
-
|
|
20985
|
-
|
|
20986
|
-
|
|
20987
|
-
|
|
20988
|
-
},
|
|
20989
|
-
queryParamsHandling: 'merge',
|
|
20990
|
-
replaceUrl: true
|
|
20991
|
-
});
|
|
21290
|
+
const target = filterUrlParameter || undefined;
|
|
21291
|
+
if (this._hub.snapshotQueryParam(FILTER_PARAM_NAME) === target)
|
|
21292
|
+
return;
|
|
21293
|
+
this._hub.write({ [FILTER_PARAM_NAME]: target }, { replaceUrl: false });
|
|
20992
21294
|
});
|
|
20993
21295
|
}
|
|
20994
|
-
disconnectFilterFromRouter(filterComponent) {
|
|
20995
|
-
if (this._connectedFilter !== filterComponent)
|
|
20996
|
-
return;
|
|
20997
|
-
this._connectedFilter = null;
|
|
20998
|
-
this._activatedRouteSubscription?.unsubscribe();
|
|
20999
|
-
this._filterUrlParameterSubscription?.unsubscribe();
|
|
21000
|
-
}
|
|
21001
21296
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
21002
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterRouterConnectorService
|
|
21297
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterRouterConnectorService });
|
|
21003
21298
|
}
|
|
21004
21299
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterRouterConnectorService, decorators: [{
|
|
21005
|
-
type: Injectable
|
|
21006
|
-
args: [{
|
|
21007
|
-
providedIn: 'root'
|
|
21008
|
-
}]
|
|
21300
|
+
type: Injectable
|
|
21009
21301
|
}], ctorParameters: () => [] });
|
|
21010
21302
|
|
|
21011
21303
|
class QdDependentFiltersService {
|
|
@@ -21145,7 +21437,7 @@ class QdFilterComponent {
|
|
|
21145
21437
|
_filterDataSubject = new BehaviorSubject(undefined);
|
|
21146
21438
|
_hasPreselectionSubject = new ReplaySubject(1);
|
|
21147
21439
|
_categoriesSubject = new ReplaySubject(1);
|
|
21148
|
-
_filterConnectedWithRouterSubject = new ReplaySubject();
|
|
21440
|
+
_filterConnectedWithRouterSubject = new ReplaySubject(1);
|
|
21149
21441
|
_filterConnectedWithRouter$ = this._filterConnectedWithRouterSubject.asObservable();
|
|
21150
21442
|
set hasPreselection(hasPreselection) {
|
|
21151
21443
|
this._hasPreselectionSubject.next(hasPreselection);
|
|
@@ -21183,7 +21475,6 @@ class QdFilterComponent {
|
|
|
21183
21475
|
}
|
|
21184
21476
|
}
|
|
21185
21477
|
ngOnDestroy() {
|
|
21186
|
-
this.filterRouterConnectorService.disconnectFilterFromRouter(this);
|
|
21187
21478
|
this.dependentFiltersService.destroy();
|
|
21188
21479
|
this._queryStringSubscription?.unsubscribe();
|
|
21189
21480
|
this._postBodySubscription?.unsubscribe();
|
|
@@ -21318,11 +21609,11 @@ class QdFilterComponent {
|
|
|
21318
21609
|
});
|
|
21319
21610
|
}
|
|
21320
21611
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
21321
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterComponent, isStandalone: false, selector: "qd-filter", inputs: { filterData: "filterData", testId: ["data-test-id", "testId"] }, outputs: { queryStringOutput: "queryStringOutput", postBodyOutput: "postBodyOutput", valueChange: "valueChange" }, host: { properties: { "attr.data-test-id": "this.dataTestId" }, classAttribute: "qd-filter" }, providers: [QdDependentFiltersService], viewQueries: [{ propertyName: "filterCategory", predicate: i0.forwardRef(() => QdFilterCategoryComponent), descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"(categories$ | async)?.length > 0\">\n <ng-container\n *ngFor=\"let category of categories$ | async; let last = last; let length = count; let categoryIndex = index\"\n >\n <qd-filter-category\n [filterId]=\"filterId\"\n [isInstantFiltering]=\"isInstantFiltering\"\n [categoryIndex]=\"categoryIndex\"\n [lastCategory]=\"last\"\n [data-test-id]=\"testId + '-category-' + categoryIndex + '-' + category\"\n ></qd-filter-category>\n </ng-container>\n\n <div [class]=\"'qd-filter__action-buttons'\" *ngIf=\"!isInstantFiltering\">\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableFilterButton$ | async\"\n (click)=\"clickFilter()\"\n [color]=\"'primary'\"\n [data-test-id]=\"testId + '-submit-button'\"\n >\n {{ \"i18n.qd.container.toolbar.filter.filter\" | translate }}\n </button>\n\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableResetButton$ | async\"\n (click)=\"resetFilter()\"\n [color]=\"'secondary'\"\n [data-test-id]=\"testId + '-reset-button'\"\n >\n {{\n ((hasPreselection$ | async)\n ? \"i18n.qd.container.toolbar.filter.backToPreSelect\"\n : \"i18n.qd.container.toolbar.filter.reset\"\n ) | translate\n }}\n </button>\n </div>\n</ng-container>\n", styles: [":host{position:relative;display:flex;flex-wrap:wrap}:host .qd-filter__action-buttons{display:flex;flex-wrap:wrap-reverse}:host ::ng-deep .qd-button{position:relative;margin-bottom:1rem}:host ::ng-deep .qd-button:last-child{margin-left:1rem}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonLinkDirective, selector: "button[qdButtonLink], a[qdButtonLink], button[qd-button-link]" }, { kind: "component", type: QdFilterCategoryComponent, selector: "qd-filter-category", inputs: ["filterId", "isInstantFiltering", "categoryIndex", "lastCategory", "data-test-id"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
21612
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterComponent, isStandalone: false, selector: "qd-filter", inputs: { filterData: "filterData", testId: ["data-test-id", "testId"] }, outputs: { queryStringOutput: "queryStringOutput", postBodyOutput: "postBodyOutput", valueChange: "valueChange" }, host: { properties: { "attr.data-test-id": "this.dataTestId" }, classAttribute: "qd-filter" }, providers: [QdDependentFiltersService, QdFilterRouterConnectorService], viewQueries: [{ propertyName: "filterCategory", predicate: i0.forwardRef(() => QdFilterCategoryComponent), descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"(categories$ | async)?.length > 0\">\n <ng-container\n *ngFor=\"let category of categories$ | async; let last = last; let length = count; let categoryIndex = index\"\n >\n <qd-filter-category\n [filterId]=\"filterId\"\n [isInstantFiltering]=\"isInstantFiltering\"\n [categoryIndex]=\"categoryIndex\"\n [lastCategory]=\"last\"\n [data-test-id]=\"testId + '-category-' + categoryIndex + '-' + category\"\n ></qd-filter-category>\n </ng-container>\n\n <div [class]=\"'qd-filter__action-buttons'\" *ngIf=\"!isInstantFiltering\">\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableFilterButton$ | async\"\n (click)=\"clickFilter()\"\n [color]=\"'primary'\"\n [data-test-id]=\"testId + '-submit-button'\"\n >\n {{ \"i18n.qd.container.toolbar.filter.filter\" | translate }}\n </button>\n\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableResetButton$ | async\"\n (click)=\"resetFilter()\"\n [color]=\"'secondary'\"\n [data-test-id]=\"testId + '-reset-button'\"\n >\n {{\n ((hasPreselection$ | async)\n ? \"i18n.qd.container.toolbar.filter.backToPreSelect\"\n : \"i18n.qd.container.toolbar.filter.reset\"\n ) | translate\n }}\n </button>\n </div>\n</ng-container>\n", styles: [":host{position:relative;display:flex;flex-wrap:wrap}:host .qd-filter__action-buttons{display:flex;flex-wrap:wrap-reverse}:host ::ng-deep .qd-button{position:relative;margin-bottom:1rem}:host ::ng-deep .qd-button:last-child{margin-left:1rem}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonLinkDirective, selector: "button[qdButtonLink], a[qdButtonLink], button[qd-button-link]" }, { kind: "component", type: QdFilterCategoryComponent, selector: "qd-filter-category", inputs: ["filterId", "isInstantFiltering", "categoryIndex", "lastCategory", "data-test-id"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
21322
21613
|
}
|
|
21323
21614
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterComponent, decorators: [{
|
|
21324
21615
|
type: Component,
|
|
21325
|
-
args: [{ selector: 'qd-filter', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'qd-filter' }, providers: [QdDependentFiltersService], standalone: false, template: "<ng-container *ngIf=\"(categories$ | async)?.length > 0\">\n <ng-container\n *ngFor=\"let category of categories$ | async; let last = last; let length = count; let categoryIndex = index\"\n >\n <qd-filter-category\n [filterId]=\"filterId\"\n [isInstantFiltering]=\"isInstantFiltering\"\n [categoryIndex]=\"categoryIndex\"\n [lastCategory]=\"last\"\n [data-test-id]=\"testId + '-category-' + categoryIndex + '-' + category\"\n ></qd-filter-category>\n </ng-container>\n\n <div [class]=\"'qd-filter__action-buttons'\" *ngIf=\"!isInstantFiltering\">\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableFilterButton$ | async\"\n (click)=\"clickFilter()\"\n [color]=\"'primary'\"\n [data-test-id]=\"testId + '-submit-button'\"\n >\n {{ \"i18n.qd.container.toolbar.filter.filter\" | translate }}\n </button>\n\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableResetButton$ | async\"\n (click)=\"resetFilter()\"\n [color]=\"'secondary'\"\n [data-test-id]=\"testId + '-reset-button'\"\n >\n {{\n ((hasPreselection$ | async)\n ? \"i18n.qd.container.toolbar.filter.backToPreSelect\"\n : \"i18n.qd.container.toolbar.filter.reset\"\n ) | translate\n }}\n </button>\n </div>\n</ng-container>\n", styles: [":host{position:relative;display:flex;flex-wrap:wrap}:host .qd-filter__action-buttons{display:flex;flex-wrap:wrap-reverse}:host ::ng-deep .qd-button{position:relative;margin-bottom:1rem}:host ::ng-deep .qd-button:last-child{margin-left:1rem}\n"] }]
|
|
21616
|
+
args: [{ selector: 'qd-filter', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'qd-filter' }, providers: [QdDependentFiltersService, QdFilterRouterConnectorService], standalone: false, template: "<ng-container *ngIf=\"(categories$ | async)?.length > 0\">\n <ng-container\n *ngFor=\"let category of categories$ | async; let last = last; let length = count; let categoryIndex = index\"\n >\n <qd-filter-category\n [filterId]=\"filterId\"\n [isInstantFiltering]=\"isInstantFiltering\"\n [categoryIndex]=\"categoryIndex\"\n [lastCategory]=\"last\"\n [data-test-id]=\"testId + '-category-' + categoryIndex + '-' + category\"\n ></qd-filter-category>\n </ng-container>\n\n <div [class]=\"'qd-filter__action-buttons'\" *ngIf=\"!isInstantFiltering\">\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableFilterButton$ | async\"\n (click)=\"clickFilter()\"\n [color]=\"'primary'\"\n [data-test-id]=\"testId + '-submit-button'\"\n >\n {{ \"i18n.qd.container.toolbar.filter.filter\" | translate }}\n </button>\n\n <button\n qdButton\n qdButtonLink\n [disabled]=\"disableResetButton$ | async\"\n (click)=\"resetFilter()\"\n [color]=\"'secondary'\"\n [data-test-id]=\"testId + '-reset-button'\"\n >\n {{\n ((hasPreselection$ | async)\n ? \"i18n.qd.container.toolbar.filter.backToPreSelect\"\n : \"i18n.qd.container.toolbar.filter.reset\"\n ) | translate\n }}\n </button>\n </div>\n</ng-container>\n", styles: [":host{position:relative;display:flex;flex-wrap:wrap}:host .qd-filter__action-buttons{display:flex;flex-wrap:wrap-reverse}:host ::ng-deep .qd-button{position:relative;margin-bottom:1rem}:host ::ng-deep .qd-button:last-child{margin-left:1rem}\n"] }]
|
|
21326
21617
|
}], propDecorators: { filterData: [{
|
|
21327
21618
|
type: Input
|
|
21328
21619
|
}], testId: [{
|
|
@@ -21990,94 +22281,88 @@ function searchReducer(state, action) {
|
|
|
21990
22281
|
}
|
|
21991
22282
|
|
|
21992
22283
|
const PHRASE_PRESELECT_SEPARATOR = '|';
|
|
22284
|
+
const SEARCH_PARAM_NAME = 'search';
|
|
22285
|
+
const OWNED_PARAMS$3 = [SEARCH_PARAM_NAME];
|
|
22286
|
+
const FEATURE_LABEL$3 = { name: 'Search', plural: 'searches' };
|
|
22287
|
+
/**
|
|
22288
|
+
* Per-view adapter that syncs `QdSearchComponent` phrase and preselection with the URL
|
|
22289
|
+
* `?search=` query param via `QdRouterQueryParamHubService`. Reads/parses on activation,
|
|
22290
|
+
* writes when the search service emits a submit. Coordination, ownership, and write
|
|
22291
|
+
* batching are delegated to the hub — see its JSDoc for details. Behavior contracts live
|
|
22292
|
+
* in `search-router-connector.service.spec.ts` and
|
|
22293
|
+
* `router-query-param-hub.integration.cy.ts`.
|
|
22294
|
+
*/
|
|
21993
22295
|
class QdSearchRouterConnectorService {
|
|
21994
|
-
|
|
21995
|
-
|
|
22296
|
+
_hub = inject(QdRouterQueryParamHubService);
|
|
22297
|
+
_destroyRef = inject(DestroyRef);
|
|
21996
22298
|
_connectedSearch;
|
|
21997
|
-
|
|
21998
|
-
|
|
21999
|
-
_navigationEnded$;
|
|
22299
|
+
_readSubscription;
|
|
22300
|
+
_writeSubscription;
|
|
22000
22301
|
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
22001
22302
|
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
22002
22303
|
constructor() {
|
|
22003
|
-
|
|
22004
|
-
return;
|
|
22005
|
-
const navigationPending$ = new ReplaySubject(1);
|
|
22006
|
-
this._navigationEnded$ = navigationPending$.pipe(filter(navigationPending => !navigationPending));
|
|
22007
|
-
if (this.router.navigated)
|
|
22008
|
-
navigationPending$.next(false);
|
|
22009
|
-
this.router.events.subscribe(event => {
|
|
22010
|
-
switch (event.constructor) {
|
|
22011
|
-
case NavigationStart:
|
|
22012
|
-
navigationPending$.next(true);
|
|
22013
|
-
break;
|
|
22014
|
-
case NavigationEnd:
|
|
22015
|
-
case NavigationCancel:
|
|
22016
|
-
case NavigationError:
|
|
22017
|
-
navigationPending$.next(false);
|
|
22018
|
-
break;
|
|
22019
|
-
}
|
|
22020
|
-
});
|
|
22304
|
+
this._destroyRef.onDestroy(() => this.tearDownConnection());
|
|
22021
22305
|
}
|
|
22022
22306
|
connectSearchWithRouter(searchComponent) {
|
|
22023
|
-
if (searchComponent.configData?.connectWithRouter !== true || !this.
|
|
22307
|
+
if (searchComponent.configData?.connectWithRouter !== true || !this._hub.isAvailable())
|
|
22024
22308
|
return of(false);
|
|
22025
|
-
|
|
22026
|
-
|
|
22027
|
-
|
|
22028
|
-
'Please set connectWithRouter to false except for one search.');
|
|
22309
|
+
if (this._connectedSearch === searchComponent)
|
|
22310
|
+
return this._activatedRouteChecked$;
|
|
22311
|
+
if (!this._hub.claim(OWNED_PARAMS$3, this, this._destroyRef, FEATURE_LABEL$3))
|
|
22029
22312
|
return of(false);
|
|
22030
|
-
}
|
|
22031
22313
|
this._connectedSearch = searchComponent;
|
|
22032
|
-
this.
|
|
22033
|
-
this.
|
|
22314
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
22315
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
22316
|
+
this.subscribeToUrlChanges();
|
|
22317
|
+
this.subscribeToSearchChanges();
|
|
22034
22318
|
return this._activatedRouteChecked$;
|
|
22035
22319
|
}
|
|
22036
|
-
|
|
22037
|
-
this.
|
|
22038
|
-
|
|
22039
|
-
|
|
22040
|
-
|
|
22041
|
-
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22045
|
-
|
|
22320
|
+
tearDownConnection() {
|
|
22321
|
+
this._connectedSearch = undefined;
|
|
22322
|
+
this._readSubscription?.unsubscribe();
|
|
22323
|
+
this._writeSubscription?.unsubscribe();
|
|
22324
|
+
}
|
|
22325
|
+
subscribeToUrlChanges() {
|
|
22326
|
+
let isFirstEmit = true;
|
|
22327
|
+
this._readSubscription = this._hub.navigationSettled$
|
|
22328
|
+
.pipe(switchMap(() => this._hub.queryParams()), map(queryParams => queryParams[SEARCH_PARAM_NAME]), distinctUntilChanged(), takeUntilDestroyed(this._destroyRef))
|
|
22329
|
+
.subscribe(rawSearch => {
|
|
22330
|
+
if (typeof rawSearch === 'string' && this._connectedSearch) {
|
|
22331
|
+
const [phrase, preSelect] = rawSearch
|
|
22332
|
+
.split(this.getNotEscapedSplitRegExp())
|
|
22333
|
+
.map(value => this.unescape(value));
|
|
22334
|
+
this._connectedSearch.search = phrase;
|
|
22335
|
+
this._connectedSearch.preSelect = preSelect || '';
|
|
22336
|
+
}
|
|
22337
|
+
else if (!isFirstEmit && this._connectedSearch) {
|
|
22338
|
+
this._connectedSearch.search = '';
|
|
22339
|
+
this._connectedSearch.preSelect = '';
|
|
22046
22340
|
}
|
|
22047
|
-
|
|
22341
|
+
if (isFirstEmit) {
|
|
22342
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
22343
|
+
isFirstEmit = false;
|
|
22344
|
+
}
|
|
22345
|
+
});
|
|
22346
|
+
}
|
|
22347
|
+
subscribeToSearchChanges() {
|
|
22348
|
+
this._writeSubscription = this._connectedSearch.searchService.searchPostBody$.pipe(switchMap(searchData => this._hub.navigationSettled$.pipe(take(1), map(() => searchData))), takeUntilDestroyed(this._destroyRef)).subscribe(({ phrase, preSelect }) => {
|
|
22349
|
+
const serialized = this.escape(phrase) + (preSelect ? PHRASE_PRESELECT_SEPARATOR + this.escape(preSelect) : '');
|
|
22350
|
+
const target = serialized || undefined;
|
|
22351
|
+
if (this._hub.snapshotQueryParam(SEARCH_PARAM_NAME) === target)
|
|
22352
|
+
return;
|
|
22353
|
+
this._hub.write({ [SEARCH_PARAM_NAME]: target }, { replaceUrl: false });
|
|
22048
22354
|
});
|
|
22049
22355
|
}
|
|
22050
22356
|
getNotEscapedSplitRegExp() {
|
|
22051
22357
|
return new RegExp('(?<!\\\\)\\' + PHRASE_PRESELECT_SEPARATOR);
|
|
22052
22358
|
}
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
.pipe(switchMap(searchData => this._navigationEnded$.pipe(take$1(1), map(() => searchData))))
|
|
22056
|
-
.subscribe(({ phrase, preSelect }) => {
|
|
22057
|
-
this.router.navigate([], {
|
|
22058
|
-
relativeTo: this.activatedRoute,
|
|
22059
|
-
queryParams: {
|
|
22060
|
-
search: this.escape(phrase) + (preSelect ? PHRASE_PRESELECT_SEPARATOR + this.escape(preSelect) : '')
|
|
22061
|
-
},
|
|
22062
|
-
queryParamsHandling: 'merge',
|
|
22063
|
-
replaceUrl: true
|
|
22064
|
-
});
|
|
22065
|
-
});
|
|
22066
|
-
}
|
|
22067
|
-
escape(string) {
|
|
22068
|
-
if (!string)
|
|
22359
|
+
escape(value) {
|
|
22360
|
+
if (!value)
|
|
22069
22361
|
return '';
|
|
22070
|
-
return
|
|
22071
|
-
}
|
|
22072
|
-
unescape(escapedString) {
|
|
22073
|
-
return escapedString.replace(new RegExp(`\\\\(${PHRASE_PRESELECT_SEPARATOR})`, 'g'), '$1');
|
|
22362
|
+
return value.replace(new RegExp(`(\\${PHRASE_PRESELECT_SEPARATOR})`, 'g'), '\\$1');
|
|
22074
22363
|
}
|
|
22075
|
-
|
|
22076
|
-
|
|
22077
|
-
return;
|
|
22078
|
-
this._connectedSearch = null;
|
|
22079
|
-
this._activatedRouteSubscription?.unsubscribe();
|
|
22080
|
-
this._searchUrlParameterSubscription?.unsubscribe();
|
|
22364
|
+
unescape(escapedValue) {
|
|
22365
|
+
return escapedValue.replace(new RegExp(`\\\\(${PHRASE_PRESELECT_SEPARATOR})`, 'g'), '$1');
|
|
22081
22366
|
}
|
|
22082
22367
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdSearchRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
22083
22368
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdSearchRouterConnectorService });
|
|
@@ -22274,7 +22559,7 @@ class QdSearchComponent {
|
|
|
22274
22559
|
_search = '';
|
|
22275
22560
|
_preSelect = '';
|
|
22276
22561
|
_destroyed$ = new Subject();
|
|
22277
|
-
_searchConnectedWithRouterSubject = new ReplaySubject();
|
|
22562
|
+
_searchConnectedWithRouterSubject = new ReplaySubject(1);
|
|
22278
22563
|
_searchConnectedWithRouter$ = this._searchConnectedWithRouterSubject.asObservable();
|
|
22279
22564
|
get inputConfig() {
|
|
22280
22565
|
return {
|
|
@@ -22357,7 +22642,6 @@ class QdSearchComponent {
|
|
|
22357
22642
|
}
|
|
22358
22643
|
}
|
|
22359
22644
|
ngOnDestroy() {
|
|
22360
|
-
this.searchRouterConnectorService.disconnectSearchFromRouter(this);
|
|
22361
22645
|
this._destroyed$.next();
|
|
22362
22646
|
this._destroyed$.complete();
|
|
22363
22647
|
}
|
|
@@ -22704,6 +22988,9 @@ class QdTableStoreSelectorService {
|
|
|
22704
22988
|
return sort.find(entry => entry.column === column)?.direction ?? QdSortDirection.NONE;
|
|
22705
22989
|
});
|
|
22706
22990
|
}
|
|
22991
|
+
tableSort() {
|
|
22992
|
+
return createSelector(this.selectTables, tables => this.getTable(tables)?.sort);
|
|
22993
|
+
}
|
|
22707
22994
|
selectIsLoading() {
|
|
22708
22995
|
return createSelector(this.selectTables, tables => {
|
|
22709
22996
|
const { requestState } = this.getTable(tables) || {};
|
|
@@ -22890,6 +23177,9 @@ class QdTableStoreService {
|
|
|
22890
23177
|
columnSortDirection$(column) {
|
|
22891
23178
|
return this.store.select(this.tableStoreSelectorService.columnSortDirection(column));
|
|
22892
23179
|
}
|
|
23180
|
+
tableSort$() {
|
|
23181
|
+
return this.store.select(this.tableStoreSelectorService.tableSort());
|
|
23182
|
+
}
|
|
22893
23183
|
selectIsLoading$() {
|
|
22894
23184
|
return this.store.select(this.tableStoreSelectorService.selectIsLoading());
|
|
22895
23185
|
}
|
|
@@ -23360,6 +23650,158 @@ var QdPaginatorDirection;
|
|
|
23360
23650
|
QdPaginatorDirection[QdPaginatorDirection["LastPage"] = 3] = "LastPage";
|
|
23361
23651
|
})(QdPaginatorDirection || (QdPaginatorDirection = {}));
|
|
23362
23652
|
|
|
23653
|
+
const PAGE_PARAM_NAME = 'page';
|
|
23654
|
+
const SIZE_PARAM_NAME = 'size';
|
|
23655
|
+
const OWNED_PARAMS$2 = [PAGE_PARAM_NAME, SIZE_PARAM_NAME];
|
|
23656
|
+
const FEATURE_LABEL$2 = { name: 'Table', plural: 'tables' };
|
|
23657
|
+
const SIZE_SANITY_MAX = 1000;
|
|
23658
|
+
/**
|
|
23659
|
+
* Per-view adapter that syncs `QdTablePaginatorComponent` page and size with the URL
|
|
23660
|
+
* `?page=` and `?size=` query params via `QdRouterQueryParamHubService`. Applies the URL
|
|
23661
|
+
* synchronously on connect (so cross-adapter store reducers cannot stomp on the deep-linked
|
|
23662
|
+
* page), then keeps store and URL in sync. Coordination, ownership, and write batching are
|
|
23663
|
+
* delegated to the hub — see its JSDoc for details. Behavior contracts live in
|
|
23664
|
+
* `pagination-router-connector.service.spec.ts` and `router-query-param-hub.integration.cy.ts`.
|
|
23665
|
+
*
|
|
23666
|
+
* Internal invariant: relies on `pageChangeInfo$()` and `totalCount$()` being
|
|
23667
|
+
* BehaviorSubject-backed selectors that emit their current value on subscribe. If either
|
|
23668
|
+
* becomes async (delay/debounce), the synchronous snapshot in `applyInitialUrlSynchronously`
|
|
23669
|
+
* stays at its initial default silently — the dispatch would always fire and the table would
|
|
23670
|
+
* flicker to "0 elements" on disconnect/reconnect cycles.
|
|
23671
|
+
*/
|
|
23672
|
+
class QdTablePaginationRouterConnectorService {
|
|
23673
|
+
_hub = inject(QdRouterQueryParamHubService);
|
|
23674
|
+
_destroyRef = inject(DestroyRef);
|
|
23675
|
+
_connection;
|
|
23676
|
+
_readSubscription;
|
|
23677
|
+
_writeSubscription;
|
|
23678
|
+
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
23679
|
+
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
23680
|
+
_hasInitialUrlBeenSet = false;
|
|
23681
|
+
constructor() {
|
|
23682
|
+
this._destroyRef.onDestroy(() => this.tearDownConnection());
|
|
23683
|
+
}
|
|
23684
|
+
connectPaginationWithRouter(paginator, tableStoreService) {
|
|
23685
|
+
if (!paginator.shouldConnectWithRouter() || !this._hub.isAvailable())
|
|
23686
|
+
return of(false);
|
|
23687
|
+
if (!this._hub.claim(OWNED_PARAMS$2, this, this._destroyRef, FEATURE_LABEL$2))
|
|
23688
|
+
return of(false);
|
|
23689
|
+
this._connection = {
|
|
23690
|
+
paginator: paginator,
|
|
23691
|
+
tableStoreService: tableStoreService
|
|
23692
|
+
};
|
|
23693
|
+
this._hasInitialUrlBeenSet = false;
|
|
23694
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
23695
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
23696
|
+
this.applyInitialUrlSynchronously();
|
|
23697
|
+
this.subscribeToUrlChanges();
|
|
23698
|
+
this.subscribeToStoreChanges();
|
|
23699
|
+
return this._activatedRouteChecked$;
|
|
23700
|
+
}
|
|
23701
|
+
applyInitialUrlSynchronously() {
|
|
23702
|
+
const { tableStoreService, paginator } = this._connection;
|
|
23703
|
+
const params = this.parseUrlParams({
|
|
23704
|
+
[PAGE_PARAM_NAME]: this._hub.snapshotQueryParam(PAGE_PARAM_NAME),
|
|
23705
|
+
[SIZE_PARAM_NAME]: this._hub.snapshotQueryParam(SIZE_PARAM_NAME)
|
|
23706
|
+
});
|
|
23707
|
+
const pageSize = params.size ?? paginator.getPageSizeDefault();
|
|
23708
|
+
const pageIndex = params.page !== undefined ? params.page - 1 : 0;
|
|
23709
|
+
let currentInfo;
|
|
23710
|
+
let currentTotalCount = 0;
|
|
23711
|
+
tableStoreService
|
|
23712
|
+
.pageChangeInfo$()
|
|
23713
|
+
.pipe(take(1))
|
|
23714
|
+
.subscribe(info => (currentInfo = info));
|
|
23715
|
+
tableStoreService
|
|
23716
|
+
.totalCount$()
|
|
23717
|
+
.pipe(take(1))
|
|
23718
|
+
.subscribe(value => (currentTotalCount = value));
|
|
23719
|
+
if (currentInfo && currentInfo.pageIndex === pageIndex && currentInfo.pageSize === pageSize)
|
|
23720
|
+
return;
|
|
23721
|
+
tableStoreService.setPageParams(pageIndex, pageSize, currentTotalCount);
|
|
23722
|
+
}
|
|
23723
|
+
tearDownConnection() {
|
|
23724
|
+
this._connection = undefined;
|
|
23725
|
+
this._hasInitialUrlBeenSet = false;
|
|
23726
|
+
this._readSubscription?.unsubscribe();
|
|
23727
|
+
this._writeSubscription?.unsubscribe();
|
|
23728
|
+
}
|
|
23729
|
+
subscribeToUrlChanges() {
|
|
23730
|
+
const { tableStoreService } = this._connection;
|
|
23731
|
+
let isFirstEmit = true;
|
|
23732
|
+
this._readSubscription = this._hub.navigationSettled$
|
|
23733
|
+
.pipe(switchMap(() => this._hub.queryParams()), map(queryParams => this.parseUrlParams(queryParams)), distinctUntilChanged((a, b) => a.page === b.page && a.size === b.size), switchMap(params => combineLatest([tableStoreService.pageChangeInfo$(), tableStoreService.totalCount$()]).pipe(take(1), map(([currentInfo, totalCount]) => ({ params, currentInfo, totalCount })))))
|
|
23734
|
+
.subscribe(({ params, currentInfo, totalCount }) => {
|
|
23735
|
+
const target = this.toStoreState(params);
|
|
23736
|
+
const isChanged = !currentInfo || currentInfo.pageIndex !== target.pageIndex || currentInfo.pageSize !== target.pageSize;
|
|
23737
|
+
if (isChanged) {
|
|
23738
|
+
tableStoreService.setPageParams(target.pageIndex, target.pageSize, totalCount);
|
|
23739
|
+
}
|
|
23740
|
+
if (isFirstEmit) {
|
|
23741
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
23742
|
+
isFirstEmit = false;
|
|
23743
|
+
}
|
|
23744
|
+
});
|
|
23745
|
+
}
|
|
23746
|
+
subscribeToStoreChanges() {
|
|
23747
|
+
const { tableStoreService } = this._connection;
|
|
23748
|
+
this._writeSubscription = tableStoreService
|
|
23749
|
+
.pageChangeInfo$()
|
|
23750
|
+
.pipe(filter((info) => info !== undefined), distinctUntilChanged((a, b) => a.pageIndex === b.pageIndex && a.pageSize === b.pageSize), switchMap(info => this._hub.navigationSettled$.pipe(take(1), map(() => info))))
|
|
23751
|
+
.subscribe(info => this.writeUrl(info.pageIndex, info.pageSize));
|
|
23752
|
+
}
|
|
23753
|
+
writeUrl(pageIndex, pageSize) {
|
|
23754
|
+
const replaceUrl = !this._hasInitialUrlBeenSet;
|
|
23755
|
+
this._hasInitialUrlBeenSet = true;
|
|
23756
|
+
const targetPage = String(pageIndex + 1);
|
|
23757
|
+
const targetSize = String(pageSize);
|
|
23758
|
+
const urlAlreadyMatches = this._hub.snapshotQueryParam(PAGE_PARAM_NAME) === targetPage &&
|
|
23759
|
+
this._hub.snapshotQueryParam(SIZE_PARAM_NAME) === targetSize;
|
|
23760
|
+
if (urlAlreadyMatches)
|
|
23761
|
+
return;
|
|
23762
|
+
this._hub.write({ [PAGE_PARAM_NAME]: targetPage, [SIZE_PARAM_NAME]: targetSize }, { replaceUrl });
|
|
23763
|
+
}
|
|
23764
|
+
parseUrlParams(queryParams) {
|
|
23765
|
+
const result = {};
|
|
23766
|
+
const rawPage = queryParams[PAGE_PARAM_NAME];
|
|
23767
|
+
if (typeof rawPage === 'string' && this.isValidPositiveIntegerString(rawPage)) {
|
|
23768
|
+
result.page = Number(rawPage);
|
|
23769
|
+
}
|
|
23770
|
+
const rawSize = queryParams[SIZE_PARAM_NAME];
|
|
23771
|
+
if (typeof rawSize === 'string' &&
|
|
23772
|
+
this.isValidPositiveIntegerString(rawSize) &&
|
|
23773
|
+
this.isValidSize(Number(rawSize))) {
|
|
23774
|
+
result.size = Number(rawSize);
|
|
23775
|
+
}
|
|
23776
|
+
return result;
|
|
23777
|
+
}
|
|
23778
|
+
isValidPositiveIntegerString(raw) {
|
|
23779
|
+
return /^[1-9]\d*$/.test(raw);
|
|
23780
|
+
}
|
|
23781
|
+
isValidSize(value) {
|
|
23782
|
+
const pageSizes = this.getConfiguredPageSizes();
|
|
23783
|
+
if (pageSizes && pageSizes.length > 0)
|
|
23784
|
+
return pageSizes.includes(value);
|
|
23785
|
+
return value <= SIZE_SANITY_MAX;
|
|
23786
|
+
}
|
|
23787
|
+
getConfiguredPageSizes() {
|
|
23788
|
+
const pagination = this._connection?.paginator.config?.pagination;
|
|
23789
|
+
return typeof pagination === 'object' ? pagination.pageSizes : undefined;
|
|
23790
|
+
}
|
|
23791
|
+
toStoreState(params) {
|
|
23792
|
+
const { paginator } = this._connection;
|
|
23793
|
+
return {
|
|
23794
|
+
pageIndex: params.page !== undefined ? params.page - 1 : 0,
|
|
23795
|
+
pageSize: params.size ?? paginator.getPageSizeDefault()
|
|
23796
|
+
};
|
|
23797
|
+
}
|
|
23798
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
23799
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService });
|
|
23800
|
+
}
|
|
23801
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService, decorators: [{
|
|
23802
|
+
type: Injectable
|
|
23803
|
+
}], ctorParameters: () => [] });
|
|
23804
|
+
|
|
23363
23805
|
class QdScrollingService {
|
|
23364
23806
|
scrollIntoViewIfNeeded(element, borderDirection = 'top', targetBorderDistance = 0) {
|
|
23365
23807
|
this.scrollIntoView(element, borderDirection, targetBorderDistance, true);
|
|
@@ -23588,6 +24030,7 @@ const PAGE_SIZE_DEFAULT = 25;
|
|
|
23588
24030
|
class QdTablePaginatorComponent {
|
|
23589
24031
|
tableDataResolver = inject(QD_TABLE_DATA_RESOLVER_TOKEN, { optional: true });
|
|
23590
24032
|
tableStoreService = inject(QdTableStoreService);
|
|
24033
|
+
routerConnector = inject(QdTablePaginationRouterConnectorService);
|
|
23591
24034
|
/**
|
|
23592
24035
|
* @description Configuration Model for Qd-Table.
|
|
23593
24036
|
*/
|
|
@@ -23624,11 +24067,38 @@ class QdTablePaginatorComponent {
|
|
|
23624
24067
|
this.totalCount$ = this.tableStoreService.totalCount$();
|
|
23625
24068
|
this.selectedRowsCount$ = this.tableStoreService.selectedRows$().pipe(map(ids => ids?.length ?? 0));
|
|
23626
24069
|
if (this.isConfigValid())
|
|
23627
|
-
this.
|
|
24070
|
+
this.startPagination();
|
|
23628
24071
|
}
|
|
23629
24072
|
ngOnDestroy() {
|
|
24073
|
+
this._destroyed$.next(null);
|
|
23630
24074
|
this._destroyed$.complete();
|
|
23631
24075
|
}
|
|
24076
|
+
/**
|
|
24077
|
+
* @description Whether this paginator should sync its state with the URL. Reads
|
|
24078
|
+
* `pagination.connectWithRouter` (default `false` — URL sync is opt-in and
|
|
24079
|
+
* requires an explicit `pagination: { connectWithRouter: true }`).
|
|
24080
|
+
*
|
|
24081
|
+
* Used by `QdTablePaginationRouterConnectorService` to decide whether to claim
|
|
24082
|
+
* the router-singleton for this paginator.
|
|
24083
|
+
*/
|
|
24084
|
+
shouldConnectWithRouter() {
|
|
24085
|
+
const pagination = this.config?.pagination;
|
|
24086
|
+
if (typeof pagination !== 'object')
|
|
24087
|
+
return false;
|
|
24088
|
+
return pagination.connectWithRouter === true;
|
|
24089
|
+
}
|
|
24090
|
+
/**
|
|
24091
|
+
* @description The effective default page size for this paginator. Resolves
|
|
24092
|
+
* `pagination.pageSizeDefault` first, then falls back to the first entry of
|
|
24093
|
+
* `pagination.pageSizes`, finally to the framework constant `PAGE_SIZE_DEFAULT`.
|
|
24094
|
+
*/
|
|
24095
|
+
getPageSizeDefault() {
|
|
24096
|
+
if (typeof this.config?.pagination !== 'object')
|
|
24097
|
+
return PAGE_SIZE_DEFAULT;
|
|
24098
|
+
const { pageSizeDefault, pageSizes } = this.config.pagination;
|
|
24099
|
+
const pageSize = pageSizes && pageSizes.length ? pageSizes[0] : PAGE_SIZE_DEFAULT;
|
|
24100
|
+
return pageSizeDefault || pageSize;
|
|
24101
|
+
}
|
|
23632
24102
|
navigateToPage(direction) {
|
|
23633
24103
|
if (!this.paginatorButtons)
|
|
23634
24104
|
return;
|
|
@@ -23649,16 +24119,22 @@ class QdTablePaginatorComponent {
|
|
|
23649
24119
|
}
|
|
23650
24120
|
return true;
|
|
23651
24121
|
}
|
|
24122
|
+
startPagination() {
|
|
24123
|
+
if (!this.shouldConnectWithRouter()) {
|
|
24124
|
+
this.initPagination();
|
|
24125
|
+
return;
|
|
24126
|
+
}
|
|
24127
|
+
this.routerConnector
|
|
24128
|
+
.connectPaginationWithRouter(this, this.tableStoreService)
|
|
24129
|
+
.pipe(takeUntil(this._destroyed$), first())
|
|
24130
|
+
.subscribe(connected => {
|
|
24131
|
+
if (!connected)
|
|
24132
|
+
this.initPagination();
|
|
24133
|
+
});
|
|
24134
|
+
}
|
|
23652
24135
|
initPagination() {
|
|
23653
24136
|
this.tableStoreService.setupPagination(this.getPageSizeDefault());
|
|
23654
24137
|
}
|
|
23655
|
-
getPageSizeDefault() {
|
|
23656
|
-
if (typeof this.config?.pagination !== 'object')
|
|
23657
|
-
return PAGE_SIZE_DEFAULT;
|
|
23658
|
-
const { pageSizeDefault, pageSizes } = this.config.pagination;
|
|
23659
|
-
const pageSize = pageSizes && pageSizes.length ? pageSizes[0] : PAGE_SIZE_DEFAULT;
|
|
23660
|
-
return pageSizeDefault || pageSize;
|
|
23661
|
-
}
|
|
23662
24138
|
calculatePageNumber(direction, totalCount, pageSize, currentPage) {
|
|
23663
24139
|
switch (direction) {
|
|
23664
24140
|
case QdPaginatorDirection.NextPage: {
|
|
@@ -23677,11 +24153,11 @@ class QdTablePaginatorComponent {
|
|
|
23677
24153
|
}
|
|
23678
24154
|
}
|
|
23679
24155
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23680
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdTablePaginatorComponent, isStandalone: false, selector: "qd-table-paginator", inputs: { config: "config", testId: ["data-test-id", "testId"] }, viewQueries: [{ propertyName: "paginatorButtons", first: true, predicate: ["paginatorButtons"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdScrollToPaginationDirective, selector: "[qdScrollToPagination]" }, { kind: "component", type: QdTablePaginatorPageSizeComponent, selector: "qd-table-paginator-page-size", inputs: ["pageSizes"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
24156
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdTablePaginatorComponent, isStandalone: false, selector: "qd-table-paginator", inputs: { config: "config", testId: ["data-test-id", "testId"] }, providers: [QdTablePaginationRouterConnectorService], viewQueries: [{ propertyName: "paginatorButtons", first: true, predicate: ["paginatorButtons"], descendants: true }], ngImport: i0, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdScrollToPaginationDirective, selector: "[qdScrollToPagination]" }, { kind: "component", type: QdTablePaginatorPageSizeComponent, selector: "qd-table-paginator-page-size", inputs: ["pageSizes"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
23681
24157
|
}
|
|
23682
24158
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginatorComponent, decorators: [{
|
|
23683
24159
|
type: Component,
|
|
23684
|
-
args: [{ selector: 'qd-table-paginator', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"] }]
|
|
24160
|
+
args: [{ selector: 'qd-table-paginator', providers: [QdTablePaginationRouterConnectorService], changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<ng-container *ngIf=\"hasData$ | async\">\n <qd-table-paginator-page-size [pageSizes]=\"pageSizes\" *ngIf=\"pageSizes.length > 0\"></qd-table-paginator-page-size>\n <span class=\"paginator-current-page\" *ngIf=\"currentPage$ | async as page\">\n {{ page.start }}\u2014{{ page.end }}\n {{ \"i18n.qd.table.pagination.of\" | translate }}\n {{ page.totalCount }}\n {{\n page.totalCount === 1\n ? (\"i18n.qd.table.pagination.entry\" | translate)\n : (\"i18n.qd.table.pagination.entries\" | translate)\n }}\n </span>\n <span\n *ngIf=\"{ count: (selectedRowsCount$ | async) ?? 0 } as ctx\"\n [hidden]=\"ctx.count === 0 || config?.selection?.type !== 'multiSelect'\"\n class=\"paginator-selection-count\"\n [attr.data-test-id]=\"testId + '-paginator-selection-count'\"\n >\n {{\n ctx.count === 1\n ? (\"i18n.qd.table.pagination.selectedSingular\" | translate)\n : (\"i18n.qd.table.pagination.selectedPlural\" | translate : { count: ctx.count })\n }}\n </span>\n <span class=\"paginator-buttons\" data-test=\"paginator-buttons\" #paginatorButtons qdScrollToPagination>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-first-page'\"\n (click)=\"navigateToPage(pageNav.FirstPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageFirst1'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-backward'\"\n (click)=\"navigateToPage(pageNav.PreviousPage)\"\n [disabled]=\"(canPageBackward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleLeftSolid'\"></qd-icon>\n </button>\n <button\n class=\"paginator-button forward\"\n [attr.data-test-id]=\"testId + '-paginator-forward'\"\n (click)=\"navigateToPage(pageNav.NextPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'triangleRightSolid'\"></qd-icon>\n </button>\n <button\n *ngIf=\"config?.pagination['hasFirstLastPageNavigation']\"\n class=\"paginator-button\"\n [attr.data-test-id]=\"testId + '-paginator-last-page'\"\n (click)=\"navigateToPage(pageNav.LastPage)\"\n [disabled]=\"(canPageForward$ | async) === false\"\n >\n <qd-icon [icon]=\"'pageLast'\"></qd-icon>\n </button>\n </span>\n</ng-container>\n", styles: [":host{color:#454545;font-size:.875rem;font-weight:400;line-height:1.3125rem;display:flex;flex-direction:row;align-items:center;justify-content:space-between;background-color:#fff}.paginator-current-page{margin-left:1rem}.paginator-selection-count{margin-right:1rem;margin-left:1rem}.paginator-buttons{margin-left:auto;text-align:right;white-space:nowrap}button.paginator-button{width:2.75rem;height:2.75rem;border-left:.0625rem solid rgb(229,229,229);background-color:unset;color:#454545;font-size:1.5rem}button.paginator-button:disabled{color:#b4b4b4;cursor:default}button.paginator-button:not(:disabled):hover{background-color:#e5e5e5;color:#171717}\n"] }]
|
|
23685
24161
|
}], propDecorators: { config: [{
|
|
23686
24162
|
type: Input
|
|
23687
24163
|
}], testId: [{
|
|
@@ -23692,6 +24168,161 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
23692
24168
|
args: ['paginatorButtons']
|
|
23693
24169
|
}] } });
|
|
23694
24170
|
|
|
24171
|
+
const SORT_PARAM_NAME = 'sort';
|
|
24172
|
+
const OWNED_PARAMS$1 = [SORT_PARAM_NAME];
|
|
24173
|
+
const FEATURE_LABEL$1 = { name: 'Table', plural: 'tables' };
|
|
24174
|
+
const SEGMENT_SEPARATOR = ',';
|
|
24175
|
+
const COLUMN_DIRECTION_SEPARATOR = '.';
|
|
24176
|
+
/**
|
|
24177
|
+
* Per-view adapter that syncs `QdTableComponent` sort state with the URL `?sort=` query
|
|
24178
|
+
* param via `QdRouterQueryParamHubService`. Reads/parses on activation (single segment
|
|
24179
|
+
* only; multi-segment URLs use the first valid entry and warn), writes when the store's
|
|
24180
|
+
* `tableSort$` selector emits. Coordination, ownership, and write batching are delegated
|
|
24181
|
+
* to the hub — see its JSDoc for details. Behavior contracts live in
|
|
24182
|
+
* `sort-router-connector.service.spec.ts` and `router-query-param-hub.integration.cy.ts`.
|
|
24183
|
+
*
|
|
24184
|
+
* Internal invariant: relies on `tableSort$()` being a BehaviorSubject-backed selector that
|
|
24185
|
+
* emits its current value on subscribe. The URL-read pipeline pairs each segments emission
|
|
24186
|
+
* with the latest sort snapshot via `withLatestFrom`; if the selector ever becomes async
|
|
24187
|
+
* (delay/debounce), `withLatestFrom` drops the outer emission until the snapshot arrives
|
|
24188
|
+
* and URL-driven sort changes are silently lost.
|
|
24189
|
+
*/
|
|
24190
|
+
class QdTableSortRouterConnectorService {
|
|
24191
|
+
_hub = inject(QdRouterQueryParamHubService);
|
|
24192
|
+
_destroyRef = inject(DestroyRef);
|
|
24193
|
+
_connection;
|
|
24194
|
+
_readSubscription;
|
|
24195
|
+
_writeSubscription;
|
|
24196
|
+
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
24197
|
+
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
24198
|
+
_hasInitialUrlBeenSet = false;
|
|
24199
|
+
_hasWarnedMultiSegment = false;
|
|
24200
|
+
constructor() {
|
|
24201
|
+
this._destroyRef.onDestroy(() => this.tearDownConnection());
|
|
24202
|
+
}
|
|
24203
|
+
connectSortWithRouter(table, tableStoreService) {
|
|
24204
|
+
if (!this.shouldConnect(table) || !this._hub.isAvailable())
|
|
24205
|
+
return of(false);
|
|
24206
|
+
if (!this._hub.claim(OWNED_PARAMS$1, this, this._destroyRef, FEATURE_LABEL$1))
|
|
24207
|
+
return of(false);
|
|
24208
|
+
this._connection = {
|
|
24209
|
+
table: table,
|
|
24210
|
+
tableStoreService: tableStoreService,
|
|
24211
|
+
configuredColumns: table.config.columns
|
|
24212
|
+
};
|
|
24213
|
+
this._hasInitialUrlBeenSet = false;
|
|
24214
|
+
this._hasWarnedMultiSegment = false;
|
|
24215
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
24216
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
24217
|
+
this.subscribeToUrlChanges();
|
|
24218
|
+
this.subscribeToStoreChanges();
|
|
24219
|
+
return this._activatedRouteChecked$;
|
|
24220
|
+
}
|
|
24221
|
+
tearDownConnection() {
|
|
24222
|
+
this._connection = undefined;
|
|
24223
|
+
this._hasInitialUrlBeenSet = false;
|
|
24224
|
+
this._hasWarnedMultiSegment = false;
|
|
24225
|
+
this._readSubscription?.unsubscribe();
|
|
24226
|
+
this._writeSubscription?.unsubscribe();
|
|
24227
|
+
}
|
|
24228
|
+
subscribeToUrlChanges() {
|
|
24229
|
+
const { tableStoreService } = this._connection;
|
|
24230
|
+
let isFirstEmit = true;
|
|
24231
|
+
this._readSubscription = this._hub.navigationSettled$
|
|
24232
|
+
.pipe(switchMap(() => this._hub.queryParams()), map(queryParams => (typeof queryParams[SORT_PARAM_NAME] === 'string' ? queryParams[SORT_PARAM_NAME] : '')), distinctUntilChanged(), map(raw => this.parseRawSortValue(raw)), withLatestFrom(tableStoreService.tableSort$()))
|
|
24233
|
+
.subscribe(([segments, currentSort]) => {
|
|
24234
|
+
if (segments.length === 1) {
|
|
24235
|
+
const [{ column, direction }] = segments;
|
|
24236
|
+
if (!this.isSameAsCurrentSort(currentSort, column, direction)) {
|
|
24237
|
+
tableStoreService.setSort(column, direction);
|
|
24238
|
+
}
|
|
24239
|
+
}
|
|
24240
|
+
if (isFirstEmit) {
|
|
24241
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
24242
|
+
isFirstEmit = false;
|
|
24243
|
+
}
|
|
24244
|
+
});
|
|
24245
|
+
}
|
|
24246
|
+
isSameAsCurrentSort(currentSort, column, direction) {
|
|
24247
|
+
if (!currentSort)
|
|
24248
|
+
return false;
|
|
24249
|
+
const active = currentSort.filter(entry => entry.direction !== QdSortDirection.NONE);
|
|
24250
|
+
return active.length === 1 && active[0].column === column && active[0].direction === direction;
|
|
24251
|
+
}
|
|
24252
|
+
subscribeToStoreChanges() {
|
|
24253
|
+
const { tableStoreService } = this._connection;
|
|
24254
|
+
this._writeSubscription = tableStoreService
|
|
24255
|
+
.tableSort$()
|
|
24256
|
+
.pipe(filter((sort) => Array.isArray(sort)), map(sort => this.serializeSort(sort)), distinctUntilChanged(), switchMap(serialized => this._hub.navigationSettled$.pipe(take(1), map(() => serialized))))
|
|
24257
|
+
.subscribe(serialized => this.writeUrl(serialized));
|
|
24258
|
+
}
|
|
24259
|
+
writeUrl(serialized) {
|
|
24260
|
+
const replaceUrl = !this._hasInitialUrlBeenSet;
|
|
24261
|
+
this._hasInitialUrlBeenSet = true;
|
|
24262
|
+
if (this._hub.snapshotQueryParam(SORT_PARAM_NAME) === serialized)
|
|
24263
|
+
return;
|
|
24264
|
+
this._hub.write({ [SORT_PARAM_NAME]: serialized }, { replaceUrl });
|
|
24265
|
+
}
|
|
24266
|
+
shouldConnect(table) {
|
|
24267
|
+
const sortConfig = table.config.sort;
|
|
24268
|
+
if (sortConfig === true || sortConfig === undefined)
|
|
24269
|
+
return false;
|
|
24270
|
+
return sortConfig.connectWithRouter === true;
|
|
24271
|
+
}
|
|
24272
|
+
parseRawSortValue(raw) {
|
|
24273
|
+
if (raw.length === 0)
|
|
24274
|
+
return [];
|
|
24275
|
+
const rawSegments = raw.split(SEGMENT_SEPARATOR);
|
|
24276
|
+
const validSegments = rawSegments
|
|
24277
|
+
.map(segment => this.parseSegment(segment))
|
|
24278
|
+
.filter((segment) => segment !== undefined);
|
|
24279
|
+
if (validSegments.length > 1) {
|
|
24280
|
+
if (!this._hasWarnedMultiSegment) {
|
|
24281
|
+
console.warn('Quadrel Framework | QdTable - Multi-column sort URL is not yet supported. Using first valid segment only.');
|
|
24282
|
+
this._hasWarnedMultiSegment = true;
|
|
24283
|
+
}
|
|
24284
|
+
return [validSegments[0]];
|
|
24285
|
+
}
|
|
24286
|
+
return validSegments;
|
|
24287
|
+
}
|
|
24288
|
+
parseSegment(segment) {
|
|
24289
|
+
if (segment.length === 0)
|
|
24290
|
+
return undefined;
|
|
24291
|
+
const separatorIndex = segment.indexOf(COLUMN_DIRECTION_SEPARATOR);
|
|
24292
|
+
if (separatorIndex <= 0 || separatorIndex === segment.length - 1)
|
|
24293
|
+
return undefined;
|
|
24294
|
+
const column = segment.slice(0, separatorIndex);
|
|
24295
|
+
const directionRaw = segment.slice(separatorIndex + 1).toLowerCase();
|
|
24296
|
+
if (!this.isValidColumn(column))
|
|
24297
|
+
return undefined;
|
|
24298
|
+
if (directionRaw === 'asc')
|
|
24299
|
+
return { column, direction: QdSortDirection.ASC };
|
|
24300
|
+
if (directionRaw === 'desc')
|
|
24301
|
+
return { column, direction: QdSortDirection.DESC };
|
|
24302
|
+
return undefined;
|
|
24303
|
+
}
|
|
24304
|
+
isValidColumn(column) {
|
|
24305
|
+
const config = this._connection?.configuredColumns.find(c => c.column === column);
|
|
24306
|
+
return !!config && config.sort !== undefined && config.sort.isDisabled !== true;
|
|
24307
|
+
}
|
|
24308
|
+
serializeSort(sort) {
|
|
24309
|
+
const active = sort.filter((entry) => entry.direction === QdSortDirection.ASC || entry.direction === QdSortDirection.DESC);
|
|
24310
|
+
if (active.length === 0)
|
|
24311
|
+
return undefined;
|
|
24312
|
+
return active
|
|
24313
|
+
.map(entry => `${entry.column}${COLUMN_DIRECTION_SEPARATOR}${this.directionToString(entry.direction)}`)
|
|
24314
|
+
.join(SEGMENT_SEPARATOR);
|
|
24315
|
+
}
|
|
24316
|
+
directionToString(direction) {
|
|
24317
|
+
return direction === QdSortDirection.ASC ? 'asc' : 'desc';
|
|
24318
|
+
}
|
|
24319
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
24320
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService });
|
|
24321
|
+
}
|
|
24322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService, decorators: [{
|
|
24323
|
+
type: Injectable
|
|
24324
|
+
}], ctorParameters: () => [] });
|
|
24325
|
+
|
|
23695
24326
|
class QdTableRowActionsSecondaryMenuComponent {
|
|
23696
24327
|
actionsService = inject(QdTableSecondaryActionsService);
|
|
23697
24328
|
tableStore = inject(QdTableStoreService);
|
|
@@ -24307,6 +24938,7 @@ class QdTableComponent {
|
|
|
24307
24938
|
breakpointService = inject(QdBreakpointService);
|
|
24308
24939
|
resolverService = inject(QdTableResolverService);
|
|
24309
24940
|
confirmationDialogService = inject(QdConfirmationDialogOpenerService);
|
|
24941
|
+
sortRouterConnector = inject(QdTableSortRouterConnectorService);
|
|
24310
24942
|
/**
|
|
24311
24943
|
* Configuration of the table. The generic type specifies the column definition. <br />
|
|
24312
24944
|
*
|
|
@@ -24414,6 +25046,7 @@ class QdTableComponent {
|
|
|
24414
25046
|
this.tableStoreService.initTableState(this._data, this.hasResolver, this._connectors, this.hasPagination);
|
|
24415
25047
|
this.tableStoreService.updateTableStateRecentSecondaryAction(undefined);
|
|
24416
25048
|
this.tableStoreService.setupSort(this.config.columns);
|
|
25049
|
+
this.sortRouterConnector.connectSortWithRouter(this, this.tableStoreService).pipe(take(1)).subscribe();
|
|
24417
25050
|
this.resolverService.init(this.config.refreshOnLanguageChange, this.hasPagination);
|
|
24418
25051
|
this.data$ = this.tableStoreService.tableDataEntries$();
|
|
24419
25052
|
this.initializeResponsiveRowService();
|
|
@@ -24613,7 +25246,8 @@ class QdTableComponent {
|
|
|
24613
25246
|
QdTableRowSelectionService,
|
|
24614
25247
|
QdTableFillingWidthService,
|
|
24615
25248
|
QdTableResolverService,
|
|
24616
|
-
QdTableExternalActionResultService
|
|
25249
|
+
QdTableExternalActionResultService,
|
|
25250
|
+
QdTableSortRouterConnectorService
|
|
24617
25251
|
], viewQueries: [{ propertyName: "paginator", first: true, predicate: QdTablePaginatorComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<table [class]=\"'qd-table__table'\">\n <tr qd-table-head [config]=\"config\" [data-test-id]=\"testId\"></tr>\n <tbody qd-table-body [config]=\"config\" [data]=\"(data$ | async) ?? []\" [data-test-id]=\"testId\"></tbody>\n</table>\n\n<qd-table-paginator [config]=\"config\" [data-test-id]=\"testId\" *ngIf=\"hasPagination\"></qd-table-paginator>\n<qd-table-empty-state *ngIf=\"hasEmptyStateView$ | async\" [config]=\"config.emptyStateView\"></qd-table-empty-state>\n", styles: [":host{display:inline-flex;flex-direction:column}:host .qd-table__table{background:#fff;border-spacing:0;color:#171717;font-size:.875rem;font-weight:400;line-height:2.5rem}:host .qd-table__head,:host .qd-table__body{vertical-align:center}:host .qd-table__head{background:#e5e5e5;text-align:left}:host .qd-table__head ::ng-deep .qd-table__head-cell{font-weight:600}:host .qd-table__body{color:#171717}:host ::ng-deep .qd-table__head-cell,:host ::ng-deep .qd-table__body-cell{padding:.125rem 1rem 0;vertical-align:top}:host ::ng-deep .qd-table__head-cell--selection,:host ::ng-deep .qd-table__body-cell--selection{width:1.875rem;padding-top:.1875rem;text-align:center}:host ::ng-deep .qd-table__head-cell--actions-inline-menu,:host ::ng-deep .qd-table__body-cell--actions-inline-menu{padding-top:.125rem;vertical-align:top}:host.main-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep th.main-column,:host.main-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep td.main-column{width:100%}:host.main-column-fills-width.table-has-remaining-width ::ng-deep th:not(.main-column),:host.main-column-fills-width.table-has-remaining-width ::ng-deep td:not(.main-column){white-space:nowrap}:host.last-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep th.last-column,:host.last-column-fills-width.table-has-remaining-width:not(.table-has-right-aligned-filling-column) ::ng-deep td.last-column{width:100%}:host.last-column-fills-width.table-has-remaining-width ::ng-deep th:not(.last-column),:host.last-column-fills-width.table-has-remaining-width ::ng-deep td:not(.last-column){white-space:nowrap}:host.harmonized{width:100%}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdTableBodyComponent, selector: "[qd-table-body]", inputs: ["config", "data", "data-test-id"] }, { kind: "component", type: QdTableEmptyStateComponent, selector: "qd-table-empty-state", inputs: ["config"] }, { kind: "component", type: QdTableHeadComponent, selector: "[qd-table-head]", inputs: ["config", "data-test-id"] }, { kind: "component", type: QdTablePaginatorComponent, selector: "qd-table-paginator", inputs: ["config", "data-test-id"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
24618
25252
|
}
|
|
24619
25253
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableComponent, decorators: [{
|
|
@@ -24627,7 +25261,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
24627
25261
|
QdTableRowSelectionService,
|
|
24628
25262
|
QdTableFillingWidthService,
|
|
24629
25263
|
QdTableResolverService,
|
|
24630
|
-
QdTableExternalActionResultService
|
|
25264
|
+
QdTableExternalActionResultService,
|
|
25265
|
+
QdTableSortRouterConnectorService
|
|
24631
25266
|
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
24632
25267
|
'[class.qd-table]': 'true',
|
|
24633
25268
|
'[class.main-column-fills-width]': 'whichColumnFillsWidth === "main"',
|
|
@@ -28576,6 +29211,149 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
28576
29211
|
args: ['data-test-id']
|
|
28577
29212
|
}] } });
|
|
28578
29213
|
|
|
29214
|
+
const TAB_PARAM_NAME = 'tab';
|
|
29215
|
+
const OWNED_PARAMS = [TAB_PARAM_NAME];
|
|
29216
|
+
const FEATURE_LABEL = { name: 'Page Tabs', plural: 'page tabs' };
|
|
29217
|
+
/**
|
|
29218
|
+
* Per-view adapter that syncs `QdPageTabsComponent` selection with the URL `?tab=` query
|
|
29219
|
+
* param via `QdRouterQueryParamHubService`. Reads on activation and selects the matching
|
|
29220
|
+
* tab (with fallback for unknown/disabled names), writes on `selectionChange`. Coordination,
|
|
29221
|
+
* ownership, and write batching are delegated to the hub — see its JSDoc for details.
|
|
29222
|
+
* Behavior contracts live in `page-tabs-router-connector.service.spec.ts` and
|
|
29223
|
+
* `router-query-param-hub.integration.cy.ts`.
|
|
29224
|
+
*
|
|
29225
|
+
* Note: this is the only connector that writes synchronously without gating on
|
|
29226
|
+
* `navigationSettled$`. Required for the deep-link case where `ngAfterViewInit` fires
|
|
29227
|
+
* before the initial NavigationEnd is replayed — gating there would hang the click-driven
|
|
29228
|
+
* write pipeline (see commit 57f0a271a).
|
|
29229
|
+
*
|
|
29230
|
+
* Internal invariant: when the requested tab is unknown or disabled, `selectFallbackTab()`
|
|
29231
|
+
* writes the URL explicitly. CdkStepper does not emit `selectionChange` if the fallback is
|
|
29232
|
+
* already the selected step, so without the explicit write deep-links like `?tab=phantom`
|
|
29233
|
+
* would leave a stale param in the URL.
|
|
29234
|
+
*/
|
|
29235
|
+
class QdPageTabsRouterConnectorService {
|
|
29236
|
+
_hub = inject(QdRouterQueryParamHubService);
|
|
29237
|
+
_destroyRef = inject(DestroyRef);
|
|
29238
|
+
_connectedComponent;
|
|
29239
|
+
_readSubscription;
|
|
29240
|
+
_writeSubscription;
|
|
29241
|
+
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
29242
|
+
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
29243
|
+
_hasInitialUrlBeenSet = false;
|
|
29244
|
+
constructor() {
|
|
29245
|
+
this._destroyRef.onDestroy(() => this.tearDownConnection());
|
|
29246
|
+
}
|
|
29247
|
+
connectTabsWithRouter(component) {
|
|
29248
|
+
if (component.config?.connectWithRouter !== true || !this._hub.isAvailable())
|
|
29249
|
+
return of(false);
|
|
29250
|
+
if (this._connectedComponent === component)
|
|
29251
|
+
return this._activatedRouteChecked$;
|
|
29252
|
+
if (!this._hub.claim(OWNED_PARAMS, this, this._destroyRef, FEATURE_LABEL))
|
|
29253
|
+
return of(false);
|
|
29254
|
+
this._connectedComponent = component;
|
|
29255
|
+
this._hasInitialUrlBeenSet = false;
|
|
29256
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
29257
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
29258
|
+
this.subscribeToTabChanges();
|
|
29259
|
+
this.subscribeToUrlChanges();
|
|
29260
|
+
return this._activatedRouteChecked$;
|
|
29261
|
+
}
|
|
29262
|
+
tearDownConnection() {
|
|
29263
|
+
this._connectedComponent = undefined;
|
|
29264
|
+
this._hasInitialUrlBeenSet = false;
|
|
29265
|
+
this._readSubscription?.unsubscribe();
|
|
29266
|
+
this._writeSubscription?.unsubscribe();
|
|
29267
|
+
}
|
|
29268
|
+
subscribeToUrlChanges() {
|
|
29269
|
+
let isFirstEmit = true;
|
|
29270
|
+
this._readSubscription = this._hub.navigationSettled$
|
|
29271
|
+
.pipe(switchMap(() => this._hub.queryParams()), map(queryParams => queryParams[TAB_PARAM_NAME]), distinctUntilChanged(), takeUntilDestroyed(this._destroyRef))
|
|
29272
|
+
.subscribe(rawTabName => {
|
|
29273
|
+
this.applyTabFromUrl(rawTabName);
|
|
29274
|
+
if (isFirstEmit) {
|
|
29275
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
29276
|
+
isFirstEmit = false;
|
|
29277
|
+
}
|
|
29278
|
+
});
|
|
29279
|
+
}
|
|
29280
|
+
subscribeToTabChanges() {
|
|
29281
|
+
const component = this._connectedComponent;
|
|
29282
|
+
this._writeSubscription = component.selectionChange
|
|
29283
|
+
.pipe(map(event => event.selectedStep?.config?.name), takeUntilDestroyed(this._destroyRef))
|
|
29284
|
+
.subscribe(name => this.writeUrl(name));
|
|
29285
|
+
}
|
|
29286
|
+
writeUrl(name) {
|
|
29287
|
+
if (!name) {
|
|
29288
|
+
console.warn('Quadrel Framework | QdPageTabs - "connectWithRouter" is active, however the selected <qd-page-tab> has no "name" attribute.');
|
|
29289
|
+
return;
|
|
29290
|
+
}
|
|
29291
|
+
const replaceUrl = !this._hasInitialUrlBeenSet;
|
|
29292
|
+
this._hasInitialUrlBeenSet = true;
|
|
29293
|
+
if (this._hub.snapshotQueryParam(TAB_PARAM_NAME) === name)
|
|
29294
|
+
return;
|
|
29295
|
+
this._hub.write({ [TAB_PARAM_NAME]: name }, { replaceUrl });
|
|
29296
|
+
}
|
|
29297
|
+
applyTabFromUrl(rawTabName) {
|
|
29298
|
+
const component = this._connectedComponent;
|
|
29299
|
+
if (!component)
|
|
29300
|
+
return;
|
|
29301
|
+
if (typeof rawTabName !== 'string' || rawTabName.length === 0) {
|
|
29302
|
+
this.selectFallbackTab();
|
|
29303
|
+
return;
|
|
29304
|
+
}
|
|
29305
|
+
const matchingTab = this.findTabByName(rawTabName);
|
|
29306
|
+
if (matchingTab && !matchingTab.config?.isDisabled) {
|
|
29307
|
+
matchingTab.select();
|
|
29308
|
+
return;
|
|
29309
|
+
}
|
|
29310
|
+
if (matchingTab) {
|
|
29311
|
+
console.warn('Quadrel Framework | QdPageTabs - Tab "' + rawTabName + '" is disabled and cannot be deep-linked.');
|
|
29312
|
+
}
|
|
29313
|
+
else {
|
|
29314
|
+
console.warn('Quadrel Framework | QdPageTabs - No tab found with name "' + rawTabName + '".');
|
|
29315
|
+
}
|
|
29316
|
+
this.selectFallbackTab();
|
|
29317
|
+
}
|
|
29318
|
+
selectFallbackTab() {
|
|
29319
|
+
const component = this._connectedComponent;
|
|
29320
|
+
if (!component)
|
|
29321
|
+
return;
|
|
29322
|
+
const fallbackIndex = this.findFallbackTabIndex();
|
|
29323
|
+
if (fallbackIndex === undefined)
|
|
29324
|
+
return;
|
|
29325
|
+
const fallback = component.tabs.get(fallbackIndex);
|
|
29326
|
+
if (!fallback)
|
|
29327
|
+
return;
|
|
29328
|
+
fallback.select();
|
|
29329
|
+
if (component.config)
|
|
29330
|
+
component.config.selectedIndex = fallbackIndex;
|
|
29331
|
+
this.writeUrl(fallback.config?.name);
|
|
29332
|
+
}
|
|
29333
|
+
findTabByName(name) {
|
|
29334
|
+
return this._connectedComponent?.tabs.find(tab => tab.config?.name === name);
|
|
29335
|
+
}
|
|
29336
|
+
findFallbackTabIndex() {
|
|
29337
|
+
const component = this._connectedComponent;
|
|
29338
|
+
if (!component)
|
|
29339
|
+
return undefined;
|
|
29340
|
+
const configuredIndex = component.config?.selectedIndex;
|
|
29341
|
+
if (typeof configuredIndex === 'number') {
|
|
29342
|
+
const candidate = component.tabs.get(configuredIndex);
|
|
29343
|
+
if (candidate && !candidate.config.isDisabled)
|
|
29344
|
+
return configuredIndex;
|
|
29345
|
+
}
|
|
29346
|
+
const tabsArray = component.tabs.toArray();
|
|
29347
|
+
const firstNonDisabledIndex = tabsArray.findIndex(tab => !tab.config.isDisabled);
|
|
29348
|
+
return firstNonDisabledIndex >= 0 ? firstNonDisabledIndex : undefined;
|
|
29349
|
+
}
|
|
29350
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabsRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
29351
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabsRouterConnectorService });
|
|
29352
|
+
}
|
|
29353
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabsRouterConnectorService, decorators: [{
|
|
29354
|
+
type: Injectable
|
|
29355
|
+
}], ctorParameters: () => [] });
|
|
29356
|
+
|
|
28579
29357
|
/**
|
|
28580
29358
|
* **QdPageTabsComponent** provides a non-linear tabbed navigation system within a **QdPage**.
|
|
28581
29359
|
* It enables switching between different sections while maintaining form validation and controlled navigation.
|
|
@@ -28613,13 +29391,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
28613
29391
|
*
|
|
28614
29392
|
* #### **Submit Button Configuration**
|
|
28615
29393
|
*
|
|
28616
|
-
* The submit button at the bottom of the tab system can be configured via `QdPageTabsConfig`:
|
|
29394
|
+
* The submit button at the bottom of the tab system can be configured via `QdPageTabsConfig.submitButton`:
|
|
28617
29395
|
*
|
|
28618
29396
|
* - **i18n**: The translated label for the submit button.
|
|
28619
29397
|
* - **handler**: A callback function that receives form data upon submission.
|
|
28620
29398
|
* - **isDisabled**: Controls whether the button should be active or not.
|
|
28621
29399
|
* - **isHidden**: Determines whether the button is visible.
|
|
28622
|
-
*
|
|
29400
|
+
*
|
|
29401
|
+
* #### **Router Integration**
|
|
29402
|
+
*
|
|
29403
|
+
* - **connectWithRouter**: If set to true, the active tab is synced with the URL via the `?tab=<name>` query param and becomes bookmarkable. Each `<qd-page-tab>` then needs a unique `name`.
|
|
28623
29404
|
*
|
|
28624
29405
|
* #### **Usage**
|
|
28625
29406
|
*
|
|
@@ -28738,8 +29519,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
28738
29519
|
class QdPageTabsComponent extends CdkStepper {
|
|
28739
29520
|
footerService = inject(QdPageFooterService, { optional: true });
|
|
28740
29521
|
pageStoreService = inject(QdPageStoreService);
|
|
28741
|
-
|
|
28742
|
-
route = inject(ActivatedRoute, { optional: true });
|
|
29522
|
+
routerConnector = inject(QdPageTabsRouterConnectorService);
|
|
28743
29523
|
/**
|
|
28744
29524
|
* Configuration of QdPageTabs.
|
|
28745
29525
|
*/
|
|
@@ -28798,8 +29578,11 @@ class QdPageTabsComponent extends CdkStepper {
|
|
|
28798
29578
|
ngAfterViewInit() {
|
|
28799
29579
|
super.ngAfterViewInit();
|
|
28800
29580
|
setTimeout(() => {
|
|
29581
|
+
if (this.config?.connectWithRouter) {
|
|
29582
|
+
this.configureBookmarkableTabs();
|
|
29583
|
+
return;
|
|
29584
|
+
}
|
|
28801
29585
|
this.initializeTabSelection();
|
|
28802
|
-
this.configureBookmarkableTabs();
|
|
28803
29586
|
});
|
|
28804
29587
|
}
|
|
28805
29588
|
initializeTabSelection() {
|
|
@@ -28810,54 +29593,7 @@ class QdPageTabsComponent extends CdkStepper {
|
|
|
28810
29593
|
this.selectFirstNotDisabledTab();
|
|
28811
29594
|
}
|
|
28812
29595
|
configureBookmarkableTabs() {
|
|
28813
|
-
|
|
28814
|
-
this.initializeTabFromUrl();
|
|
28815
|
-
this.initializeFirstTabSelection();
|
|
28816
|
-
}
|
|
28817
|
-
}
|
|
28818
|
-
/**
|
|
28819
|
-
* Initializes the tab selection based on the URL parameter 'tab'.
|
|
28820
|
-
* @private
|
|
28821
|
-
*/
|
|
28822
|
-
initializeTabFromUrl() {
|
|
28823
|
-
this.route.queryParams.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(params => {
|
|
28824
|
-
const tabNameFromParams = params['tab'];
|
|
28825
|
-
const pageTab = this.tabs.find(tab => tab.config?.name === tabNameFromParams);
|
|
28826
|
-
if (pageTab) {
|
|
28827
|
-
pageTab.select();
|
|
28828
|
-
}
|
|
28829
|
-
else {
|
|
28830
|
-
console.warn('Quadrel Framework | QdPageTabs - No tab found with name "' + tabNameFromParams + '".');
|
|
28831
|
-
this.selectFirstNotDisabledTab(true);
|
|
28832
|
-
}
|
|
28833
|
-
});
|
|
28834
|
-
}
|
|
28835
|
-
/**
|
|
28836
|
-
* If the user navigates to a page with a tab selected, the tab will be selected automatically in {@link initializeTabFromUrl()} method.
|
|
28837
|
-
* If the user navigates to a page without a tab selected, the first active tab will be selected.
|
|
28838
|
-
* @private
|
|
28839
|
-
*/
|
|
28840
|
-
initializeFirstTabSelection() {
|
|
28841
|
-
this.route.queryParams.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(params => {
|
|
28842
|
-
const tabNameFromParams = params['tab'];
|
|
28843
|
-
if (!tabNameFromParams) {
|
|
28844
|
-
const selectedIndex = this.config.selectedIndex;
|
|
28845
|
-
const pageTab = this.tabs.find((tab, tabIndex) => tabIndex === selectedIndex);
|
|
28846
|
-
if (pageTab && pageTab?.config.name) {
|
|
28847
|
-
this.router.navigate([], {
|
|
28848
|
-
relativeTo: this.route,
|
|
28849
|
-
queryParams: { tab: pageTab.config.name },
|
|
28850
|
-
queryParamsHandling: 'merge'
|
|
28851
|
-
});
|
|
28852
|
-
}
|
|
28853
|
-
else {
|
|
28854
|
-
console.warn('Quadrel Framework | QdPageTabs - "connectedWithRouter" is active, however <qd-page-tab> has no "name" attribute.');
|
|
28855
|
-
}
|
|
28856
|
-
}
|
|
28857
|
-
});
|
|
28858
|
-
}
|
|
28859
|
-
ngOnDestroy() {
|
|
28860
|
-
super.ngOnDestroy();
|
|
29596
|
+
this.routerConnector.connectTabsWithRouter(this).pipe(takeUntilDestroyed(this.destroyRef)).subscribe();
|
|
28861
29597
|
}
|
|
28862
29598
|
isTabSelectable(index) {
|
|
28863
29599
|
const tab = this.tabs.get(index);
|
|
@@ -28865,22 +29601,14 @@ class QdPageTabsComponent extends CdkStepper {
|
|
|
28865
29601
|
}
|
|
28866
29602
|
/**
|
|
28867
29603
|
* Selects the first tab that is not disabled.
|
|
28868
|
-
* @param updateUrl if true, the URL will be updated to reflect the selected tab.
|
|
28869
29604
|
*/
|
|
28870
|
-
selectFirstNotDisabledTab(
|
|
29605
|
+
selectFirstNotDisabledTab() {
|
|
28871
29606
|
this.tabs.some((tab, tabIndex) => {
|
|
28872
29607
|
if (!tab.config.isDisabled) {
|
|
28873
29608
|
if (this.config) {
|
|
28874
29609
|
this.config.selectedIndex = tabIndex;
|
|
28875
29610
|
}
|
|
28876
29611
|
this.selectedIndex = tabIndex;
|
|
28877
|
-
if (updateUrl && this.config?.connectWithRouter && tab.config?.name) {
|
|
28878
|
-
this.router.navigate([], {
|
|
28879
|
-
relativeTo: this.route,
|
|
28880
|
-
queryParams: { tab: tab.config.name },
|
|
28881
|
-
queryParamsHandling: 'merge'
|
|
28882
|
-
});
|
|
28883
|
-
}
|
|
28884
29612
|
return true;
|
|
28885
29613
|
}
|
|
28886
29614
|
else {
|
|
@@ -28897,13 +29625,6 @@ class QdPageTabsComponent extends CdkStepper {
|
|
|
28897
29625
|
if (tab.config?.isDisabled)
|
|
28898
29626
|
return;
|
|
28899
29627
|
tab.select();
|
|
28900
|
-
if (this.config?.connectWithRouter && tab.config?.name) {
|
|
28901
|
-
this.router.navigate([], {
|
|
28902
|
-
relativeTo: this.route,
|
|
28903
|
-
queryParams: { tab: tab.config.name },
|
|
28904
|
-
queryParamsHandling: 'merge'
|
|
28905
|
-
});
|
|
28906
|
-
}
|
|
28907
29628
|
}
|
|
28908
29629
|
isSubmitButtonShown() {
|
|
28909
29630
|
return this.config?.submitButton?.isHidden !== true && !this.footerService;
|
|
@@ -28928,11 +29649,11 @@ class QdPageTabsComponent extends CdkStepper {
|
|
|
28928
29649
|
});
|
|
28929
29650
|
}
|
|
28930
29651
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
28931
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageTabsComponent, isStandalone: true, selector: "qd-page-tabs", inputs: { config: "config", testId: ["data-test-id", "testId"] }, outputs: { tabSelection: "tabSelection" }, host: { properties: { "class.standalone": "!footerService" }, classAttribute: "qd-tabs" }, providers: [{ provide: CdkStepper, useExisting: QdPageTabsComponent }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"qd-tabs-items-container\" [ngClass]=\"{ scrollable: config?.scrollabe }\">\n <qd-page-tab-header\n *ngFor=\"let tab of tabs; let i = index\"\n (click)=\"selectTab(tab)\"\n [id]=\"_getTabLabelId(i)\"\n [index]=\"i\"\n [state]=\"_getIndicatorType(i, tab.state)\"\n [label]=\"tab.config.label.i18n | translate\"\n [counters]=\"tab.config.counters\"\n [isSelected]=\"selectedIndex === i\"\n [isDisabled]=\"tab.config?.isDisabled\"\n [data-test-id]=\"testId + '-header' + '-' + i\"\n >\n </qd-page-tab-header>\n</div>\n\n<div class=\"tabs-content\">\n <ng-container *ngIf=\"!selected?.config?.isDisabled\" [ngTemplateOutlet]=\"selected?.content\"></ng-container>\n</div>\n\n<div class=\"qd-tabs-action-area\" *ngIf=\"isSubmitButtonShown()\">\n <button qdButton (click)=\"save()\" [disabled]=\"isSubmitButtonDisabled()\" [data-test-id]=\"testId + '-submit'\">\n {{ config?.submitButton?.i18n || \"i18n.qd.tabs.button.submit\" | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column}:host.standalone{height:calc(100% - 50px)}:host .qd-tabs-items-container{display:flex;width:100%;flex-direction:row;flex-wrap:wrap;padding:0 1.25rem;border-bottom:.125rem solid rgb(213,213,213);background-color:#fff;gap:0 .9375rem}@media (max-width: 599.98px){:host .qd-tabs-items-container{padding:0 .9375rem}}@media (max-width: 1279.98px){:host .qd-tabs-items-container.scrollable{flex-wrap:nowrap;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none}}:host .tabs-content{flex:1 1 auto}:host .qd-tabs-action-area{display:flex;width:100%;height:50px;justify-content:flex-end}:host .qd-tabs-action-area button{margin-right:1.25rem}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: QdPageTabHeaderComponent, selector: "qd-page-tab-header", inputs: ["state", "label", "counters", "index", "isSelected", "isDisabled", "data-test-id"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: QdButtonModule }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
29652
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageTabsComponent, isStandalone: true, selector: "qd-page-tabs", inputs: { config: "config", testId: ["data-test-id", "testId"] }, outputs: { tabSelection: "tabSelection" }, host: { properties: { "class.standalone": "!footerService" }, classAttribute: "qd-tabs" }, providers: [{ provide: CdkStepper, useExisting: QdPageTabsComponent }, QdPageTabsRouterConnectorService], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<div class=\"qd-tabs-items-container\" [ngClass]=\"{ scrollable: config?.scrollabe }\">\n <qd-page-tab-header\n *ngFor=\"let tab of tabs; let i = index\"\n (click)=\"selectTab(tab)\"\n [id]=\"_getTabLabelId(i)\"\n [index]=\"i\"\n [state]=\"_getIndicatorType(i, tab.state)\"\n [label]=\"tab.config.label.i18n | translate\"\n [counters]=\"tab.config.counters\"\n [isSelected]=\"selectedIndex === i\"\n [isDisabled]=\"tab.config?.isDisabled\"\n [data-test-id]=\"testId + '-header' + '-' + i\"\n >\n </qd-page-tab-header>\n</div>\n\n<div class=\"tabs-content\">\n <ng-container *ngIf=\"!selected?.config?.isDisabled\" [ngTemplateOutlet]=\"selected?.content\"></ng-container>\n</div>\n\n<div class=\"qd-tabs-action-area\" *ngIf=\"isSubmitButtonShown()\">\n <button qdButton (click)=\"save()\" [disabled]=\"isSubmitButtonDisabled()\" [data-test-id]=\"testId + '-submit'\">\n {{ config?.submitButton?.i18n || \"i18n.qd.tabs.button.submit\" | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column}:host.standalone{height:calc(100% - 50px)}:host .qd-tabs-items-container{display:flex;width:100%;flex-direction:row;flex-wrap:wrap;padding:0 1.25rem;border-bottom:.125rem solid rgb(213,213,213);background-color:#fff;gap:0 .9375rem}@media (max-width: 599.98px){:host .qd-tabs-items-container{padding:0 .9375rem}}@media (max-width: 1279.98px){:host .qd-tabs-items-container.scrollable{flex-wrap:nowrap;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none}}:host .tabs-content{flex:1 1 auto}:host .qd-tabs-action-area{display:flex;width:100%;height:50px;justify-content:flex-end}:host .qd-tabs-action-area button{margin-right:1.25rem}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: QdPageTabHeaderComponent, selector: "qd-page-tab-header", inputs: ["state", "label", "counters", "index", "isSelected", "isDisabled", "data-test-id"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "ngmodule", type: QdButtonModule }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
28932
29653
|
}
|
|
28933
29654
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageTabsComponent, decorators: [{
|
|
28934
29655
|
type: Component,
|
|
28935
|
-
args: [{ selector: 'qd-page-tabs', providers: [{ provide: CdkStepper, useExisting: QdPageTabsComponent }], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'qd-tabs', '[class.standalone]': '!footerService' }, standalone: true, imports: [NgFor, NgIf, NgTemplateOutlet, QdPageTabHeaderComponent, TranslateModule, QdButtonModule, CommonModule], template: "<div class=\"qd-tabs-items-container\" [ngClass]=\"{ scrollable: config?.scrollabe }\">\n <qd-page-tab-header\n *ngFor=\"let tab of tabs; let i = index\"\n (click)=\"selectTab(tab)\"\n [id]=\"_getTabLabelId(i)\"\n [index]=\"i\"\n [state]=\"_getIndicatorType(i, tab.state)\"\n [label]=\"tab.config.label.i18n | translate\"\n [counters]=\"tab.config.counters\"\n [isSelected]=\"selectedIndex === i\"\n [isDisabled]=\"tab.config?.isDisabled\"\n [data-test-id]=\"testId + '-header' + '-' + i\"\n >\n </qd-page-tab-header>\n</div>\n\n<div class=\"tabs-content\">\n <ng-container *ngIf=\"!selected?.config?.isDisabled\" [ngTemplateOutlet]=\"selected?.content\"></ng-container>\n</div>\n\n<div class=\"qd-tabs-action-area\" *ngIf=\"isSubmitButtonShown()\">\n <button qdButton (click)=\"save()\" [disabled]=\"isSubmitButtonDisabled()\" [data-test-id]=\"testId + '-submit'\">\n {{ config?.submitButton?.i18n || \"i18n.qd.tabs.button.submit\" | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column}:host.standalone{height:calc(100% - 50px)}:host .qd-tabs-items-container{display:flex;width:100%;flex-direction:row;flex-wrap:wrap;padding:0 1.25rem;border-bottom:.125rem solid rgb(213,213,213);background-color:#fff;gap:0 .9375rem}@media (max-width: 599.98px){:host .qd-tabs-items-container{padding:0 .9375rem}}@media (max-width: 1279.98px){:host .qd-tabs-items-container.scrollable{flex-wrap:nowrap;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none}}:host .tabs-content{flex:1 1 auto}:host .qd-tabs-action-area{display:flex;width:100%;height:50px;justify-content:flex-end}:host .qd-tabs-action-area button{margin-right:1.25rem}\n"] }]
|
|
29656
|
+
args: [{ selector: 'qd-page-tabs', providers: [{ provide: CdkStepper, useExisting: QdPageTabsComponent }, QdPageTabsRouterConnectorService], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'qd-tabs', '[class.standalone]': '!footerService' }, standalone: true, imports: [NgFor, NgIf, NgTemplateOutlet, QdPageTabHeaderComponent, TranslateModule, QdButtonModule, CommonModule], template: "<div class=\"qd-tabs-items-container\" [ngClass]=\"{ scrollable: config?.scrollabe }\">\n <qd-page-tab-header\n *ngFor=\"let tab of tabs; let i = index\"\n (click)=\"selectTab(tab)\"\n [id]=\"_getTabLabelId(i)\"\n [index]=\"i\"\n [state]=\"_getIndicatorType(i, tab.state)\"\n [label]=\"tab.config.label.i18n | translate\"\n [counters]=\"tab.config.counters\"\n [isSelected]=\"selectedIndex === i\"\n [isDisabled]=\"tab.config?.isDisabled\"\n [data-test-id]=\"testId + '-header' + '-' + i\"\n >\n </qd-page-tab-header>\n</div>\n\n<div class=\"tabs-content\">\n <ng-container *ngIf=\"!selected?.config?.isDisabled\" [ngTemplateOutlet]=\"selected?.content\"></ng-container>\n</div>\n\n<div class=\"qd-tabs-action-area\" *ngIf=\"isSubmitButtonShown()\">\n <button qdButton (click)=\"save()\" [disabled]=\"isSubmitButtonDisabled()\" [data-test-id]=\"testId + '-submit'\">\n {{ config?.submitButton?.i18n || \"i18n.qd.tabs.button.submit\" | translate }}\n </button>\n</div>\n", styles: [":host{display:flex;flex-direction:column}:host.standalone{height:calc(100% - 50px)}:host .qd-tabs-items-container{display:flex;width:100%;flex-direction:row;flex-wrap:wrap;padding:0 1.25rem;border-bottom:.125rem solid rgb(213,213,213);background-color:#fff;gap:0 .9375rem}@media (max-width: 599.98px){:host .qd-tabs-items-container{padding:0 .9375rem}}@media (max-width: 1279.98px){:host .qd-tabs-items-container.scrollable{flex-wrap:nowrap;overflow-x:scroll;overflow-y:hidden;scrollbar-width:none}}:host .tabs-content{flex:1 1 auto}:host .qd-tabs-action-area{display:flex;width:100%;height:50px;justify-content:flex-end}:host .qd-tabs-action-area button{margin-right:1.25rem}\n"] }]
|
|
28936
29657
|
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
28937
29658
|
type: Input
|
|
28938
29659
|
}], testId: [{
|
|
@@ -30322,147 +31043,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
30322
31043
|
args: [{ selector: 'qd-shell-header-search', standalone: false, template: "<qd-search [configData]=\"config\"> </qd-search>\n", styles: [":host{display:none}:host:not(:last-child){margin-right:1rem}:host ::ng-deep .qd-input-input{border-color:#fff0!important;background:#efefef!important}:host ::ng-deep input{background:#fff0!important}:host ::ng-deep input::placeholder{color:#979797!important}:host ::ng-deep input:hover::placeholder,:host ::ng-deep input:focus::placeholder{color:#171717!important}@media (min-width: 1280px){:host{display:block}}\n"] }]
|
|
30323
31044
|
}] });
|
|
30324
31045
|
|
|
30325
|
-
// @ts-strict-ignore
|
|
30326
|
-
class QdNavigationService {
|
|
30327
|
-
router = inject(Router);
|
|
30328
|
-
activatedRoute = inject(ActivatedRoute);
|
|
30329
|
-
routeLeafSnapshot$;
|
|
30330
|
-
routeData$;
|
|
30331
|
-
routeComponentInstanceSubject = new ReplaySubject(1);
|
|
30332
|
-
constructor() {
|
|
30333
|
-
this.routeLeafSnapshot$ = this.router.events.pipe(filter(event => event instanceof NavigationEnd), map(() => this.activatedRoute), map(route => this.getLeafRoute(route).snapshot), filter(snapshot => snapshot.outlet === 'primary'));
|
|
30334
|
-
this.routeData$ = this.routeLeafSnapshot$.pipe(map((snapshot) => snapshot.routeConfig?.data || {}), shareReplay(1));
|
|
30335
|
-
}
|
|
30336
|
-
getLeafRoute(route) {
|
|
30337
|
-
if (!route.firstChild)
|
|
30338
|
-
return route;
|
|
30339
|
-
return this.getLeafRoute(route.firstChild);
|
|
30340
|
-
}
|
|
30341
|
-
isHome$() {
|
|
30342
|
-
return this.routeData$.pipe(map(({ isHome }) => isHome ?? false));
|
|
30343
|
-
}
|
|
30344
|
-
getRouteParams$() {
|
|
30345
|
-
return this.routeLeafSnapshot$.pipe(map(this.getMergedRouteParams.bind(this)));
|
|
30346
|
-
}
|
|
30347
|
-
getMergedRouteParams(snapshot) {
|
|
30348
|
-
if (!snapshot)
|
|
30349
|
-
return {};
|
|
30350
|
-
return {
|
|
30351
|
-
...this.getMergedRouteParams(snapshot.parent),
|
|
30352
|
-
...(snapshot.params || {})
|
|
30353
|
-
};
|
|
30354
|
-
}
|
|
30355
|
-
getPreviousHref$() {
|
|
30356
|
-
return this.routeData$.pipe(map(({ previousHref }) => previousHref));
|
|
30357
|
-
}
|
|
30358
|
-
navigate(commands, extras) {
|
|
30359
|
-
return this.router.navigate(commands, extras);
|
|
30360
|
-
}
|
|
30361
|
-
navigateByUrl(url, extras) {
|
|
30362
|
-
return this.router.navigateByUrl(url, extras);
|
|
30363
|
-
}
|
|
30364
|
-
updateRouteComponentInstance(routeComponentInstance) {
|
|
30365
|
-
this.routeComponentInstanceSubject.next(routeComponentInstance);
|
|
30366
|
-
}
|
|
30367
|
-
getRouteComponentInstance$() {
|
|
30368
|
-
return this.routeComponentInstanceSubject.asObservable();
|
|
30369
|
-
}
|
|
30370
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30371
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService });
|
|
30372
|
-
}
|
|
30373
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, decorators: [{
|
|
30374
|
-
type: Injectable
|
|
30375
|
-
}], ctorParameters: () => [] });
|
|
30376
|
-
|
|
30377
|
-
// @ts-strict-ignore
|
|
30378
|
-
class QdShellLeftService {
|
|
30379
|
-
_hasNavigation = new BehaviorSubject(false);
|
|
30380
|
-
_isNavigationPinned = new BehaviorSubject(false);
|
|
30381
|
-
_isNavigationRolledOver = new BehaviorSubject(false);
|
|
30382
|
-
hasNavigation$ = this._hasNavigation.asObservable();
|
|
30383
|
-
isNavigationPinned$ = this._isNavigationPinned.asObservable();
|
|
30384
|
-
isNavigationRolledOver$ = this._isNavigationRolledOver.asObservable();
|
|
30385
|
-
set config(config) {
|
|
30386
|
-
this._hasNavigation.next(config.navigation?.length > 0);
|
|
30387
|
-
}
|
|
30388
|
-
set isNavigationRolledOver(value) {
|
|
30389
|
-
this._isNavigationRolledOver.next(value);
|
|
30390
|
-
}
|
|
30391
|
-
togglePinnedNavigation() {
|
|
30392
|
-
this._isNavigationPinned.next(!this._isNavigationPinned.value);
|
|
30393
|
-
}
|
|
30394
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30395
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService });
|
|
30396
|
-
}
|
|
30397
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, decorators: [{
|
|
30398
|
-
type: Injectable
|
|
30399
|
-
}] });
|
|
30400
|
-
|
|
30401
|
-
class QdShellRightService {
|
|
30402
|
-
notificationsService = inject(QdNotificationsService);
|
|
30403
|
-
_open = new BehaviorSubject(false);
|
|
30404
|
-
_pinned = new BehaviorSubject(false);
|
|
30405
|
-
_hasNotificationsToggle = new BehaviorSubject(false);
|
|
30406
|
-
open$ = this._open.asObservable();
|
|
30407
|
-
pinned$ = this._pinned.asObservable();
|
|
30408
|
-
notifications$;
|
|
30409
|
-
set open(open) {
|
|
30410
|
-
this._open.next(open);
|
|
30411
|
-
}
|
|
30412
|
-
get hasNotificationsToggle$() {
|
|
30413
|
-
return combineLatest([this._hasNotificationsToggle, this.hasNotifications$]).pipe(map(([hasNotificationsToggle, hasNotifications]) => hasNotificationsToggle || hasNotifications));
|
|
30414
|
-
}
|
|
30415
|
-
get hasNotifications$() {
|
|
30416
|
-
return this.notifications$.pipe(map(notifications => notifications.length > 0));
|
|
30417
|
-
}
|
|
30418
|
-
set config(config) {
|
|
30419
|
-
this._hasNotificationsToggle.next(config.hasNotificationsToggle ?? false);
|
|
30420
|
-
}
|
|
30421
|
-
constructor() {
|
|
30422
|
-
const notificationsService = this.notificationsService;
|
|
30423
|
-
this.notifications$ = notificationsService.getNotificationsForContext('shell');
|
|
30424
|
-
this._open.pipe(filter(open => open)).subscribe(() => {
|
|
30425
|
-
this._pinned.next(false);
|
|
30426
|
-
});
|
|
30427
|
-
}
|
|
30428
|
-
toggleOpen() {
|
|
30429
|
-
this._open.next(!this._open.value);
|
|
30430
|
-
}
|
|
30431
|
-
togglePinned() {
|
|
30432
|
-
this._pinned.next(!this._pinned.value);
|
|
30433
|
-
}
|
|
30434
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30435
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService });
|
|
30436
|
-
}
|
|
30437
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, decorators: [{
|
|
30438
|
-
type: Injectable
|
|
30439
|
-
}], ctorParameters: () => [] });
|
|
30440
|
-
|
|
30441
|
-
// @ts-strict-ignore
|
|
30442
|
-
class QdShellHeaderMinimizationService {
|
|
30443
|
-
navigationService = inject(QdNavigationService);
|
|
30444
|
-
breakpointService = inject(QdBreakpointService);
|
|
30445
|
-
_headerMinimizedBreakpoints = ['sm', 'xs'];
|
|
30446
|
-
_config;
|
|
30447
|
-
_isInternal$ = new BehaviorSubject(false);
|
|
30448
|
-
set config(config) {
|
|
30449
|
-
this._config = config;
|
|
30450
|
-
this._isInternal$.next(config.isInternal);
|
|
30451
|
-
}
|
|
30452
|
-
isHeaderMinimized$() {
|
|
30453
|
-
const isMinimizedForAllBreakpoints$ = this._isInternal$.pipe(combineLatestWith(this.navigationService.isHome$()), map(([isInternal, isHomePage]) => isInternal ?? !isHomePage));
|
|
30454
|
-
return isMinimizedForAllBreakpoints$.pipe(combineLatestWith(this.breakpointService.getMatchingBreakpoint()), map(([isMinimizedForAllBreakpoints, breakpoint]) => isMinimizedForAllBreakpoints || this._isMinimizedBreakpoint(breakpoint)));
|
|
30455
|
-
}
|
|
30456
|
-
_isMinimizedBreakpoint(breakpoint) {
|
|
30457
|
-
return this._headerMinimizedBreakpoints.includes(breakpoint);
|
|
30458
|
-
}
|
|
30459
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30460
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService });
|
|
30461
|
-
}
|
|
30462
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, decorators: [{
|
|
30463
|
-
type: Injectable
|
|
30464
|
-
}] });
|
|
30465
|
-
|
|
30466
31046
|
// @ts-strict-ignore
|
|
30467
31047
|
const loadJavascriptAsset = (path, scriptElementAttributes = {}) => {
|
|
30468
31048
|
const scriptElement = document.createElement('script');
|
|
@@ -30918,6 +31498,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
30918
31498
|
args: ['serviceNavigation']
|
|
30919
31499
|
}] } });
|
|
30920
31500
|
|
|
31501
|
+
class QdShellServiceNavigationModule {
|
|
31502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
31503
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, declarations: [QdShellServiceNavigationComponent], imports: [CommonModule], exports: [QdShellServiceNavigationComponent] });
|
|
31504
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, imports: [CommonModule] });
|
|
31505
|
+
}
|
|
31506
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, decorators: [{
|
|
31507
|
+
type: NgModule,
|
|
31508
|
+
args: [{
|
|
31509
|
+
imports: [CommonModule],
|
|
31510
|
+
declarations: [QdShellServiceNavigationComponent],
|
|
31511
|
+
exports: [QdShellServiceNavigationComponent],
|
|
31512
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
31513
|
+
}]
|
|
31514
|
+
}] });
|
|
31515
|
+
|
|
31516
|
+
// @ts-strict-ignore
|
|
31517
|
+
class QdNavigationService {
|
|
31518
|
+
router = inject(Router);
|
|
31519
|
+
activatedRoute = inject(ActivatedRoute);
|
|
31520
|
+
routeLeafSnapshot$;
|
|
31521
|
+
routeData$;
|
|
31522
|
+
routeComponentInstanceSubject = new ReplaySubject(1);
|
|
31523
|
+
constructor() {
|
|
31524
|
+
this.routeLeafSnapshot$ = this.router.events.pipe(filter(event => event instanceof NavigationEnd), map(() => this.activatedRoute), map(route => this.getLeafRoute(route).snapshot), filter(snapshot => snapshot.outlet === 'primary'));
|
|
31525
|
+
this.routeData$ = this.routeLeafSnapshot$.pipe(map((snapshot) => snapshot.routeConfig?.data || {}), shareReplay(1));
|
|
31526
|
+
}
|
|
31527
|
+
getLeafRoute(route) {
|
|
31528
|
+
if (!route.firstChild)
|
|
31529
|
+
return route;
|
|
31530
|
+
return this.getLeafRoute(route.firstChild);
|
|
31531
|
+
}
|
|
31532
|
+
isHome$() {
|
|
31533
|
+
return this.routeData$.pipe(map(({ isHome }) => isHome ?? false));
|
|
31534
|
+
}
|
|
31535
|
+
getRouteParams$() {
|
|
31536
|
+
return this.routeLeafSnapshot$.pipe(map(this.getMergedRouteParams.bind(this)));
|
|
31537
|
+
}
|
|
31538
|
+
getMergedRouteParams(snapshot) {
|
|
31539
|
+
if (!snapshot)
|
|
31540
|
+
return {};
|
|
31541
|
+
return {
|
|
31542
|
+
...this.getMergedRouteParams(snapshot.parent),
|
|
31543
|
+
...(snapshot.params || {})
|
|
31544
|
+
};
|
|
31545
|
+
}
|
|
31546
|
+
getPreviousHref$() {
|
|
31547
|
+
return this.routeData$.pipe(map(({ previousHref }) => previousHref));
|
|
31548
|
+
}
|
|
31549
|
+
navigate(commands, extras) {
|
|
31550
|
+
return this.router.navigate(commands, extras);
|
|
31551
|
+
}
|
|
31552
|
+
navigateByUrl(url, extras) {
|
|
31553
|
+
return this.router.navigateByUrl(url, extras);
|
|
31554
|
+
}
|
|
31555
|
+
updateRouteComponentInstance(routeComponentInstance) {
|
|
31556
|
+
this.routeComponentInstanceSubject.next(routeComponentInstance);
|
|
31557
|
+
}
|
|
31558
|
+
getRouteComponentInstance$() {
|
|
31559
|
+
return this.routeComponentInstanceSubject.asObservable();
|
|
31560
|
+
}
|
|
31561
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31562
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService });
|
|
31563
|
+
}
|
|
31564
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, decorators: [{
|
|
31565
|
+
type: Injectable
|
|
31566
|
+
}], ctorParameters: () => [] });
|
|
31567
|
+
|
|
31568
|
+
// @ts-strict-ignore
|
|
31569
|
+
class QdShellLeftService {
|
|
31570
|
+
_hasNavigation = new BehaviorSubject(false);
|
|
31571
|
+
_isNavigationPinned = new BehaviorSubject(false);
|
|
31572
|
+
_isNavigationRolledOver = new BehaviorSubject(false);
|
|
31573
|
+
hasNavigation$ = this._hasNavigation.asObservable();
|
|
31574
|
+
isNavigationPinned$ = this._isNavigationPinned.asObservable();
|
|
31575
|
+
isNavigationRolledOver$ = this._isNavigationRolledOver.asObservable();
|
|
31576
|
+
set config(config) {
|
|
31577
|
+
this._hasNavigation.next(config.navigation?.length > 0);
|
|
31578
|
+
}
|
|
31579
|
+
set isNavigationRolledOver(value) {
|
|
31580
|
+
this._isNavigationRolledOver.next(value);
|
|
31581
|
+
}
|
|
31582
|
+
togglePinnedNavigation() {
|
|
31583
|
+
this._isNavigationPinned.next(!this._isNavigationPinned.value);
|
|
31584
|
+
}
|
|
31585
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31586
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService });
|
|
31587
|
+
}
|
|
31588
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, decorators: [{
|
|
31589
|
+
type: Injectable
|
|
31590
|
+
}] });
|
|
31591
|
+
|
|
31592
|
+
class QdShellRightService {
|
|
31593
|
+
notificationsService = inject(QdNotificationsService);
|
|
31594
|
+
_open = new BehaviorSubject(false);
|
|
31595
|
+
_pinned = new BehaviorSubject(false);
|
|
31596
|
+
_hasNotificationsToggle = new BehaviorSubject(false);
|
|
31597
|
+
open$ = this._open.asObservable();
|
|
31598
|
+
pinned$ = this._pinned.asObservable();
|
|
31599
|
+
notifications$;
|
|
31600
|
+
set open(open) {
|
|
31601
|
+
this._open.next(open);
|
|
31602
|
+
}
|
|
31603
|
+
get hasNotificationsToggle$() {
|
|
31604
|
+
return combineLatest([this._hasNotificationsToggle, this.hasNotifications$]).pipe(map(([hasNotificationsToggle, hasNotifications]) => hasNotificationsToggle || hasNotifications));
|
|
31605
|
+
}
|
|
31606
|
+
get hasNotifications$() {
|
|
31607
|
+
return this.notifications$.pipe(map(notifications => notifications.length > 0));
|
|
31608
|
+
}
|
|
31609
|
+
set config(config) {
|
|
31610
|
+
this._hasNotificationsToggle.next(config.hasNotificationsToggle ?? false);
|
|
31611
|
+
}
|
|
31612
|
+
constructor() {
|
|
31613
|
+
const notificationsService = this.notificationsService;
|
|
31614
|
+
this.notifications$ = notificationsService.getNotificationsForContext('shell');
|
|
31615
|
+
this._open.pipe(filter(open => open)).subscribe(() => {
|
|
31616
|
+
this._pinned.next(false);
|
|
31617
|
+
});
|
|
31618
|
+
}
|
|
31619
|
+
toggleOpen() {
|
|
31620
|
+
this._open.next(!this._open.value);
|
|
31621
|
+
}
|
|
31622
|
+
togglePinned() {
|
|
31623
|
+
this._pinned.next(!this._pinned.value);
|
|
31624
|
+
}
|
|
31625
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31626
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService });
|
|
31627
|
+
}
|
|
31628
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, decorators: [{
|
|
31629
|
+
type: Injectable
|
|
31630
|
+
}], ctorParameters: () => [] });
|
|
31631
|
+
|
|
31632
|
+
// @ts-strict-ignore
|
|
31633
|
+
class QdShellHeaderMinimizationService {
|
|
31634
|
+
navigationService = inject(QdNavigationService);
|
|
31635
|
+
breakpointService = inject(QdBreakpointService);
|
|
31636
|
+
_headerMinimizedBreakpoints = ['sm', 'xs'];
|
|
31637
|
+
_config;
|
|
31638
|
+
_isInternal$ = new BehaviorSubject(false);
|
|
31639
|
+
set config(config) {
|
|
31640
|
+
this._config = config;
|
|
31641
|
+
this._isInternal$.next(config.isInternal);
|
|
31642
|
+
}
|
|
31643
|
+
isHeaderMinimized$() {
|
|
31644
|
+
const isMinimizedForAllBreakpoints$ = this._isInternal$.pipe(combineLatestWith(this.navigationService.isHome$()), map(([isInternal, isHomePage]) => isInternal ?? !isHomePage));
|
|
31645
|
+
return isMinimizedForAllBreakpoints$.pipe(combineLatestWith(this.breakpointService.getMatchingBreakpoint()), map(([isMinimizedForAllBreakpoints, breakpoint]) => isMinimizedForAllBreakpoints || this._isMinimizedBreakpoint(breakpoint)));
|
|
31646
|
+
}
|
|
31647
|
+
_isMinimizedBreakpoint(breakpoint) {
|
|
31648
|
+
return this._headerMinimizedBreakpoints.includes(breakpoint);
|
|
31649
|
+
}
|
|
31650
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31651
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService });
|
|
31652
|
+
}
|
|
31653
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, decorators: [{
|
|
31654
|
+
type: Injectable
|
|
31655
|
+
}] });
|
|
31656
|
+
|
|
30921
31657
|
// @ts-strict-ignore
|
|
30922
31658
|
const DEFAULT_LANGUAGE_LIST$1 = ['de', 'fr', 'it', 'en'];
|
|
30923
31659
|
class QdShellHeaderWidgetService {
|
|
@@ -31312,7 +32048,7 @@ class QdShellHeaderComponent {
|
|
|
31312
32048
|
const navigationService = this.navigationService;
|
|
31313
32049
|
const shellLeftService = this.shellLeftService;
|
|
31314
32050
|
const shellRightService = this.shellRightService;
|
|
31315
|
-
this.backLinkDisplayed$ = navigationService.getPreviousHref$().pipe(withLatestFrom(navigationService.getRouteComponentInstance$()), switchMap(([previousHref, routeComponentInstance]) => {
|
|
32051
|
+
this.backLinkDisplayed$ = navigationService.getPreviousHref$().pipe(withLatestFrom$1(navigationService.getRouteComponentInstance$()), switchMap(([previousHref, routeComponentInstance]) => {
|
|
31316
32052
|
if (typeof previousHref === 'function')
|
|
31317
32053
|
previousHref = previousHref(routeComponentInstance);
|
|
31318
32054
|
return isObservable(previousHref) ? previousHref.pipe(take(1)) : of(previousHref);
|
|
@@ -32000,21 +32736,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
32000
32736
|
args: [QdCommentsComponent]
|
|
32001
32737
|
}] } });
|
|
32002
32738
|
|
|
32003
|
-
class QdShellServiceNavigationModule {
|
|
32004
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
32005
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, declarations: [QdShellServiceNavigationComponent], imports: [CommonModule], exports: [QdShellServiceNavigationComponent] });
|
|
32006
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, imports: [CommonModule] });
|
|
32007
|
-
}
|
|
32008
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, decorators: [{
|
|
32009
|
-
type: NgModule,
|
|
32010
|
-
args: [{
|
|
32011
|
-
imports: [CommonModule],
|
|
32012
|
-
declarations: [QdShellServiceNavigationComponent],
|
|
32013
|
-
exports: [QdShellServiceNavigationComponent],
|
|
32014
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
32015
|
-
}]
|
|
32016
|
-
}] });
|
|
32017
|
-
|
|
32018
32739
|
function initializeBreadcrumbServices(breadcrumbsService, dialogBreadcrumbsService) {
|
|
32019
32740
|
return () => {
|
|
32020
32741
|
breadcrumbsService.initialize();
|
|
@@ -33267,5 +33988,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
33267
33988
|
* Generated bundle index. Do not edit.
|
|
33268
33989
|
*/
|
|
33269
33990
|
|
|
33270
|
-
export { APP_ENVIRONMENT, AVAILABLE_ICONS, BACKEND_ERROR_CODES, MockLocaleDatePipe, NavigationTileComponent, NavigationTilesComponent, QD_DIALOG_CONFIRMATION_RESOLVER_TOKEN, QD_FILE_MANAGER_TOKEN, QD_FILE_UPLOAD_MANAGER_TOKEN, QD_FORM_OPTIONS_RESOLVER, QD_PAGE_OBJECT_RESOLVER_TOKEN, QD_PAGE_STEP_RESOLVER_TOKEN, QD_POPOVER_TOP_FIRST, QD_SAFE_BOTTOM_OFFSET, QD_TABLE_DATA_RESOLVER_TOKEN, QD_UPLOAD_HTTP_OPTIONS, QdButtonComponent, QdButtonGhostDirective, QdButtonGridComponent, QdButtonLinkDirective, QdButtonModule, QdButtonStackButtonComponent, QdButtonStackComponent, QdCheckboxChipsComponent, QdCheckboxComponent, QdCheckboxesComponent, QdChipComponent, QdChipModule, QdColumnAutoFillDirective, QdColumnBreakBeforeDirective, QdColumnDirective, QdColumnDisableResponsiveColspansDirective, QdColumnFullGridWidthDirective, QdColumnNextInSameRowDirective, QdColumnsDirective, QdColumnsDisableAutoFillDirective, QdColumnsDisableResponsiveColspansDirective, QdColumnsMaxDirective, QdCommentsComponent, QdCommentsModule, QdConnectFormStateToPageDirective, QdConnectorTableContextDirective, QdConnectorTableFilterDirective, QdConnectorTableSearchDirective, QdContactCardComponent, QdContactCardModule, QdContainerPairsCaptionComponent, QdContainerPairsContainerComponent, QdContainerPairsHeaderComponent, QdContainerPairsItemComponent, QdContainerPairsValueComponent, QdContextService, QdCoreModule, QdDatepickerComponent, QdDialogActionComponent, QdDialogAuthSessionEndComponent, QdDialogAuthSessionEndService, QdDialogComponent, QdDialogConfirmationComponent, QdDialogConfirmationErrorDirective, QdDialogConfirmationInfoDirective, QdDialogConfirmationSuccessDirective, QdDialogModule, QdDialogRecordStepperComponent, QdDialogService, QdDialogSize, QdDisabledDirective, QdDropdownComponent, QdFileCollectorComponent, QdFileCollectorModule, QdFileSizePipe$1 as QdFileSizePipe, QdFileUploadComponent, QdFileUploadService, QdFilterComponent, QdFilterFormItemsComponent, QdFilterModule, QdFilterRestParamBuilder, QdFilterService, QdFormArray, QdFormBuilder, QdFormControl, QdFormGroup, QdFormModule, QdGridComponent, QdGridModule, QdHorizontalPairsCaptionComponent, QdHorizontalPairsComponent, QdHorizontalPairsItemComponent, QdHorizontalPairsValueComponent, QdIconButtonComponent, QdIconComponent, QdIconModule, QdImageComponent, QdImageModule, QdIndeterminateProgressBarComponent, QdInputComponent, QdListModule, QdMenuButtonComponent, QdMockBreakpointService, QdMockButtonComponent, QdMockButtonGhostDirective, QdMockButtonGridComponent, QdMockButtonLinkDirective, QdMockButtonModule, QdMockButtonStackButtonComponent, QdMockButtonStackComponent, QdMockCalendarComponent, QdMockCheckboxChipsComponent, QdMockCheckboxComponent, QdMockCheckboxesComponent, QdMockChipComponent, QdMockChipModule, QdMockColumnDirective, QdMockColumnsDirective, QdMockContactCardComponent, QdMockContactCardModule, QdMockContainerPairsCaptionComponent, QdMockContainerPairsContainerComponent, QdMockContainerPairsHeaderComponent, QdMockContainerPairsItemComponent, QdMockContainerPairsValueComponent, QdMockCoreModule, QdMockCounterBadgeComponent, QdMockDatepickerComponent, QdMockDisabledDirective, QdMockDropdownComponent, QdMockFileCollectorComponent, QdMockFileCollectorModule, QdMockFilterCategoryBooleanComponent, QdMockFilterCategoryComponent, QdMockFilterCategoryDateComponent, QdMockFilterCategoryDateRangeComponent, QdMockFilterCategoryFreeTextComponent, QdMockFilterCategorySelectComponent, QdMockFilterComponent, QdMockFilterFormItemsComponent, QdMockFilterItemBooleanComponent, QdMockFilterItemDateComponent, QdMockFilterItemDateRangeComponent, QdMockFilterItemFreeTextComponent, QdMockFilterItemMultiSelectComponent, QdMockFilterItemSingleSelectComponent, QdMockFilterModule, QdMockFilterService, QdMockFormErrorComponent, QdMockFormGroupErrorComponent, QdMockFormHintComponent, QdMockFormLabelComponent, QdMockFormReadonlyComponent, QdMockFormViewonlyComponent, QdMockFormsModule, QdMockGridModule, QdMockIconButtonComponent, QdMockIconComponent, QdMockIconModule, QdMockImageComponent, QdMockImageModule, QdMockIndeterminateProgressBarComponent, QdMockInputComponent, QdMockListModule, QdMockNavigationTileComponent, QdMockNavigationTilesComponent, QdMockNavigationTilesModule, QdMockNotificationComponent, QdMockNotificationContentComponent, QdMockNotificationsComponent, QdMockNotificationsModule, QdMockNotificationsService, QdMockPageComponent, QdMockPageModule, QdMockPercentageProgressBarComponent, QdMockPinCodeComponent, QdMockPlaceHolderModule, QdMockPopoverOnClickDirective, QdMockProgressBarModule, QdMockQdPlaceHolderComponent, QdMockRadioButtonsComponent, QdMockRwdDisabledDirective, QdMockSearchComponent, QdMockSearchModule, QdMockSectionComponent, QdMockSectionModule, QdMockShellComponent, QdMockShellFooterComponent, QdMockShellHeaderBannerComponent, QdMockShellHeaderComponent, QdMockShellHeaderSearchComponent, QdMockShellHeaderWidgetComponent, QdMockShellModule, QdMockShellToolbarComponent, QdMockShellToolbarItemComponent, QdMockStatusIndicatorCaptionComponent, QdMockStatusIndicatorComponent, QdMockStatusIndicatorItemComponent, QdMockStatusIndicatorModule, QdMockStatusPairsCaptionComponent, QdMockStatusPairsComponent, QdMockStatusPairsErrorComponent, QdMockStatusPairsItemComponent, QdMockStatusPairsValueComponent, QdMockSwitchComponent, QdMockSwitchesComponent, QdMockTableComponent, QdMockTableModule, QdMockTextSectionComponent, QdMockTextSectionHeadlineComponent, QdMockTextSectionModule, QdMockTextSectionParagraphComponent, QdMockTextareaComponent, QdMockTileButtonListComponent, QdMockTileComponent, QdMockTileTextListComponent, QdMockTileTextListItemComponent, QdMockTileTitleComponent, QdMockTilesContainerComponent, QdMockTilesContainerTitleComponent, QdMockTilesModule, QdMockTranslatePipe, QdMockVisuallyHiddenDirective, QdMultiInputComponent, QdNavigationTilesModule, QdNotificationComponent, QdNotificationContentComponent, QdNotificationsComponent, QdNotificationsHttpInterceptorService, QdNotificationsModule, QdNotificationsService, QdNotificationsSnackbarListenerDirective, QdPageComponent, QdPageControlPanelComponent, QdPageFooterComponent, QdPageFooterCustomContentDirective, QdPageInfoBannerComponent, QdPageModule, QdPageStepComponent, QdPageStepperAdapterDirective, QdPageStepperComponent, QdPageStepperModule, QdPageStoreService, QdPageTabComponent, QdPageTabsAdapterDirective, QdPageTabsComponent, QdPageTabsModule, QdPanelSectionActionsComponent, QdPanelSectionComponent, QdPanelSectionModule, QdPanelSectionStatusComponent, QdPanelSectionTextParagraphComponent, QdPendingChangesGuardDirective, QdPercentageProgressBarComponent, QdPinCodeComponent, QdPlaceHolderComponent, QdPlaceHolderModule, QdPlaceholderPipe, QdProgressBarModule, QdProjectionGuardComponent, QdPushEventsService, QdQuickEditComponent, QdQuickEditModule, QdRadioButtonsComponent, QdRichtextComponent, QdRwdDisabledDirective, QdSearchComponent, QdSearchModule, QdSectionAdapterDirective, QdSectionComponent, QdSectionModule, QdSectionToolbarComponent, QdShellComponent, QdShellModule, QdSortDirection, QdSpinnerComponent, QdSpinnerModule, QdStatusIndicatorComponent, QdStatusIndicatorModule, QdStatusPairsCaptionComponent, QdStatusPairsComponent, QdStatusPairsErrorComponent, QdStatusPairsItemComponent, QdStatusPairsValueComponent, QdSubgridComponent, QdSwitchComponent, QdSwitchesComponent, QdTableComponent, QdTableModule, QdTableSpringTools, QdTextSectionComponent, QdTextSectionHeadlineComponent, QdTextSectionModule, QdTextSectionParagraphComponent, QdTextareaComponent, QdTileButtonListComponent, QdTileComponent, QdTileTextListComponent, QdTileTextListItemComponent, QdTileTitleComponent, QdTilesComponent, QdTilesModule, QdTilesTitleComponent, QdTooltipAtIntersectionDirective, QdTooltipIconComponent, QdTreeComponent, QdTreeModule, QdTreeRowExpanderService, QdUiMockModule, QdUiModule, QdUploadErrorType, QdValidators, QdViewportAdaptiveDirective, QdVisuallyHiddenDirective, chipColorDefault, createMetadataStream, updateHtmlLang };
|
|
33991
|
+
export { APP_ENVIRONMENT, AVAILABLE_ICONS, BACKEND_ERROR_CODES, MockLocaleDatePipe, NavigationTileComponent, NavigationTilesComponent, QD_DIALOG_CONFIRMATION_RESOLVER_TOKEN, QD_FILE_MANAGER_TOKEN, QD_FILE_UPLOAD_MANAGER_TOKEN, QD_FORM_OPTIONS_RESOLVER, QD_PAGE_OBJECT_RESOLVER_TOKEN, QD_PAGE_STEP_RESOLVER_TOKEN, QD_POPOVER_TOP_FIRST, QD_SAFE_BOTTOM_OFFSET, QD_TABLE_DATA_RESOLVER_TOKEN, QD_UPLOAD_HTTP_OPTIONS, QdButtonComponent, QdButtonGhostDirective, QdButtonGridComponent, QdButtonLinkDirective, QdButtonModule, QdButtonStackButtonComponent, QdButtonStackComponent, QdCheckboxChipsComponent, QdCheckboxComponent, QdCheckboxesComponent, QdChipComponent, QdChipModule, QdColumnAutoFillDirective, QdColumnBreakBeforeDirective, QdColumnDirective, QdColumnDisableResponsiveColspansDirective, QdColumnFullGridWidthDirective, QdColumnNextInSameRowDirective, QdColumnsDirective, QdColumnsDisableAutoFillDirective, QdColumnsDisableResponsiveColspansDirective, QdColumnsMaxDirective, QdCommentsComponent, QdCommentsModule, QdConnectFormStateToPageDirective, QdConnectorTableContextDirective, QdConnectorTableFilterDirective, QdConnectorTableSearchDirective, QdContactCardComponent, QdContactCardModule, QdContainerPairsCaptionComponent, QdContainerPairsContainerComponent, QdContainerPairsHeaderComponent, QdContainerPairsItemComponent, QdContainerPairsValueComponent, QdContextService, QdCoreModule, QdDatepickerComponent, QdDialogActionComponent, QdDialogAuthSessionEndComponent, QdDialogAuthSessionEndService, QdDialogComponent, QdDialogConfirmationComponent, QdDialogConfirmationErrorDirective, QdDialogConfirmationInfoDirective, QdDialogConfirmationSuccessDirective, QdDialogModule, QdDialogRecordStepperComponent, QdDialogService, QdDialogSize, QdDisabledDirective, QdDropdownComponent, QdFileCollectorComponent, QdFileCollectorModule, QdFileSizePipe$1 as QdFileSizePipe, QdFileUploadComponent, QdFileUploadService, QdFilterComponent, QdFilterFormItemsComponent, QdFilterModule, QdFilterRestParamBuilder, QdFilterService, QdFormArray, QdFormBuilder, QdFormControl, QdFormGroup, QdFormModule, QdGridComponent, QdGridModule, QdHorizontalPairsCaptionComponent, QdHorizontalPairsComponent, QdHorizontalPairsItemComponent, QdHorizontalPairsValueComponent, QdIconButtonComponent, QdIconComponent, QdIconModule, QdImageComponent, QdImageModule, QdIndeterminateProgressBarComponent, QdInputComponent, QdListModule, QdMenuButtonComponent, QdMockBreakpointService, QdMockButtonComponent, QdMockButtonGhostDirective, QdMockButtonGridComponent, QdMockButtonLinkDirective, QdMockButtonModule, QdMockButtonStackButtonComponent, QdMockButtonStackComponent, QdMockCalendarComponent, QdMockCheckboxChipsComponent, QdMockCheckboxComponent, QdMockCheckboxesComponent, QdMockChipComponent, QdMockChipModule, QdMockColumnDirective, QdMockColumnsDirective, QdMockContactCardComponent, QdMockContactCardModule, QdMockContainerPairsCaptionComponent, QdMockContainerPairsContainerComponent, QdMockContainerPairsHeaderComponent, QdMockContainerPairsItemComponent, QdMockContainerPairsValueComponent, QdMockCoreModule, QdMockCounterBadgeComponent, QdMockDatepickerComponent, QdMockDisabledDirective, QdMockDropdownComponent, QdMockFileCollectorComponent, QdMockFileCollectorModule, QdMockFilterCategoryBooleanComponent, QdMockFilterCategoryComponent, QdMockFilterCategoryDateComponent, QdMockFilterCategoryDateRangeComponent, QdMockFilterCategoryFreeTextComponent, QdMockFilterCategorySelectComponent, QdMockFilterComponent, QdMockFilterFormItemsComponent, QdMockFilterItemBooleanComponent, QdMockFilterItemDateComponent, QdMockFilterItemDateRangeComponent, QdMockFilterItemFreeTextComponent, QdMockFilterItemMultiSelectComponent, QdMockFilterItemSingleSelectComponent, QdMockFilterModule, QdMockFilterService, QdMockFormErrorComponent, QdMockFormGroupErrorComponent, QdMockFormHintComponent, QdMockFormLabelComponent, QdMockFormReadonlyComponent, QdMockFormViewonlyComponent, QdMockFormsModule, QdMockGridModule, QdMockIconButtonComponent, QdMockIconComponent, QdMockIconModule, QdMockImageComponent, QdMockImageModule, QdMockIndeterminateProgressBarComponent, QdMockInputComponent, QdMockListModule, QdMockNavigationTileComponent, QdMockNavigationTilesComponent, QdMockNavigationTilesModule, QdMockNotificationComponent, QdMockNotificationContentComponent, QdMockNotificationsComponent, QdMockNotificationsModule, QdMockNotificationsService, QdMockPageComponent, QdMockPageModule, QdMockPercentageProgressBarComponent, QdMockPinCodeComponent, QdMockPlaceHolderModule, QdMockPopoverOnClickDirective, QdMockProgressBarModule, QdMockQdPlaceHolderComponent, QdMockRadioButtonsComponent, QdMockRwdDisabledDirective, QdMockSearchComponent, QdMockSearchModule, QdMockSectionComponent, QdMockSectionModule, QdMockShellComponent, QdMockShellFooterComponent, QdMockShellHeaderBannerComponent, QdMockShellHeaderComponent, QdMockShellHeaderSearchComponent, QdMockShellHeaderWidgetComponent, QdMockShellModule, QdMockShellToolbarComponent, QdMockShellToolbarItemComponent, QdMockStatusIndicatorCaptionComponent, QdMockStatusIndicatorComponent, QdMockStatusIndicatorItemComponent, QdMockStatusIndicatorModule, QdMockStatusPairsCaptionComponent, QdMockStatusPairsComponent, QdMockStatusPairsErrorComponent, QdMockStatusPairsItemComponent, QdMockStatusPairsValueComponent, QdMockSwitchComponent, QdMockSwitchesComponent, QdMockTableComponent, QdMockTableModule, QdMockTextSectionComponent, QdMockTextSectionHeadlineComponent, QdMockTextSectionModule, QdMockTextSectionParagraphComponent, QdMockTextareaComponent, QdMockTileButtonListComponent, QdMockTileComponent, QdMockTileTextListComponent, QdMockTileTextListItemComponent, QdMockTileTitleComponent, QdMockTilesContainerComponent, QdMockTilesContainerTitleComponent, QdMockTilesModule, QdMockTranslatePipe, QdMockVisuallyHiddenDirective, QdMultiInputComponent, QdNavigationTilesModule, QdNotificationComponent, QdNotificationContentComponent, QdNotificationsComponent, QdNotificationsHttpInterceptorService, QdNotificationsModule, QdNotificationsService, QdNotificationsSnackbarListenerDirective, QdPageComponent, QdPageControlPanelComponent, QdPageFooterComponent, QdPageFooterCustomContentDirective, QdPageInfoBannerComponent, QdPageModule, QdPageStepComponent, QdPageStepperAdapterDirective, QdPageStepperComponent, QdPageStepperModule, QdPageStoreService, QdPageTabComponent, QdPageTabsAdapterDirective, QdPageTabsComponent, QdPageTabsModule, QdPanelSectionActionsComponent, QdPanelSectionComponent, QdPanelSectionModule, QdPanelSectionStatusComponent, QdPanelSectionTextParagraphComponent, QdPendingChangesGuardDirective, QdPercentageProgressBarComponent, QdPinCodeComponent, QdPlaceHolderComponent, QdPlaceHolderModule, QdPlaceholderPipe, QdProgressBarModule, QdProjectionGuardComponent, QdPushEventsService, QdQuickEditComponent, QdQuickEditModule, QdRadioButtonsComponent, QdRichtextComponent, QdRouterQueryParamHubService, QdRwdDisabledDirective, QdSearchComponent, QdSearchModule, QdSectionAdapterDirective, QdSectionComponent, QdSectionModule, QdSectionToolbarComponent, QdShellComponent, QdShellModule, QdSortDirection, QdSpinnerComponent, QdSpinnerModule, QdStatusIndicatorComponent, QdStatusIndicatorModule, QdStatusPairsCaptionComponent, QdStatusPairsComponent, QdStatusPairsErrorComponent, QdStatusPairsItemComponent, QdStatusPairsValueComponent, QdSubgridComponent, QdSwitchComponent, QdSwitchesComponent, QdTableComponent, QdTableModule, QdTableSpringTools, QdTextSectionComponent, QdTextSectionHeadlineComponent, QdTextSectionModule, QdTextSectionParagraphComponent, QdTextareaComponent, QdTileButtonListComponent, QdTileComponent, QdTileTextListComponent, QdTileTextListItemComponent, QdTileTitleComponent, QdTilesComponent, QdTilesModule, QdTilesTitleComponent, QdTooltipAtIntersectionDirective, QdTooltipIconComponent, QdTreeComponent, QdTreeModule, QdTreeRowExpanderService, QdUiMockModule, QdUiModule, QdUploadErrorType, QdValidators, QdViewportAdaptiveDirective, QdVisuallyHiddenDirective, chipColorDefault, createMetadataStream, updateHtmlLang };
|
|
33271
33992
|
//# sourceMappingURL=quadrel-enterprise-ui-framework.mjs.map
|