@quadrel-enterprise-ui/framework 20.11.2-beta.150.1 → 20.12.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.
- package/fesm2022/quadrel-enterprise-ui-framework.mjs +1016 -648
- package/fesm2022/quadrel-enterprise-ui-framework.mjs.map +1 -1
- package/index.d.ts +337 -106
- package/package.json +1 -1
- package/src/assets/i18n/de.json +0 -4
- package/src/assets/i18n/en.json +0 -6
- package/src/assets/i18n/fr.json +0 -7
- package/src/assets/i18n/it.json +0 -6
|
@@ -3,13 +3,13 @@ import { inject, ElementRef, Directive, InjectionToken, HostBinding, Input, View
|
|
|
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,
|
|
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, async } from 'rxjs';
|
|
7
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';
|
|
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';
|
|
@@ -18,8 +18,8 @@ import { NG_VALUE_ACCESSOR, FormsModule, UntypedFormControl, UntypedFormArray, U
|
|
|
18
18
|
import { ComponentPortal } from '@angular/cdk/portal';
|
|
19
19
|
import { OverlayPositionBuilder, Overlay } from '@angular/cdk/overlay';
|
|
20
20
|
import isNumber from 'lodash/isNumber';
|
|
21
|
-
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
22
21
|
import { EventSourcePolyfill } from 'event-source-polyfill';
|
|
22
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
23
23
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
24
24
|
import * as i3$1 from 'ngx-editor';
|
|
25
25
|
import { Editor, NgxEditorModule } from 'ngx-editor';
|
|
@@ -1604,24 +1604,6 @@ const updateHtmlLang = (lang) => {
|
|
|
1604
1604
|
const htmlNode = document.documentElement;
|
|
1605
1605
|
htmlNode.setAttribute('lang', lang);
|
|
1606
1606
|
};
|
|
1607
|
-
const SERVICE_NAV_LOCALE_DEFAULTS = {
|
|
1608
|
-
DE: 'de-CH',
|
|
1609
|
-
IT: 'it-CH',
|
|
1610
|
-
FR: 'fr-CH',
|
|
1611
|
-
EN: 'en-GB'
|
|
1612
|
-
};
|
|
1613
|
-
const determineLocale = (serviceNavLanguage, browserLocales) => {
|
|
1614
|
-
const browserLocale = browserLocales?.[0] ?? navigator.language;
|
|
1615
|
-
if (!serviceNavLanguage) {
|
|
1616
|
-
const browserLocaleUpper = browserLocale.toUpperCase();
|
|
1617
|
-
return SERVICE_NAV_LOCALE_DEFAULTS[browserLocaleUpper] ?? browserLocale;
|
|
1618
|
-
}
|
|
1619
|
-
const serviceNavLangUpper = serviceNavLanguage.toUpperCase();
|
|
1620
|
-
const browserLanguage = browserLocale.split('-')[0].toUpperCase();
|
|
1621
|
-
if (browserLanguage === serviceNavLangUpper)
|
|
1622
|
-
return browserLocale;
|
|
1623
|
-
return SERVICE_NAV_LOCALE_DEFAULTS[serviceNavLangUpper] ?? browserLocale;
|
|
1624
|
-
};
|
|
1625
1607
|
|
|
1626
1608
|
const constantCase = (str) => upperCase(str).replace(/ /g, '_');
|
|
1627
1609
|
|
|
@@ -6654,8 +6636,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
6654
6636
|
}]
|
|
6655
6637
|
}] });
|
|
6656
6638
|
|
|
6657
|
-
const QD_SAFE_BOTTOM_OFFSET = new InjectionToken('QD_SAFE_BOTTOM_OFFSET');
|
|
6658
|
-
|
|
6659
6639
|
let QdFileSizePipe$1 = class QdFileSizePipe {
|
|
6660
6640
|
translate = inject(TranslateService, { optional: true });
|
|
6661
6641
|
transform(bytes) {
|
|
@@ -6707,8 +6687,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
6707
6687
|
}]
|
|
6708
6688
|
}] });
|
|
6709
6689
|
|
|
6710
|
-
const QD_POPOVER_TOP_FIRST = new InjectionToken('QD_POPOVER_TOP_FIRST');
|
|
6711
|
-
|
|
6712
6690
|
class QdProjectionGuardComponent {
|
|
6713
6691
|
elementRef = inject(ElementRef);
|
|
6714
6692
|
isDisabled = false;
|
|
@@ -6750,360 +6728,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
6750
6728
|
}]
|
|
6751
6729
|
}] });
|
|
6752
6730
|
|
|
6753
|
-
class QdLocaleService {
|
|
6754
|
-
_serviceNavLanguage$ = new BehaviorSubject(null);
|
|
6755
|
-
locale$ = this._serviceNavLanguage$.pipe(map(serviceNavLanguage => determineLocale(serviceNavLanguage, navigator.languages)));
|
|
6756
|
-
setServiceNavigationLanguage(language) {
|
|
6757
|
-
this._serviceNavLanguage$.next(language);
|
|
6758
|
-
}
|
|
6759
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6760
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, providedIn: 'root' });
|
|
6761
|
-
}
|
|
6762
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdLocaleService, decorators: [{
|
|
6763
|
-
type: Injectable,
|
|
6764
|
-
args: [{ providedIn: 'root' }]
|
|
6765
|
-
}] });
|
|
6766
|
-
|
|
6767
|
-
class QdNumberInputService {
|
|
6768
|
-
_locale;
|
|
6769
|
-
_decimalSeparator;
|
|
6770
|
-
_groupSeparator;
|
|
6771
|
-
localeService = inject(QdLocaleService, { optional: true });
|
|
6772
|
-
destroyRef = inject(DestroyRef);
|
|
6773
|
-
ambiguityHintKeyDot = 'i18n.qd.input.number.ambiguousHint.dot';
|
|
6774
|
-
ambiguityHintKeyComma = 'i18n.qd.input.number.ambiguousHint.comma';
|
|
6775
|
-
invalidCharactersErrorKeyComma = 'i18n.qd.input.number.invalidCharacters.comma';
|
|
6776
|
-
invalidCharactersErrorKeyDot = 'i18n.qd.input.number.invalidCharacters.dot';
|
|
6777
|
-
get invalidCharactersErrorKey() {
|
|
6778
|
-
return this._decimalSeparator === ',' ? this.invalidCharactersErrorKeyComma : this.invalidCharactersErrorKeyDot;
|
|
6779
|
-
}
|
|
6780
|
-
get decimalSeparator() {
|
|
6781
|
-
return this._decimalSeparator;
|
|
6782
|
-
}
|
|
6783
|
-
get groupSeparator() {
|
|
6784
|
-
return this._groupSeparator;
|
|
6785
|
-
}
|
|
6786
|
-
constructor() {
|
|
6787
|
-
if (this.localeService) {
|
|
6788
|
-
this.localeService.locale$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(locale => {
|
|
6789
|
-
this.detectSeparatorsForLocale(locale);
|
|
6790
|
-
});
|
|
6791
|
-
}
|
|
6792
|
-
else {
|
|
6793
|
-
this.detectSeparators();
|
|
6794
|
-
}
|
|
6795
|
-
}
|
|
6796
|
-
detectSeparators() {
|
|
6797
|
-
const locale = navigator.languages && navigator.languages.length ? navigator.languages[0] : navigator.language;
|
|
6798
|
-
this.detectSeparatorsForLocale(locale);
|
|
6799
|
-
}
|
|
6800
|
-
isValidNumber(value) {
|
|
6801
|
-
if (!value)
|
|
6802
|
-
return false;
|
|
6803
|
-
const escaped = this._decimalSeparator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
6804
|
-
return new RegExp(`^-?\\d+(${escaped}\\d+)?$`).test(value);
|
|
6805
|
-
}
|
|
6806
|
-
detectSeparatorsForLocale(locale) {
|
|
6807
|
-
this._locale = locale;
|
|
6808
|
-
const parts = new Intl.NumberFormat(locale).formatToParts(1234567.89);
|
|
6809
|
-
this._decimalSeparator = parts.find(p => p.type === 'decimal')?.value ?? '.';
|
|
6810
|
-
this._groupSeparator = parts.find(p => p.type === 'group')?.value ?? ',';
|
|
6811
|
-
}
|
|
6812
|
-
filterValue(value) {
|
|
6813
|
-
let result = '';
|
|
6814
|
-
let hasDecimal = false;
|
|
6815
|
-
for (let i = 0; i < value.length; i++) {
|
|
6816
|
-
const char = value[i];
|
|
6817
|
-
if (char >= '0' && char <= '9') {
|
|
6818
|
-
result += char;
|
|
6819
|
-
}
|
|
6820
|
-
else if (char === this._decimalSeparator && !hasDecimal) {
|
|
6821
|
-
result += char;
|
|
6822
|
-
hasDecimal = true;
|
|
6823
|
-
}
|
|
6824
|
-
else if (char === '-' && i === 0) {
|
|
6825
|
-
result += char;
|
|
6826
|
-
}
|
|
6827
|
-
}
|
|
6828
|
-
return result;
|
|
6829
|
-
}
|
|
6830
|
-
parseValue(value) {
|
|
6831
|
-
if (!value)
|
|
6832
|
-
return value;
|
|
6833
|
-
const normalized = value.split(this._groupSeparator).join('').replace(this._decimalSeparator, '.');
|
|
6834
|
-
const parsed = parseFloat(normalized);
|
|
6835
|
-
return isNaN(parsed) ? value : parsed;
|
|
6836
|
-
}
|
|
6837
|
-
isAmbiguous(value) {
|
|
6838
|
-
if (typeof value !== 'string' || !value)
|
|
6839
|
-
return false;
|
|
6840
|
-
return /^-?[1-9]\d*[.,]\d{3}$/.test(value);
|
|
6841
|
-
}
|
|
6842
|
-
getAmbiguityHintKey(value) {
|
|
6843
|
-
if (typeof value === 'string' && value.includes('.'))
|
|
6844
|
-
return this.ambiguityHintKeyDot;
|
|
6845
|
-
return this.ambiguityHintKeyComma;
|
|
6846
|
-
}
|
|
6847
|
-
formatNumberForViewonly(value) {
|
|
6848
|
-
if (value == null || value === '')
|
|
6849
|
-
return '';
|
|
6850
|
-
const str = String(value);
|
|
6851
|
-
const parsed = typeof value === 'number' ? value : this.parseValue(str);
|
|
6852
|
-
if (typeof parsed !== 'number')
|
|
6853
|
-
return str;
|
|
6854
|
-
return new Intl.NumberFormat(this._locale).format(parsed);
|
|
6855
|
-
}
|
|
6856
|
-
formatValueForDisplay(value) {
|
|
6857
|
-
if (value == null || value === '')
|
|
6858
|
-
return '';
|
|
6859
|
-
const str = String(value);
|
|
6860
|
-
if (this._decimalSeparator === '.')
|
|
6861
|
-
return str;
|
|
6862
|
-
return str.replace('.', this._decimalSeparator);
|
|
6863
|
-
}
|
|
6864
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
6865
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService });
|
|
6866
|
-
}
|
|
6867
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNumberInputService, decorators: [{
|
|
6868
|
-
type: Injectable
|
|
6869
|
-
}], ctorParameters: () => [] });
|
|
6870
|
-
|
|
6871
|
-
/**
|
|
6872
|
-
* Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
|
|
6873
|
-
*
|
|
6874
|
-
* All service endpoints — including SSE — must be protected. The connection is therefore secured
|
|
6875
|
-
* via Quadrel Auth (Bearer token) by default. When the access token refreshes, the connection is
|
|
6876
|
-
* transparently rebuilt. Only disable authentication for endpoints that are explicitly public.
|
|
6877
|
-
*
|
|
6878
|
-
* ### Reconnection behavior
|
|
6879
|
-
*
|
|
6880
|
-
* - **Heartbeat timeout**: If no HEARTBEAT event arrives within the expected interval, the service reconnects.
|
|
6881
|
-
* - **401 Unauthorized**: Triggers exponential-backoff reconnection (max 5 attempts, capped at 30 s).
|
|
6882
|
-
* - **Other errors**: Reconnects immediately when the EventSource transitions to CLOSED.
|
|
6883
|
-
*
|
|
6884
|
-
* Existing `observe()` subscriptions are preserved across reconnections.
|
|
6885
|
-
*
|
|
6886
|
-
* ### Usage
|
|
6887
|
-
*
|
|
6888
|
-
* ```ts
|
|
6889
|
-
* pushEventsService.connect('https://api.example.com/events');
|
|
6890
|
-
*
|
|
6891
|
-
* const sub = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
|
|
6892
|
-
*
|
|
6893
|
-
* sub.unsubscribe();
|
|
6894
|
-
* pushEventsService.disconnect();
|
|
6895
|
-
* ```
|
|
6896
|
-
*/
|
|
6897
|
-
class QdPushEventsService {
|
|
6898
|
-
authenticationService = inject('QdAuthenticationService', { optional: true });
|
|
6899
|
-
_eventSource;
|
|
6900
|
-
_subjects = new Map();
|
|
6901
|
-
_listeners = [];
|
|
6902
|
-
_accessTokenSub;
|
|
6903
|
-
_options;
|
|
6904
|
-
_heartbeatTimeout;
|
|
6905
|
-
_heartbeatGracePeriod = 100;
|
|
6906
|
-
_initialHeartbeatTimeout = 10000;
|
|
6907
|
-
_isUnauthorized = false;
|
|
6908
|
-
_reconnectAttempts = 0;
|
|
6909
|
-
_maxReconnectAttempts = 5;
|
|
6910
|
-
_backoffTimer;
|
|
6911
|
-
/**
|
|
6912
|
-
* Opens an SSE connection to the given URL.
|
|
6913
|
-
*
|
|
6914
|
-
* With authentication enabled (default), the service subscribes to the `accessToken$` observable
|
|
6915
|
-
* provided by Quadrel Auth and rebuilds the connection whenever the token changes.
|
|
6916
|
-
* No-op if already connected.
|
|
6917
|
-
*
|
|
6918
|
-
* @param url The SSE endpoint URL.
|
|
6919
|
-
* @param options Set `{ disableAuthentication: true }` only for explicitly public endpoints.
|
|
6920
|
-
*
|
|
6921
|
-
* @example
|
|
6922
|
-
* ```ts
|
|
6923
|
-
* // Authenticated (default — requires Quadrel Auth)
|
|
6924
|
-
* pushEventsService.connect('https://api.example.com/events');
|
|
6925
|
-
*
|
|
6926
|
-
* // Without authentication (only for public endpoints)
|
|
6927
|
-
* pushEventsService.connect('https://api.example.com/public-events', { disableAuthentication: true });
|
|
6928
|
-
* ```
|
|
6929
|
-
*/
|
|
6930
|
-
connect(url, options) {
|
|
6931
|
-
if (this.isConnectedOrConnecting())
|
|
6932
|
-
return;
|
|
6933
|
-
this._options = { url, options };
|
|
6934
|
-
if (options?.disableAuthentication) {
|
|
6935
|
-
this.openEventSource(url);
|
|
6936
|
-
}
|
|
6937
|
-
else {
|
|
6938
|
-
this.connectWithAuth(url);
|
|
6939
|
-
}
|
|
6940
|
-
}
|
|
6941
|
-
/**
|
|
6942
|
-
* Closes the EventSource connection, clears all event listeners, and cancels pending backoff timers.
|
|
6943
|
-
* Subscription subjects are preserved so that a subsequent `connect()` re-attaches them.
|
|
6944
|
-
*
|
|
6945
|
-
* @example
|
|
6946
|
-
* ```ts
|
|
6947
|
-
* pushEventsService.disconnect();
|
|
6948
|
-
* // Subjects survive — a new connect() will re-attach existing observe() subscriptions.
|
|
6949
|
-
* ```
|
|
6950
|
-
*/
|
|
6951
|
-
disconnect() {
|
|
6952
|
-
if (!this._eventSource) {
|
|
6953
|
-
this.logWarn('No active connection to disconnect.');
|
|
6954
|
-
return;
|
|
6955
|
-
}
|
|
6956
|
-
if (this._accessTokenSub) {
|
|
6957
|
-
this._accessTokenSub.unsubscribe();
|
|
6958
|
-
this._accessTokenSub = undefined;
|
|
6959
|
-
}
|
|
6960
|
-
if (this._heartbeatTimeout)
|
|
6961
|
-
clearTimeout(this._heartbeatTimeout);
|
|
6962
|
-
if (this._backoffTimer) {
|
|
6963
|
-
clearTimeout(this._backoffTimer);
|
|
6964
|
-
this._backoffTimer = undefined;
|
|
6965
|
-
}
|
|
6966
|
-
this.removeAllListeners();
|
|
6967
|
-
this._eventSource.close();
|
|
6968
|
-
}
|
|
6969
|
-
/**
|
|
6970
|
-
* Returns an Observable that emits whenever the server sends an event of the given type.
|
|
6971
|
-
*
|
|
6972
|
-
* Lazily registers an EventSource listener on first call per event name.
|
|
6973
|
-
* Returns `NEVER` and logs an error if no connection exists.
|
|
6974
|
-
*
|
|
6975
|
-
* @param eventName The SSE event type to listen for.
|
|
6976
|
-
*
|
|
6977
|
-
* @example
|
|
6978
|
-
* ```ts
|
|
6979
|
-
* pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleUpdate(event));
|
|
6980
|
-
* ```
|
|
6981
|
-
*/
|
|
6982
|
-
observe(eventName) {
|
|
6983
|
-
if (!this._eventSource) {
|
|
6984
|
-
this.logWarn('Cannot observe events without a connection. Call connect() first.');
|
|
6985
|
-
return NEVER;
|
|
6986
|
-
}
|
|
6987
|
-
if (!this._subjects.has(eventName)) {
|
|
6988
|
-
this._subjects.set(eventName, new Subject());
|
|
6989
|
-
this.addListener(eventName, (event) => this._subjects.get(eventName).next(event));
|
|
6990
|
-
}
|
|
6991
|
-
return this._subjects.get(eventName).asObservable();
|
|
6992
|
-
}
|
|
6993
|
-
/**
|
|
6994
|
-
* Removes all event listeners and clears all subscription subjects. The connection stays open.
|
|
6995
|
-
* Use this to reset all subscriptions without disconnecting the SSE stream.
|
|
6996
|
-
*
|
|
6997
|
-
* @example
|
|
6998
|
-
* ```ts
|
|
6999
|
-
* pushEventsService.unobserveAll();
|
|
7000
|
-
* // Connection remains open, but no events are forwarded until observe() is called again.
|
|
7001
|
-
* ```
|
|
7002
|
-
*/
|
|
7003
|
-
unobserveAll() {
|
|
7004
|
-
this.removeAllListeners();
|
|
7005
|
-
this._subjects.clear();
|
|
7006
|
-
}
|
|
7007
|
-
/** Returns `true` when the EventSource is in state OPEN or CONNECTING. */
|
|
7008
|
-
isConnectedOrConnecting() {
|
|
7009
|
-
return (this._eventSource &&
|
|
7010
|
-
(this._eventSource.readyState === EventSource.OPEN || this._eventSource.readyState === EventSource.CONNECTING));
|
|
7011
|
-
}
|
|
7012
|
-
connectWithAuth(url) {
|
|
7013
|
-
if (!this.authenticationService) {
|
|
7014
|
-
this.logError("Can't connect to SSE without Quadrel Auth as the connection has to be secured. Please install Quadrel Auth or disable authentication when connecting.");
|
|
7015
|
-
return;
|
|
7016
|
-
}
|
|
7017
|
-
this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
|
|
7018
|
-
this.openEventSource(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
7019
|
-
});
|
|
7020
|
-
}
|
|
7021
|
-
openEventSource(url, options = {}) {
|
|
7022
|
-
this._isUnauthorized = false;
|
|
7023
|
-
if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
|
|
7024
|
-
this._eventSource.close();
|
|
7025
|
-
this._eventSource = new EventSourcePolyfill(url, options);
|
|
7026
|
-
this._eventSource.onerror = (err) => this.handleError(err);
|
|
7027
|
-
this._eventSource.addEventListener('HEARTBEAT', (message) => this.handleHeartbeat(message));
|
|
7028
|
-
if (this._heartbeatTimeout)
|
|
7029
|
-
clearTimeout(this._heartbeatTimeout);
|
|
7030
|
-
this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._initialHeartbeatTimeout);
|
|
7031
|
-
if (this._backoffTimer) {
|
|
7032
|
-
clearTimeout(this._backoffTimer);
|
|
7033
|
-
this._backoffTimer = undefined;
|
|
7034
|
-
}
|
|
7035
|
-
this._listeners = [];
|
|
7036
|
-
this.reattachListeners();
|
|
7037
|
-
}
|
|
7038
|
-
reconnect() {
|
|
7039
|
-
if (this.isConnectedOrConnecting() || this._isUnauthorized)
|
|
7040
|
-
return;
|
|
7041
|
-
this.disconnect();
|
|
7042
|
-
this.connect(this._options.url, this._options.options);
|
|
7043
|
-
}
|
|
7044
|
-
handleError(err) {
|
|
7045
|
-
const status = err?.status || err?.target?.status;
|
|
7046
|
-
if (status === 401) {
|
|
7047
|
-
this._isUnauthorized = true;
|
|
7048
|
-
this.logError('SSE connection unauthorized (401):', err);
|
|
7049
|
-
this._eventSource.close();
|
|
7050
|
-
this.scheduleRetry();
|
|
7051
|
-
return;
|
|
7052
|
-
}
|
|
7053
|
-
if (this._eventSource.readyState === EventSource.CLOSED)
|
|
7054
|
-
this.reconnect();
|
|
7055
|
-
this.logError('SSE connection error:', err);
|
|
7056
|
-
}
|
|
7057
|
-
scheduleRetry() {
|
|
7058
|
-
if (this._reconnectAttempts >= this._maxReconnectAttempts) {
|
|
7059
|
-
this.logError(`SSE reconnect aborted after ${this._maxReconnectAttempts} failed attempts.`);
|
|
7060
|
-
return;
|
|
7061
|
-
}
|
|
7062
|
-
const delay = Math.min(1000 * Math.pow(2, this._reconnectAttempts), 30000);
|
|
7063
|
-
this._reconnectAttempts++;
|
|
7064
|
-
this._backoffTimer = setTimeout(() => {
|
|
7065
|
-
this._isUnauthorized = false;
|
|
7066
|
-
this.reconnect();
|
|
7067
|
-
}, delay);
|
|
7068
|
-
}
|
|
7069
|
-
handleHeartbeat(message) {
|
|
7070
|
-
if (this._isUnauthorized)
|
|
7071
|
-
return;
|
|
7072
|
-
if (this._heartbeatTimeout)
|
|
7073
|
-
clearTimeout(this._heartbeatTimeout);
|
|
7074
|
-
this._reconnectAttempts = 0;
|
|
7075
|
-
const interval = JSON.parse(message.data).interval;
|
|
7076
|
-
this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatGracePeriod);
|
|
7077
|
-
}
|
|
7078
|
-
addListener(eventName, callback) {
|
|
7079
|
-
this._eventSource.addEventListener(eventName, callback);
|
|
7080
|
-
this._listeners.push([eventName, callback]);
|
|
7081
|
-
}
|
|
7082
|
-
reattachListeners() {
|
|
7083
|
-
this._subjects.forEach((subject, eventName) => this.addListener(eventName, (event) => subject.next(event)));
|
|
7084
|
-
}
|
|
7085
|
-
removeAllListeners() {
|
|
7086
|
-
if (!this._eventSource)
|
|
7087
|
-
return;
|
|
7088
|
-
this._listeners.forEach(([eventName, callback]) => this._eventSource.removeEventListener(eventName, callback));
|
|
7089
|
-
this._listeners = [];
|
|
7090
|
-
}
|
|
7091
|
-
logWarn(message) {
|
|
7092
|
-
console.warn(`Quadrel Framework | QdPushEvents - ${message}`);
|
|
7093
|
-
}
|
|
7094
|
-
logError(message, err) {
|
|
7095
|
-
console.error(`Quadrel Framework | QdPushEvents - ${message}`, err);
|
|
7096
|
-
}
|
|
7097
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7098
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
|
|
7099
|
-
}
|
|
7100
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, decorators: [{
|
|
7101
|
-
type: Injectable,
|
|
7102
|
-
args: [{
|
|
7103
|
-
providedIn: 'root'
|
|
7104
|
-
}]
|
|
7105
|
-
}] });
|
|
7106
|
-
|
|
7107
6731
|
var breakpoints$1 = {
|
|
7108
6732
|
xs: 320,
|
|
7109
6733
|
sm: 600,
|
|
@@ -7242,6 +6866,526 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
7242
6866
|
}]
|
|
7243
6867
|
}] });
|
|
7244
6868
|
|
|
6869
|
+
class QdVisuallyHiddenDirective {
|
|
6870
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
6871
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: QdVisuallyHiddenDirective, isStandalone: false, selector: "[qdVisuallyHidden]", host: { classAttribute: "qd-visually-hidden" }, ngImport: i0 });
|
|
6872
|
+
}
|
|
6873
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, decorators: [{
|
|
6874
|
+
type: Directive,
|
|
6875
|
+
args: [{
|
|
6876
|
+
selector: '[qdVisuallyHidden]',
|
|
6877
|
+
host: { class: 'qd-visually-hidden' },
|
|
6878
|
+
standalone: false
|
|
6879
|
+
}]
|
|
6880
|
+
}] });
|
|
6881
|
+
|
|
6882
|
+
/**
|
|
6883
|
+
* Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
|
|
6884
|
+
*
|
|
6885
|
+
* All service endpoints — including SSE — must be protected. The connection is therefore secured
|
|
6886
|
+
* via Quadrel Auth (Bearer token) by default. When the access token refreshes, the connection is
|
|
6887
|
+
* transparently rebuilt. Only disable authentication for endpoints that are explicitly public.
|
|
6888
|
+
*
|
|
6889
|
+
* ### Reconnection behavior
|
|
6890
|
+
*
|
|
6891
|
+
* - **Heartbeat timeout**: If no HEARTBEAT event arrives within the expected interval, the service reconnects.
|
|
6892
|
+
* - **401 Unauthorized**: Triggers exponential-backoff reconnection (max 5 attempts, capped at 30 s).
|
|
6893
|
+
* - **Other errors**: Reconnects immediately when the EventSource transitions to CLOSED.
|
|
6894
|
+
*
|
|
6895
|
+
* Existing `observe()` subscriptions are preserved across reconnections.
|
|
6896
|
+
*
|
|
6897
|
+
* ### Usage
|
|
6898
|
+
*
|
|
6899
|
+
* ```ts
|
|
6900
|
+
* pushEventsService.connect('https://api.example.com/events');
|
|
6901
|
+
*
|
|
6902
|
+
* const sub = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
|
|
6903
|
+
*
|
|
6904
|
+
* sub.unsubscribe();
|
|
6905
|
+
* pushEventsService.disconnect();
|
|
6906
|
+
* ```
|
|
6907
|
+
*/
|
|
6908
|
+
class QdPushEventsService {
|
|
6909
|
+
authenticationService = inject('QdAuthenticationService', { optional: true });
|
|
6910
|
+
_eventSource;
|
|
6911
|
+
_subjects = new Map();
|
|
6912
|
+
_listeners = [];
|
|
6913
|
+
_accessTokenSub;
|
|
6914
|
+
_options;
|
|
6915
|
+
_heartbeatTimeout;
|
|
6916
|
+
_heartbeatGracePeriod = 100;
|
|
6917
|
+
_initialHeartbeatTimeout = 10000;
|
|
6918
|
+
_isUnauthorized = false;
|
|
6919
|
+
_reconnectAttempts = 0;
|
|
6920
|
+
_maxReconnectAttempts = 5;
|
|
6921
|
+
_backoffTimer;
|
|
6922
|
+
/**
|
|
6923
|
+
* Opens an SSE connection to the given URL.
|
|
6924
|
+
*
|
|
6925
|
+
* With authentication enabled (default), the service subscribes to the `accessToken$` observable
|
|
6926
|
+
* provided by Quadrel Auth and rebuilds the connection whenever the token changes.
|
|
6927
|
+
* No-op if already connected.
|
|
6928
|
+
*
|
|
6929
|
+
* @param url The SSE endpoint URL.
|
|
6930
|
+
* @param options Set `{ disableAuthentication: true }` only for explicitly public endpoints.
|
|
6931
|
+
*
|
|
6932
|
+
* @example
|
|
6933
|
+
* ```ts
|
|
6934
|
+
* // Authenticated (default — requires Quadrel Auth)
|
|
6935
|
+
* pushEventsService.connect('https://api.example.com/events');
|
|
6936
|
+
*
|
|
6937
|
+
* // Without authentication (only for public endpoints)
|
|
6938
|
+
* pushEventsService.connect('https://api.example.com/public-events', { disableAuthentication: true });
|
|
6939
|
+
* ```
|
|
6940
|
+
*/
|
|
6941
|
+
connect(url, options) {
|
|
6942
|
+
if (this.isConnectedOrConnecting())
|
|
6943
|
+
return;
|
|
6944
|
+
this._options = { url, options };
|
|
6945
|
+
if (options?.disableAuthentication) {
|
|
6946
|
+
this.openEventSource(url);
|
|
6947
|
+
}
|
|
6948
|
+
else {
|
|
6949
|
+
this.connectWithAuth(url);
|
|
6950
|
+
}
|
|
6951
|
+
}
|
|
6952
|
+
/**
|
|
6953
|
+
* Closes the EventSource connection, clears all event listeners, and cancels pending backoff timers.
|
|
6954
|
+
* Subscription subjects are preserved so that a subsequent `connect()` re-attaches them.
|
|
6955
|
+
*
|
|
6956
|
+
* @example
|
|
6957
|
+
* ```ts
|
|
6958
|
+
* pushEventsService.disconnect();
|
|
6959
|
+
* // Subjects survive — a new connect() will re-attach existing observe() subscriptions.
|
|
6960
|
+
* ```
|
|
6961
|
+
*/
|
|
6962
|
+
disconnect() {
|
|
6963
|
+
if (!this._eventSource) {
|
|
6964
|
+
this.logWarn('No active connection to disconnect.');
|
|
6965
|
+
return;
|
|
6966
|
+
}
|
|
6967
|
+
if (this._accessTokenSub) {
|
|
6968
|
+
this._accessTokenSub.unsubscribe();
|
|
6969
|
+
this._accessTokenSub = undefined;
|
|
6970
|
+
}
|
|
6971
|
+
if (this._heartbeatTimeout)
|
|
6972
|
+
clearTimeout(this._heartbeatTimeout);
|
|
6973
|
+
if (this._backoffTimer) {
|
|
6974
|
+
clearTimeout(this._backoffTimer);
|
|
6975
|
+
this._backoffTimer = undefined;
|
|
6976
|
+
}
|
|
6977
|
+
this.removeAllListeners();
|
|
6978
|
+
this._eventSource.close();
|
|
6979
|
+
}
|
|
6980
|
+
/**
|
|
6981
|
+
* Returns an Observable that emits whenever the server sends an event of the given type.
|
|
6982
|
+
*
|
|
6983
|
+
* Lazily registers an EventSource listener on first call per event name.
|
|
6984
|
+
* Returns `NEVER` and logs an error if no connection exists.
|
|
6985
|
+
*
|
|
6986
|
+
* @param eventName The SSE event type to listen for.
|
|
6987
|
+
*
|
|
6988
|
+
* @example
|
|
6989
|
+
* ```ts
|
|
6990
|
+
* pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleUpdate(event));
|
|
6991
|
+
* ```
|
|
6992
|
+
*/
|
|
6993
|
+
observe(eventName) {
|
|
6994
|
+
if (!this._eventSource) {
|
|
6995
|
+
this.logWarn('Cannot observe events without a connection. Call connect() first.');
|
|
6996
|
+
return NEVER;
|
|
6997
|
+
}
|
|
6998
|
+
if (!this._subjects.has(eventName)) {
|
|
6999
|
+
this._subjects.set(eventName, new Subject());
|
|
7000
|
+
this.addListener(eventName, (event) => this._subjects.get(eventName).next(event));
|
|
7001
|
+
}
|
|
7002
|
+
return this._subjects.get(eventName).asObservable();
|
|
7003
|
+
}
|
|
7004
|
+
/**
|
|
7005
|
+
* Removes all event listeners and clears all subscription subjects. The connection stays open.
|
|
7006
|
+
* Use this to reset all subscriptions without disconnecting the SSE stream.
|
|
7007
|
+
*
|
|
7008
|
+
* @example
|
|
7009
|
+
* ```ts
|
|
7010
|
+
* pushEventsService.unobserveAll();
|
|
7011
|
+
* // Connection remains open, but no events are forwarded until observe() is called again.
|
|
7012
|
+
* ```
|
|
7013
|
+
*/
|
|
7014
|
+
unobserveAll() {
|
|
7015
|
+
this.removeAllListeners();
|
|
7016
|
+
this._subjects.clear();
|
|
7017
|
+
}
|
|
7018
|
+
/** Returns `true` when the EventSource is in state OPEN or CONNECTING. */
|
|
7019
|
+
isConnectedOrConnecting() {
|
|
7020
|
+
return (this._eventSource &&
|
|
7021
|
+
(this._eventSource.readyState === EventSource.OPEN || this._eventSource.readyState === EventSource.CONNECTING));
|
|
7022
|
+
}
|
|
7023
|
+
connectWithAuth(url) {
|
|
7024
|
+
if (!this.authenticationService) {
|
|
7025
|
+
this.logError("Can't connect to SSE without Quadrel Auth as the connection has to be secured. Please install Quadrel Auth or disable authentication when connecting.");
|
|
7026
|
+
return;
|
|
7027
|
+
}
|
|
7028
|
+
this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
|
|
7029
|
+
this.openEventSource(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
7030
|
+
});
|
|
7031
|
+
}
|
|
7032
|
+
openEventSource(url, options = {}) {
|
|
7033
|
+
this._isUnauthorized = false;
|
|
7034
|
+
if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
|
|
7035
|
+
this._eventSource.close();
|
|
7036
|
+
this._eventSource = new EventSourcePolyfill(url, options);
|
|
7037
|
+
this._eventSource.onerror = (err) => this.handleError(err);
|
|
7038
|
+
this._eventSource.addEventListener('HEARTBEAT', (message) => this.handleHeartbeat(message));
|
|
7039
|
+
if (this._heartbeatTimeout)
|
|
7040
|
+
clearTimeout(this._heartbeatTimeout);
|
|
7041
|
+
this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._initialHeartbeatTimeout);
|
|
7042
|
+
if (this._backoffTimer) {
|
|
7043
|
+
clearTimeout(this._backoffTimer);
|
|
7044
|
+
this._backoffTimer = undefined;
|
|
7045
|
+
}
|
|
7046
|
+
this._listeners = [];
|
|
7047
|
+
this.reattachListeners();
|
|
7048
|
+
}
|
|
7049
|
+
reconnect() {
|
|
7050
|
+
if (this.isConnectedOrConnecting() || this._isUnauthorized)
|
|
7051
|
+
return;
|
|
7052
|
+
this.disconnect();
|
|
7053
|
+
this.connect(this._options.url, this._options.options);
|
|
7054
|
+
}
|
|
7055
|
+
handleError(err) {
|
|
7056
|
+
const status = err?.status || err?.target?.status;
|
|
7057
|
+
if (status === 401) {
|
|
7058
|
+
this._isUnauthorized = true;
|
|
7059
|
+
this.logError('SSE connection unauthorized (401):', err);
|
|
7060
|
+
this._eventSource.close();
|
|
7061
|
+
this.scheduleRetry();
|
|
7062
|
+
return;
|
|
7063
|
+
}
|
|
7064
|
+
if (this._eventSource.readyState === EventSource.CLOSED)
|
|
7065
|
+
this.reconnect();
|
|
7066
|
+
this.logError('SSE connection error:', err);
|
|
7067
|
+
}
|
|
7068
|
+
scheduleRetry() {
|
|
7069
|
+
if (this._reconnectAttempts >= this._maxReconnectAttempts) {
|
|
7070
|
+
this.logError(`SSE reconnect aborted after ${this._maxReconnectAttempts} failed attempts.`);
|
|
7071
|
+
return;
|
|
7072
|
+
}
|
|
7073
|
+
const delay = Math.min(1000 * Math.pow(2, this._reconnectAttempts), 30000);
|
|
7074
|
+
this._reconnectAttempts++;
|
|
7075
|
+
this._backoffTimer = setTimeout(() => {
|
|
7076
|
+
this._isUnauthorized = false;
|
|
7077
|
+
this.reconnect();
|
|
7078
|
+
}, delay);
|
|
7079
|
+
}
|
|
7080
|
+
handleHeartbeat(message) {
|
|
7081
|
+
if (this._isUnauthorized)
|
|
7082
|
+
return;
|
|
7083
|
+
if (this._heartbeatTimeout)
|
|
7084
|
+
clearTimeout(this._heartbeatTimeout);
|
|
7085
|
+
this._reconnectAttempts = 0;
|
|
7086
|
+
const interval = JSON.parse(message.data).interval;
|
|
7087
|
+
this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatGracePeriod);
|
|
7088
|
+
}
|
|
7089
|
+
addListener(eventName, callback) {
|
|
7090
|
+
this._eventSource.addEventListener(eventName, callback);
|
|
7091
|
+
this._listeners.push([eventName, callback]);
|
|
7092
|
+
}
|
|
7093
|
+
reattachListeners() {
|
|
7094
|
+
this._subjects.forEach((subject, eventName) => this.addListener(eventName, (event) => subject.next(event)));
|
|
7095
|
+
}
|
|
7096
|
+
removeAllListeners() {
|
|
7097
|
+
if (!this._eventSource)
|
|
7098
|
+
return;
|
|
7099
|
+
this._listeners.forEach(([eventName, callback]) => this._eventSource.removeEventListener(eventName, callback));
|
|
7100
|
+
this._listeners = [];
|
|
7101
|
+
}
|
|
7102
|
+
logWarn(message) {
|
|
7103
|
+
console.warn(`Quadrel Framework | QdPushEvents - ${message}`);
|
|
7104
|
+
}
|
|
7105
|
+
logError(message, err) {
|
|
7106
|
+
console.error(`Quadrel Framework | QdPushEvents - ${message}`, err);
|
|
7107
|
+
}
|
|
7108
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7109
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
|
|
7110
|
+
}
|
|
7111
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, decorators: [{
|
|
7112
|
+
type: Injectable,
|
|
7113
|
+
args: [{
|
|
7114
|
+
providedIn: 'root'
|
|
7115
|
+
}]
|
|
7116
|
+
}] });
|
|
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 — the table's sort and pagination today,
|
|
7122
|
+
* filter, search, and `qd-page-tabs` over time. Without coordination they each call
|
|
7123
|
+
* `router.navigate(...)` directly, which produces two failure modes:
|
|
7124
|
+
*
|
|
7125
|
+
* 1. **Race**: two navigates issued in the same JS turn cancel each other. Only the last writer
|
|
7126
|
+
* wins; the URL silently loses the cancelled feature's params.
|
|
7127
|
+
* 2. **History pollution**: a single user action that changes two features (e.g. clicking a sort
|
|
7128
|
+
* header resets the page index) ends up as two history entries. Browser-back only undoes one.
|
|
7129
|
+
*
|
|
7130
|
+
* `QdRouterQueryParamHubService` is the single funnel through which features run their query-param
|
|
7131
|
+
* reads and writes. It does three jobs:
|
|
7132
|
+
*
|
|
7133
|
+
* - **Ownership** — `claim()` / `release()` enforce one writer per param key, app-wide.
|
|
7134
|
+
* - **Shared reads** — `queryParams()` and `snapshotQueryParam()` expose the route state without
|
|
7135
|
+
* each feature needing its own `ActivatedRoute` subscription.
|
|
7136
|
+
* - **Coordinated writes** — `write()` buffers param updates within a microtask and serializes
|
|
7137
|
+
* navigations via a Promise chain, so two writes in the same JS turn become one history entry
|
|
7138
|
+
* and concurrent writes never race.
|
|
7139
|
+
*
|
|
7140
|
+
* The hub is feature-agnostic. Per-feature adapters (e.g. `QdTableSortRouterConnectorService`)
|
|
7141
|
+
* own their parsing/serialization and delegate the URL plumbing to the hub.
|
|
7142
|
+
*
|
|
7143
|
+
* ### Usage
|
|
7144
|
+
*
|
|
7145
|
+
* ```ts
|
|
7146
|
+
* @Injectable()
|
|
7147
|
+
* export class FilterRouterAdapterService {
|
|
7148
|
+
* private readonly _hub = inject(QdRouterQueryParamHubService);
|
|
7149
|
+
* private readonly _destroyRef = inject(DestroyRef);
|
|
7150
|
+
*
|
|
7151
|
+
* connect(state$: Observable<FilterState>, dispatch: (state: FilterState) => void): void {
|
|
7152
|
+
* if (!this._hub.isAvailable()) return;
|
|
7153
|
+
* if (!this._hub.claim(['filter'], this, this._destroyRef)) return;
|
|
7154
|
+
*
|
|
7155
|
+
* this._hub
|
|
7156
|
+
* .queryParams()
|
|
7157
|
+
* .pipe(takeUntilDestroyed(this._destroyRef))
|
|
7158
|
+
* .subscribe(params => dispatch(parseFilter(params['filter'])));
|
|
7159
|
+
*
|
|
7160
|
+
* state$
|
|
7161
|
+
* .pipe(takeUntilDestroyed(this._destroyRef))
|
|
7162
|
+
* .subscribe(state => this._hub.write({ filter: serializeFilter(state) }, false));
|
|
7163
|
+
* }
|
|
7164
|
+
* }
|
|
7165
|
+
* ```
|
|
7166
|
+
*/
|
|
7167
|
+
class QdRouterQueryParamHubService {
|
|
7168
|
+
/**
|
|
7169
|
+
* Replays whenever the router has finished a navigation (`NavigationEnd`, `NavigationCancel`
|
|
7170
|
+
* or `NavigationError` — every event that ends a navigation, regardless of outcome).
|
|
7171
|
+
* Adapters that want to delay a write until any in-flight navigation has settled can take(1)
|
|
7172
|
+
* on this stream before calling `write()`.
|
|
7173
|
+
*
|
|
7174
|
+
* Late subscribers receive the most recent settling event immediately, so an adapter that
|
|
7175
|
+
* mounts after the initial route navigation can observe the route as already-settled. The
|
|
7176
|
+
* first replayed tick may represent that initial route navigation rather than a user-driven
|
|
7177
|
+
* settling event — adapters that need to distinguish "the route just changed" should compare
|
|
7178
|
+
* `ActivatedRoute.snapshot` themselves.
|
|
7179
|
+
*
|
|
7180
|
+
* **When the hub is unavailable** (no `Router` / `ActivatedRoute` in the injector — see
|
|
7181
|
+
* `isAvailable()`) this observable never emits. Adapters that compose `navigationSettled$`
|
|
7182
|
+
* via operators like `switchMap` or `concat` must guard with `isAvailable()` first, otherwise
|
|
7183
|
+
* their pipelines hang silently.
|
|
7184
|
+
*/
|
|
7185
|
+
navigationSettled$;
|
|
7186
|
+
_router = inject(Router, { optional: true });
|
|
7187
|
+
_activatedRoute = inject(ActivatedRoute, { optional: true });
|
|
7188
|
+
_destroyRef = inject(DestroyRef);
|
|
7189
|
+
_ownership = new Map();
|
|
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
|
+
* @returns `true` if every requested key is now owned by `owner`. `false` if at least one key
|
|
7245
|
+
* was already owned by a different adapter; the registry is left untouched and `destroyRef`
|
|
7246
|
+
* is not registered.
|
|
7247
|
+
*/
|
|
7248
|
+
claim(keys, owner, destroyRef) {
|
|
7249
|
+
const conflicts = [];
|
|
7250
|
+
for (const key of keys) {
|
|
7251
|
+
const existing = this._ownership.get(key);
|
|
7252
|
+
if (existing && existing !== owner)
|
|
7253
|
+
conflicts.push(key);
|
|
7254
|
+
}
|
|
7255
|
+
if (conflicts.length > 0) {
|
|
7256
|
+
const list = conflicts.map(k => `"${k}"`).join(', ');
|
|
7257
|
+
console.error(`Quadrel Framework | QdRouterQueryParamHub - Query param ${list} ${conflicts.length === 1 ? 'is' : 'are'} ` +
|
|
7258
|
+
`already owned by another adapter. Disable the conflicting feature's URL sync or move it to a ` +
|
|
7259
|
+
`different param key.`);
|
|
7260
|
+
return false;
|
|
7261
|
+
}
|
|
7262
|
+
keys.forEach(key => this._ownership.set(key, owner));
|
|
7263
|
+
if (destroyRef && keys.length > 0)
|
|
7264
|
+
this.registerAutoRelease(owner, keys, destroyRef);
|
|
7265
|
+
return true;
|
|
7266
|
+
}
|
|
7267
|
+
/**
|
|
7268
|
+
* Drops `owner`'s claim on the given keys. Keys not owned by `owner` are left untouched —
|
|
7269
|
+
* a foreign release call cannot steal another adapter's ownership.
|
|
7270
|
+
*
|
|
7271
|
+
* Adapters typically release in their `DestroyRef.onDestroy` callback so a destroyed component
|
|
7272
|
+
* frees its keys for the next adapter that mounts.
|
|
7273
|
+
*/
|
|
7274
|
+
release(keys, owner) {
|
|
7275
|
+
keys.forEach(key => {
|
|
7276
|
+
if (this._ownership.get(key) === owner)
|
|
7277
|
+
this._ownership.delete(key);
|
|
7278
|
+
});
|
|
7279
|
+
}
|
|
7280
|
+
/**
|
|
7281
|
+
* Reactive view of `ActivatedRoute.queryParams`. Returns the empty observable if the hub is
|
|
7282
|
+
* not available (no Router/ActivatedRoute). Adapters subscribe here instead of injecting
|
|
7283
|
+
* `ActivatedRoute` themselves so the hub stays the single read funnel.
|
|
7284
|
+
*
|
|
7285
|
+
* The observable is hot — late subscribers receive the current params immediately.
|
|
7286
|
+
*/
|
|
7287
|
+
queryParams() {
|
|
7288
|
+
return this._activatedRoute?.queryParams ?? of({});
|
|
7289
|
+
}
|
|
7290
|
+
/**
|
|
7291
|
+
* Synchronous read of a single query param from the latest `ActivatedRoute` snapshot.
|
|
7292
|
+
* Adapters use this to detect "URL already matches the desired state" and skip a redundant
|
|
7293
|
+
* `write()`.
|
|
7294
|
+
*
|
|
7295
|
+
* @returns The param value, or `undefined` if the param is missing or the hub is unavailable.
|
|
7296
|
+
*/
|
|
7297
|
+
snapshotQueryParam(key) {
|
|
7298
|
+
return this._activatedRoute?.snapshot.queryParamMap.get(key) ?? undefined;
|
|
7299
|
+
}
|
|
7300
|
+
/**
|
|
7301
|
+
* Schedules a query-param update.
|
|
7302
|
+
*
|
|
7303
|
+
* Two coordination guarantees:
|
|
7304
|
+
*
|
|
7305
|
+
* - **Microtask batching** — every `write()` issued in the same JavaScript turn is merged into
|
|
7306
|
+
* a single `router.navigate(...)` call. A user action that changes two features at once
|
|
7307
|
+
* (e.g. sort change resets the page) becomes one history entry, not two. Note: batching is
|
|
7308
|
+
* per JS turn, not per logical user action — writes that fall into the next microtask after
|
|
7309
|
+
* a settled navigation produce a separate history entry, even when they belong to the same
|
|
7310
|
+
* conceptual gesture.
|
|
7311
|
+
* - **Serialized navigations** — flushes are chained on a Promise so a second flush only fires
|
|
7312
|
+
* after the previous `router.navigate` has settled. Concurrent navigates can therefore not
|
|
7313
|
+
* cancel each other. A rejected `router.navigate` (cancelled by a guard, redirected, or
|
|
7314
|
+
* failed) does not stop the chain — the next pending flush still runs. Rejections are not
|
|
7315
|
+
* logged here; consumers that need routing diagnostics should subscribe to `router.events`.
|
|
7316
|
+
*
|
|
7317
|
+
* Adapters are still responsible for skipping no-op writes (compare the desired value against
|
|
7318
|
+
* `snapshotQueryParam()` first), since the hub does not deduplicate identical values.
|
|
7319
|
+
*
|
|
7320
|
+
* Setting a param value to `undefined` removes the param from the URL via Angular Router's
|
|
7321
|
+
* `merge` behavior. Other params not mentioned in the call are preserved.
|
|
7322
|
+
*
|
|
7323
|
+
* @param params Partial map of query-param keys to their new values. Missing keys are not touched.
|
|
7324
|
+
* An empty object short-circuits and is a no-op.
|
|
7325
|
+
* @param replaceUrl `true` replaces the current history entry; `false` pushes a new entry.
|
|
7326
|
+
* When several `write()` calls in the same microtask disagree, `true` wins (so an initial
|
|
7327
|
+
* replace is preserved when a follow-up write would otherwise push). The escalation is
|
|
7328
|
+
* per-batch — after each flush the pending flag resets to `false`, so writes that arrive
|
|
7329
|
+
* in the next microtask start a fresh batch with their own `replaceUrl` argument.
|
|
7330
|
+
*/
|
|
7331
|
+
write(params, replaceUrl) {
|
|
7332
|
+
const router = this._router;
|
|
7333
|
+
const activatedRoute = this._activatedRoute;
|
|
7334
|
+
if (!router || !activatedRoute)
|
|
7335
|
+
return;
|
|
7336
|
+
if (Object.keys(params).length === 0)
|
|
7337
|
+
return;
|
|
7338
|
+
Object.assign(this._pendingParams, params);
|
|
7339
|
+
this._pendingReplaceUrl = this._pendingReplaceUrl || replaceUrl;
|
|
7340
|
+
if (this._flushScheduled)
|
|
7341
|
+
return;
|
|
7342
|
+
this._flushScheduled = true;
|
|
7343
|
+
Promise.resolve().then(() => this.flush(router, activatedRoute));
|
|
7344
|
+
}
|
|
7345
|
+
replayCurrentRouterStateForLateSubscribers(router) {
|
|
7346
|
+
if (router.navigated)
|
|
7347
|
+
this._navigationSettledSubject.next();
|
|
7348
|
+
}
|
|
7349
|
+
forwardSettlingRouterEventsToNavigationSettled(router) {
|
|
7350
|
+
router.events
|
|
7351
|
+
.pipe(filter(event => event instanceof NavigationEnd || event instanceof NavigationCancel || event instanceof NavigationError), takeUntilDestroyed(this._destroyRef))
|
|
7352
|
+
.subscribe(() => this._navigationSettledSubject.next());
|
|
7353
|
+
}
|
|
7354
|
+
registerAutoRelease(owner, keys, destroyRef) {
|
|
7355
|
+
const existingClaims = this._destroyClaims.get(destroyRef);
|
|
7356
|
+
if (existingClaims) {
|
|
7357
|
+
existingClaims.push({ owner, keys });
|
|
7358
|
+
return;
|
|
7359
|
+
}
|
|
7360
|
+
const claims = [{ owner, keys }];
|
|
7361
|
+
this._destroyClaims.set(destroyRef, claims);
|
|
7362
|
+
destroyRef.onDestroy(() => {
|
|
7363
|
+
for (const claim of claims)
|
|
7364
|
+
this.release(claim.keys, claim.owner);
|
|
7365
|
+
});
|
|
7366
|
+
}
|
|
7367
|
+
flush(router, activatedRoute) {
|
|
7368
|
+
const params = this._pendingParams;
|
|
7369
|
+
const replaceUrl = this._pendingReplaceUrl;
|
|
7370
|
+
this._pendingParams = {};
|
|
7371
|
+
this._pendingReplaceUrl = false;
|
|
7372
|
+
this._flushScheduled = false;
|
|
7373
|
+
const exec = () => router.navigate([], {
|
|
7374
|
+
relativeTo: activatedRoute,
|
|
7375
|
+
queryParams: params,
|
|
7376
|
+
queryParamsHandling: 'merge',
|
|
7377
|
+
replaceUrl
|
|
7378
|
+
});
|
|
7379
|
+
this._navigationChain = this._navigationChain.catch(() => undefined).then(exec);
|
|
7380
|
+
}
|
|
7381
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7382
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, providedIn: 'root' });
|
|
7383
|
+
}
|
|
7384
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdRouterQueryParamHubService, decorators: [{
|
|
7385
|
+
type: Injectable,
|
|
7386
|
+
args: [{ providedIn: 'root' }]
|
|
7387
|
+
}], ctorParameters: () => [] });
|
|
7388
|
+
|
|
7245
7389
|
const MAX_TOOLTIP_CHARACTER = 512;
|
|
7246
7390
|
const TOOLTIP_POSITIONS = [
|
|
7247
7391
|
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom' },
|
|
@@ -7347,18 +7491,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
7347
7491
|
type: Input
|
|
7348
7492
|
}] } });
|
|
7349
7493
|
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
}
|
|
7354
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdVisuallyHiddenDirective, decorators: [{
|
|
7355
|
-
type: Directive,
|
|
7356
|
-
args: [{
|
|
7357
|
-
selector: '[qdVisuallyHidden]',
|
|
7358
|
-
host: { class: 'qd-visually-hidden' },
|
|
7359
|
-
standalone: false
|
|
7360
|
-
}]
|
|
7361
|
-
}] });
|
|
7494
|
+
const QD_SAFE_BOTTOM_OFFSET = new InjectionToken('QD_SAFE_BOTTOM_OFFSET');
|
|
7495
|
+
|
|
7496
|
+
const QD_POPOVER_TOP_FIRST = new InjectionToken('QD_POPOVER_TOP_FIRST');
|
|
7362
7497
|
|
|
7363
7498
|
class QdCoreModule {
|
|
7364
7499
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdCoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
@@ -8436,11 +8571,11 @@ class QdFormHintComponent {
|
|
|
8436
8571
|
this.actionEmitterService.hintEventEmitterSubject.next(null);
|
|
8437
8572
|
}
|
|
8438
8573
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormHintComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8439
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFormHintComponent, isStandalone: false, selector: "qd-form-hint", inputs: { hint: "hint", control: "control", hasError: "hasError", hintAction: "hintAction", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-form-hint" }, ngImport: i0, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}
|
|
8574
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFormHintComponent, isStandalone: false, selector: "qd-form-hint", inputs: { hint: "hint", control: "control", hasError: "hasError", hintAction: "hintAction", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-form-hint" }, ngImport: i0, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}:host .qd-form-hint--hint-action{color:#069;cursor:pointer}:host .qd-form-hint--hint-action:hover,:host .qd-form-hint--hint-action:active,:host .qd-form-hint--hint-action:focus{text-decoration:underline}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdFormErrorComponent, selector: "qd-form-error", inputs: ["control"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
8440
8575
|
}
|
|
8441
8576
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFormHintComponent, decorators: [{
|
|
8442
8577
|
type: Component,
|
|
8443
|
-
args: [{ selector: 'qd-form-hint', host: { class: 'qd-form-hint' }, standalone: false, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}
|
|
8578
|
+
args: [{ selector: 'qd-form-hint', host: { class: 'qd-form-hint' }, standalone: false, template: "<div class=\"qd-form-hint\" [attr.data-test-id]=\"testId + '-hint'\">\n <ng-container *ngIf=\"!hasError && !hintAction\">\n {{ hint | translate }}\n </ng-container>\n <ng-container *ngIf=\"!hasError && hintAction\">\n <div class=\"qd-form-hint--hint-action\" (click)=\"handleClick()\">\n {{ hint | translate }}\n </div>\n </ng-container>\n</div>\n\n<div class=\"qd-form-hint--error\" [attr.data-test-id]=\"testId + '-error'\">\n <ng-container *ngIf=\"hasError\">\n <qd-form-error [control]=\"control\"></qd-form-error>\n </ng-container>\n</div>\n", styles: [":host{display:block;min-height:.75rem;color:#757575;font-size:.75rem;font-weight:300;line-height:.75rem}:host .qd-form-hint--error{color:#c70023}.qd-form-disabled :host{color:#979797}:host .qd-form-hint--hint-action{color:#069;cursor:pointer}:host .qd-form-hint--hint-action:hover,:host .qd-form-hint--hint-action:active,:host .qd-form-hint--hint-action:focus{text-decoration:underline}\n"] }]
|
|
8444
8579
|
}], propDecorators: { hint: [{
|
|
8445
8580
|
type: Input
|
|
8446
8581
|
}], control: [{
|
|
@@ -11065,7 +11200,6 @@ class QdInputComponent {
|
|
|
11065
11200
|
resolverRegistry = inject(QdFormOptionsResolverRegistry);
|
|
11066
11201
|
controlContainer = inject(ControlContainer, { optional: true, host: true, skipSelf: true });
|
|
11067
11202
|
eventBrokerService = inject(QdEventBrokerService, { optional: true });
|
|
11068
|
-
numberInputService = inject(QdNumberInputService);
|
|
11069
11203
|
/**
|
|
11070
11204
|
* The form control name can be assigned here if you want to use Reactive Forms.
|
|
11071
11205
|
*/
|
|
@@ -11140,13 +11274,9 @@ class QdInputComponent {
|
|
|
11140
11274
|
get isErrorFromOutside() {
|
|
11141
11275
|
return this.isError;
|
|
11142
11276
|
}
|
|
11143
|
-
get isAmbiguousState() {
|
|
11144
|
-
return this.isAmbiguousInput;
|
|
11145
|
-
}
|
|
11146
11277
|
inputElement;
|
|
11147
11278
|
inputType;
|
|
11148
11279
|
inputMode;
|
|
11149
|
-
htmlInputType;
|
|
11150
11280
|
placeholder;
|
|
11151
11281
|
label;
|
|
11152
11282
|
hint;
|
|
@@ -11158,7 +11288,6 @@ class QdInputComponent {
|
|
|
11158
11288
|
control;
|
|
11159
11289
|
_optionsResolver;
|
|
11160
11290
|
_subs = new Subscription();
|
|
11161
|
-
_isUserTyped = false;
|
|
11162
11291
|
_onChange = () => { };
|
|
11163
11292
|
_onTouch = () => { };
|
|
11164
11293
|
get hasOnlyUnitsError() {
|
|
@@ -11167,15 +11296,6 @@ class QdInputComponent {
|
|
|
11167
11296
|
get hasUnits() {
|
|
11168
11297
|
return this.config?.units?.length > 0;
|
|
11169
11298
|
}
|
|
11170
|
-
get ambiguityHintKey() {
|
|
11171
|
-
return this.numberInputService.getAmbiguityHintKey(this._value.value);
|
|
11172
|
-
}
|
|
11173
|
-
get isAmbiguousInput() {
|
|
11174
|
-
return (this.inputType === 'number' &&
|
|
11175
|
-
!this.hasError &&
|
|
11176
|
-
this._isUserTyped &&
|
|
11177
|
-
this.numberInputService.isAmbiguous(this._value.value));
|
|
11178
|
-
}
|
|
11179
11299
|
get numberOfCharacters() {
|
|
11180
11300
|
if (!this._value.value)
|
|
11181
11301
|
return 0;
|
|
@@ -11192,10 +11312,7 @@ class QdInputComponent {
|
|
|
11192
11312
|
return this.control.getMaxLengthOrUndefined();
|
|
11193
11313
|
}
|
|
11194
11314
|
get valueAsList() {
|
|
11195
|
-
|
|
11196
|
-
? this.numberInputService.formatNumberForViewonly(this._value.value)
|
|
11197
|
-
: this._value.value;
|
|
11198
|
-
return [`${displayValue}${this._value.unit ? ' ' + this._value.unit : ''}`];
|
|
11315
|
+
return [`${this._value.value}${this._value.unit ? ' ' + this._value.unit : ''}`];
|
|
11199
11316
|
}
|
|
11200
11317
|
ngOnInit() {
|
|
11201
11318
|
this.initializeOptionsResolver();
|
|
@@ -11208,11 +11325,6 @@ class QdInputComponent {
|
|
|
11208
11325
|
console.warn('Quadrel Framework | QdInput - Please use the QdFormControl instead of the Angular FormControl.');
|
|
11209
11326
|
}
|
|
11210
11327
|
}
|
|
11211
|
-
if (this.config.inputType === 'number' &&
|
|
11212
|
-
this.config.inputMode !== 'numeric' &&
|
|
11213
|
-
this.config.inputMode !== 'decimal' &&
|
|
11214
|
-
this.config.inputMode != null)
|
|
11215
|
-
console.error('QD-UI | QdInputComponent - Please use either decimal or numeric when using QdInputType number');
|
|
11216
11328
|
this.writeValue(this.value ?? getValue(this.config));
|
|
11217
11329
|
this.normalizeInitialControlValueIfNeeded();
|
|
11218
11330
|
this._subs.add(this.actionEmitterService.hintEventEmitter$.subscribe(() => this.clickHint.emit()));
|
|
@@ -11243,10 +11355,6 @@ class QdInputComponent {
|
|
|
11243
11355
|
writeValue(value) {
|
|
11244
11356
|
this._value = getValueWithUnit(value, this.config);
|
|
11245
11357
|
this._displayValue = String(this._value.value ?? '');
|
|
11246
|
-
this._isUserTyped = false;
|
|
11247
|
-
if (this.inputType === 'number') {
|
|
11248
|
-
this._value = { ...this._value, value: this.numberInputService.formatValueForDisplay(this._value.value) };
|
|
11249
|
-
}
|
|
11250
11358
|
}
|
|
11251
11359
|
setDisabledState(disabled) {
|
|
11252
11360
|
this.disabled = disabled;
|
|
@@ -11258,36 +11366,6 @@ class QdInputComponent {
|
|
|
11258
11366
|
if (input?.validity?.badInput)
|
|
11259
11367
|
return;
|
|
11260
11368
|
const value = event.target.value;
|
|
11261
|
-
if (this.inputType === 'number' && value && !this.numberInputService.isValidNumber(value)) {
|
|
11262
|
-
this.control?.setErrors({
|
|
11263
|
-
...this.control.errors,
|
|
11264
|
-
invalidCharacters: this.numberInputService.invalidCharactersErrorKey
|
|
11265
|
-
});
|
|
11266
|
-
return;
|
|
11267
|
-
}
|
|
11268
|
-
if (this.inputType === 'number' && value) {
|
|
11269
|
-
const valueWithoutGroups = value.split(this.numberInputService.groupSeparator).join('');
|
|
11270
|
-
const filtered = this.numberInputService.filterValue(valueWithoutGroups);
|
|
11271
|
-
const hasInvalidChars = filtered !== valueWithoutGroups;
|
|
11272
|
-
if (hasInvalidChars) {
|
|
11273
|
-
this._value = { ...this._value, value: filtered };
|
|
11274
|
-
if (this.control) {
|
|
11275
|
-
this.control.setErrors({
|
|
11276
|
-
...this.control.errors,
|
|
11277
|
-
invalidCharacters: this.numberInputService.invalidCharactersErrorKey
|
|
11278
|
-
});
|
|
11279
|
-
}
|
|
11280
|
-
this._isUserTyped = true;
|
|
11281
|
-
this._onTouch();
|
|
11282
|
-
this.emitValue();
|
|
11283
|
-
return;
|
|
11284
|
-
}
|
|
11285
|
-
if (this.control?.errors?.['invalidCharacters']) {
|
|
11286
|
-
const remainingErrors = Object.fromEntries(Object.entries(this.control.errors).filter(([key]) => key !== 'invalidCharacters'));
|
|
11287
|
-
this.control.setErrors(Object.keys(remainingErrors).length ? remainingErrors : null);
|
|
11288
|
-
}
|
|
11289
|
-
}
|
|
11290
|
-
this._isUserTyped = true;
|
|
11291
11369
|
this._value = { ...this._value, value };
|
|
11292
11370
|
this.emitValue();
|
|
11293
11371
|
this._onTouch();
|
|
@@ -11344,15 +11422,6 @@ class QdInputComponent {
|
|
|
11344
11422
|
updateConfig() {
|
|
11345
11423
|
this.inputType = getInputType(this.config);
|
|
11346
11424
|
this.inputMode = getInputMode(this.config);
|
|
11347
|
-
if (this.inputType === 'number') {
|
|
11348
|
-
this.htmlInputType = 'text';
|
|
11349
|
-
if (!this.inputMode) {
|
|
11350
|
-
this.inputMode = this.inputMode ?? 'decimal';
|
|
11351
|
-
}
|
|
11352
|
-
}
|
|
11353
|
-
else {
|
|
11354
|
-
this.htmlInputType = this.inputType;
|
|
11355
|
-
}
|
|
11356
11425
|
this.placeholder = getPlaceholder(this.config);
|
|
11357
11426
|
this.label = getLabel(this.config);
|
|
11358
11427
|
this.hint = getHint(this.config);
|
|
@@ -11371,15 +11440,13 @@ class QdInputComponent {
|
|
|
11371
11440
|
this._optionsResolver = this.resolverRegistry.findResolver();
|
|
11372
11441
|
}
|
|
11373
11442
|
emitValue() {
|
|
11374
|
-
const emittable = this.inputType === 'number' ? this.numberInputService.parseValue(this._value.value) : this._value.value;
|
|
11375
11443
|
if (this.hasUnits) {
|
|
11376
|
-
|
|
11377
|
-
this.
|
|
11378
|
-
this._onChange(emittableWithUnit);
|
|
11444
|
+
this.valueChange.emit(this._value);
|
|
11445
|
+
this._onChange(this._value);
|
|
11379
11446
|
}
|
|
11380
11447
|
else {
|
|
11381
|
-
this.valueChange.emit(
|
|
11382
|
-
this._onChange(
|
|
11448
|
+
this.valueChange.emit(this._value.value);
|
|
11449
|
+
this._onChange(this._value.value);
|
|
11383
11450
|
}
|
|
11384
11451
|
}
|
|
11385
11452
|
initOpModeSubscription() {
|
|
@@ -11402,12 +11469,9 @@ class QdInputComponent {
|
|
|
11402
11469
|
if (!isEqual(modelValue, target))
|
|
11403
11470
|
this.control.setValue(target, { emitEvent: false });
|
|
11404
11471
|
this._value = normalized;
|
|
11405
|
-
if (this.inputType === 'number') {
|
|
11406
|
-
this._value = { ...this._value, value: this.numberInputService.formatValueForDisplay(this._value.value) };
|
|
11407
|
-
}
|
|
11408
11472
|
}
|
|
11409
11473
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11410
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdInputComponent, isStandalone: false, selector: "qd-input", inputs: { formControlName: "formControlName", value: "value", config: "config", isError: "isError", testId: ["data-test-id", "testId"] }, outputs: { valueChange: "valueChange", enterClick: "enterClick", clickClear: "clickClear", clickHint: "clickHint", clickReadonly: "clickReadonly", clickViewonly: "clickViewonly" }, host: { properties: { "class.qd-input-readonly": "this.readonly", "class.qd-input--readonly-action": "this.readonlyAction", "class.qd-input-viewonly": "this.viewonly", "class.qd-input--viewonly-action": "this.viewonlyAction", "class.qd-form-hint-action": "this.hintAction", "class.qd-input-hint-action": "this.hintAction", "class.qd-form-disabled": "this.disabled", "class.qd-input-disabled": "this.disabled", "class.qd-input-focus": "this.isInputFocused", "class.qd-form-error": "this.hasError", "class.qd-input-error": "this.hasError", "class.qd-input-error-from-outside": "this.isErrorFromOutside"
|
|
11474
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdInputComponent, isStandalone: false, selector: "qd-input", inputs: { formControlName: "formControlName", value: "value", config: "config", isError: "isError", testId: ["data-test-id", "testId"] }, outputs: { valueChange: "valueChange", enterClick: "enterClick", clickClear: "clickClear", clickHint: "clickHint", clickReadonly: "clickReadonly", clickViewonly: "clickViewonly" }, host: { properties: { "class.qd-input-readonly": "this.readonly", "class.qd-input--readonly-action": "this.readonlyAction", "class.qd-input-viewonly": "this.viewonly", "class.qd-input--viewonly-action": "this.viewonlyAction", "class.qd-form-hint-action": "this.hintAction", "class.qd-input-hint-action": "this.hintAction", "class.qd-form-disabled": "this.disabled", "class.qd-input-disabled": "this.disabled", "class.qd-input-focus": "this.isInputFocused", "class.qd-form-error": "this.hasError", "class.qd-input-error": "this.hasError", "class.qd-input-error-from-outside": "this.isErrorFromOutside" } }, providers: [
|
|
11411
11475
|
{
|
|
11412
11476
|
provide: NG_VALUE_ACCESSOR,
|
|
11413
11477
|
useExisting: QdInputComponent,
|
|
@@ -11415,14 +11479,13 @@ class QdInputComponent {
|
|
|
11415
11479
|
},
|
|
11416
11480
|
QdFormsActionEmitterService,
|
|
11417
11481
|
QdFormOptionsResolverRegistry,
|
|
11418
|
-
QdNumberInputService,
|
|
11419
11482
|
// TODO: Remove when removing derived directive
|
|
11420
11483
|
QdPopoverSizingService,
|
|
11421
11484
|
{
|
|
11422
11485
|
provide: QD_FOCUSABLE_TOKEN,
|
|
11423
11486
|
useExisting: QdInputComponent
|
|
11424
11487
|
}
|
|
11425
|
-
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n
|
|
11488
|
+
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["input"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"inputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: QdAutofocusDirective, selector: "[qdAutofocus]", inputs: ["qdAutofocus"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "component", type: QdFormHintComponent, selector: "qd-form-hint", inputs: ["hint", "control", "hasError", "hintAction", "data-test-id"] }, { kind: "component", type: QdFormLabelComponent, selector: "qd-form-label", inputs: ["label", "isDisabled", "readonly", "viewonly", "control", "tooltip", "data-test-id"] }, { kind: "component", type: QdFormReadonlyComponent, selector: "qd-form-readonly", inputs: ["values", "readonlyAction", "data-test-id"] }, { kind: "component", type: QdFormViewonlyComponent, selector: "qd-form-viewonly", inputs: ["values", "viewonlyAction", "data-test-id"] }, { kind: "component", type: QdInputUnitsComponent, selector: "qd-input-units", inputs: ["config", "unit"], outputs: ["unitChange", "opened", "closed"] }, { kind: "directive", type: QdInputOptionsDirective, selector: "[qdInputOptions]", inputs: ["value", "config"], outputs: ["enterClick", "optionSelected"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
11426
11489
|
}
|
|
11427
11490
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdInputComponent, decorators: [{
|
|
11428
11491
|
type: Component,
|
|
@@ -11434,14 +11497,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
11434
11497
|
},
|
|
11435
11498
|
QdFormsActionEmitterService,
|
|
11436
11499
|
QdFormOptionsResolverRegistry,
|
|
11437
|
-
QdNumberInputService,
|
|
11438
11500
|
// TODO: Remove when removing derived directive
|
|
11439
11501
|
QdPopoverSizingService,
|
|
11440
11502
|
{
|
|
11441
11503
|
provide: QD_FOCUSABLE_TOKEN,
|
|
11442
11504
|
useExisting: QdInputComponent
|
|
11443
11505
|
}
|
|
11444
|
-
], standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n
|
|
11506
|
+
], standalone: false, template: "<qd-form-label\n [label]=\"label\"\n [readonly]=\"readonly\"\n [viewonly]=\"viewonly\"\n [control]=\"control\"\n [tooltip]=\"config?.tooltip\"\n [data-test-id]=\"testId\"\n></qd-form-label>\n\n<ng-container *ngIf=\"!readonly && !viewonly && !hasOptions\">\n <div class=\"qd-input-input\" (keydown.enter)=\"emitEnterClick()\">\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</ng-container>\n\n<div *ngIf=\"!readonly && !viewonly && hasOptions\">\n <div\n class=\"qd-input-input\"\n qdInputOptions\n [qdPopoverMinWidth]=\"200\"\n [config]=\"config\"\n [value]=\"_value.value\"\n (optionSelected)=\"handleOptionSelected($event)\"\n (enterClick)=\"emitEnterClick()\"\n >\n <!-- handle (enterClick) by options directive here because event has to be fired after selection -->\n <ng-container *ngTemplateOutlet=\"inputBox\"></ng-container>\n </div>\n\n <span class=\"qd-input-character-counter\" *ngIf=\"hasMaxLength\">{{ numberOfCharacters }} / {{ maxLength }}</span>\n\n <qd-form-hint\n *ngIf=\"hint || hasError\"\n [hint]=\"hint\"\n [control]=\"control\"\n [hasError]=\"hasError\"\n [hintAction]=\"hintAction\"\n [data-test-id]=\"testId\"\n ></qd-form-hint>\n</div>\n\n<qd-form-readonly\n *ngIf=\"readonly\"\n [values]=\"valueAsList\"\n [readonlyAction]=\"readonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-readonly>\n\n<qd-form-viewonly\n *ngIf=\"viewonly\"\n [values]=\"valueAsList\"\n [viewonlyAction]=\"viewonlyAction\"\n [data-test-id]=\"testId\"\n></qd-form-viewonly>\n\n<ng-template #inputBox>\n <input\n #input\n [placeholder]=\"placeholder | translate\"\n [value]=\"hasOptions ? (_value.value.toString() | translate) : _displayValue\"\n (input)=\"handleInput($event)\"\n (focus)=\"handleInputFocus()\"\n (blur)=\"handleInputBlur()\"\n [disabled]=\"disabled || readonly\"\n [type]=\"inputType\"\n [attr.inputmode]=\"inputMode\"\n [qdAutofocus]=\"hasAutofocus\"\n [attr.data-test-id]=\"testId + '-input'\"\n [step]=\"config?.step\"\n required\n />\n <div class=\"qd-input-suffix\">\n <qd-icon *ngIf=\"hasError && !hasOnlyUnitsError\" class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n <qd-icon *ngIf=\"clearable\" class=\"qd-input-clearable-icon\" icon=\"timesLarge\" (click)=\"clearInput()\"></qd-icon>\n <ng-content select=\"[qdIconButton]\"></ng-content>\n </div>\n <qd-input-units\n *ngIf=\"hasUnits\"\n [unit]=\"_value.unit\"\n [config]=\"config\"\n (unitChange)=\"handleUnitChange($event)\"\n (opened)=\"handleUnitsOpened()\"\n (closed)=\"handleUnitsClosed()\"\n ></qd-input-units>\n <div class=\"qd-input-suffix\" *ngIf=\"hasError && hasOnlyUnitsError\">\n <qd-icon class=\"qd-input-error-icon\" icon=\"exclamationCircleSolid\"></qd-icon>\n </div>\n</ng-template>\n", styles: [":host{position:relative;display:block;width:100%;flex-direction:column;margin-bottom:.75rem}:host .qd-input-input{display:flex;overflow:hidden;height:2.25rem;align-items:center;padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(180,180,180);border-radius:0;margin-bottom:.375rem;background-color:#fff}:host .qd-input-input:hover,:host .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(23,23,23);border-radius:0}:host .qd-input-input input{overflow:hidden;width:100%;flex-grow:1;border:none;background-color:#fff;color:#171717;font-size:.875rem;line-height:1.875rem}:host .qd-input-input input:hover,:host .qd-input-input input:focus,:host .qd-input-input input:active{border:none;outline:none}:host .qd-input-input input::placeholder{color:#b4b4b4}:host .qd-input-input input:focus::placeholder{display:block;color:#b4b4b4}:host .qd-input-input .qd-input-suffix{display:flex;align-items:center;margin-left:.75rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon{padding-right:.5rem;color:#c70023}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-error-icon+.qd-input-clearable-icon{margin-left:-.25rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon{margin-right:.5625rem;color:#979797;cursor:pointer;font-size:1.25rem;line-height:2rem}:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:hover,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:focus,:host .qd-input-input .qd-input-suffix ::ng-deep .qd-input-clearable-icon:active{color:#171717}:host .qd-input-input qd-input-units+.qd-input-suffix{margin:0 0 0 -.1875rem}:host .qd-input-character-counter{padding-left:.125rem;color:#757575;float:right;font-size:.75rem;font-weight:300;line-height:.75rem}:host:after{display:block;height:0;clear:both;content:\".\";visibility:hidden}:host.qd-input-focus .qd-input-input{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(0,102,153);border-radius:0;outline:none}:host.qd-input-readonly .qd-input-readonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-viewonly .qd-input-viewonly{color:#171717;font-size:.875rem;line-height:2.25rem}:host.qd-input-disabled .qd-input-input{border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled .qd-input-input input{background-color:#f5f5f5;color:#979797}:host.qd-input-disabled .qd-input-input input::placeholder{opacity:0}:host.qd-input-disabled .qd-input-input:hover,:host.qd-input-disabled .qd-input-input:active{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(151,151,151);background-color:#f5f5f5}:host.qd-input-disabled.qd-input-focus{border-color:#ff9b00}:host.qd-input--readonly-action .qd-input-readonly{color:#069;cursor:pointer}:host.qd-input--readonly-action .qd-input-readonly:hover,:host.qd-input--readonly-action .qd-input-readonly:active,:host.qd-input--readonly-action .qd-input-readonly:focus{text-decoration:underline}:host.qd-input--viewonly-action .qd-input-viewonly{color:#069;cursor:pointer}:host.qd-input--viewonly-action .qd-input-viewonly:hover,:host.qd-input--viewonly-action .qd-input-viewonly:active,:host.qd-input--viewonly-action .qd-input-viewonly:focus{text-decoration:underline}:host.qd-input-error .qd-input-input,:host.qd-input-error-from-outside .qd-input-input{padding:0 .0625rem 0 .5rem;border:.0625rem solid rgb(199,0,35)}:host.qd-input-error .qd-input-input:hover,:host.qd-input-error .qd-input-input:active,:host.qd-input-error-from-outside .qd-input-input:hover,:host.qd-input-error-from-outside .qd-input-input:active{padding:.0625rem 0 .0625rem .4375rem;border:.125rem solid rgb(199,0,35)}:host.qd-input-error.qd-input-focus,:host.qd-input-error-from-outside.qd-input-focus{border-color:#c70023}\n"] }]
|
|
11445
11507
|
}], propDecorators: { formControlName: [{
|
|
11446
11508
|
type: Input
|
|
11447
11509
|
}], value: [{
|
|
@@ -11501,9 +11563,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
11501
11563
|
}], isErrorFromOutside: [{
|
|
11502
11564
|
type: HostBinding,
|
|
11503
11565
|
args: ['class.qd-input-error-from-outside']
|
|
11504
|
-
}], isAmbiguousState: [{
|
|
11505
|
-
type: HostBinding,
|
|
11506
|
-
args: ['class.qd-input-ambiguous']
|
|
11507
11566
|
}], inputElement: [{
|
|
11508
11567
|
type: ViewChild,
|
|
11509
11568
|
args: ['input']
|
|
@@ -22932,6 +22991,9 @@ class QdTableStoreSelectorService {
|
|
|
22932
22991
|
return sort.find(entry => entry.column === column)?.direction ?? QdSortDirection.NONE;
|
|
22933
22992
|
});
|
|
22934
22993
|
}
|
|
22994
|
+
tableSort() {
|
|
22995
|
+
return createSelector(this.selectTables, tables => this.getTable(tables)?.sort);
|
|
22996
|
+
}
|
|
22935
22997
|
selectIsLoading() {
|
|
22936
22998
|
return createSelector(this.selectTables, tables => {
|
|
22937
22999
|
const { requestState } = this.getTable(tables) || {};
|
|
@@ -23118,6 +23180,9 @@ class QdTableStoreService {
|
|
|
23118
23180
|
columnSortDirection$(column) {
|
|
23119
23181
|
return this.store.select(this.tableStoreSelectorService.columnSortDirection(column));
|
|
23120
23182
|
}
|
|
23183
|
+
tableSort$() {
|
|
23184
|
+
return this.store.select(this.tableStoreSelectorService.tableSort());
|
|
23185
|
+
}
|
|
23121
23186
|
selectIsLoading$() {
|
|
23122
23187
|
return this.store.select(this.tableStoreSelectorService.selectIsLoading());
|
|
23123
23188
|
}
|
|
@@ -23588,6 +23653,130 @@ var QdPaginatorDirection;
|
|
|
23588
23653
|
QdPaginatorDirection[QdPaginatorDirection["LastPage"] = 3] = "LastPage";
|
|
23589
23654
|
})(QdPaginatorDirection || (QdPaginatorDirection = {}));
|
|
23590
23655
|
|
|
23656
|
+
const PAGE_PARAM_NAME = 'page';
|
|
23657
|
+
const SIZE_PARAM_NAME = 'size';
|
|
23658
|
+
const OWNED_PARAMS$1 = [PAGE_PARAM_NAME, SIZE_PARAM_NAME];
|
|
23659
|
+
const SIZE_SANITY_MAX = 1000;
|
|
23660
|
+
class QdTablePaginationRouterConnectorService {
|
|
23661
|
+
hub = inject(QdRouterQueryParamHubService);
|
|
23662
|
+
destroyRef = inject(DestroyRef);
|
|
23663
|
+
_connection;
|
|
23664
|
+
_readSubscription;
|
|
23665
|
+
_writeSubscription;
|
|
23666
|
+
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
23667
|
+
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
23668
|
+
_hasInitialUrlBeenSet = false;
|
|
23669
|
+
constructor() {
|
|
23670
|
+
this.destroyRef.onDestroy(() => {
|
|
23671
|
+
this.tearDownConnection();
|
|
23672
|
+
this.hub.release(OWNED_PARAMS$1, this);
|
|
23673
|
+
});
|
|
23674
|
+
}
|
|
23675
|
+
connectPaginationWithRouter(paginator, tableStoreService) {
|
|
23676
|
+
if (!paginator.shouldConnectWithRouter() || !this.hub.isAvailable())
|
|
23677
|
+
return of(false);
|
|
23678
|
+
if (!this.hub.claim(OWNED_PARAMS$1, this))
|
|
23679
|
+
return of(false);
|
|
23680
|
+
this._connection = {
|
|
23681
|
+
paginator: paginator,
|
|
23682
|
+
tableStoreService: tableStoreService
|
|
23683
|
+
};
|
|
23684
|
+
this._hasInitialUrlBeenSet = false;
|
|
23685
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
23686
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
23687
|
+
this.subscribeToUrlChanges();
|
|
23688
|
+
this.subscribeToStoreChanges();
|
|
23689
|
+
return this._activatedRouteChecked$;
|
|
23690
|
+
}
|
|
23691
|
+
disconnectPaginationFromRouter(paginator) {
|
|
23692
|
+
if (this._connection?.paginator !== paginator)
|
|
23693
|
+
return;
|
|
23694
|
+
this.tearDownConnection();
|
|
23695
|
+
this.hub.release(OWNED_PARAMS$1, this);
|
|
23696
|
+
}
|
|
23697
|
+
tearDownConnection() {
|
|
23698
|
+
this._connection = undefined;
|
|
23699
|
+
this._hasInitialUrlBeenSet = false;
|
|
23700
|
+
this._readSubscription?.unsubscribe();
|
|
23701
|
+
this._writeSubscription?.unsubscribe();
|
|
23702
|
+
}
|
|
23703
|
+
subscribeToUrlChanges() {
|
|
23704
|
+
const { tableStoreService } = this._connection;
|
|
23705
|
+
let isFirstEmit = true;
|
|
23706
|
+
this._readSubscription = this.hub.navigationSettled$
|
|
23707
|
+
.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 })))))
|
|
23708
|
+
.subscribe(({ params, currentInfo, totalCount }) => {
|
|
23709
|
+
const target = this.toStoreState(params);
|
|
23710
|
+
const isChanged = !currentInfo || currentInfo.pageIndex !== target.pageIndex || currentInfo.pageSize !== target.pageSize;
|
|
23711
|
+
if (isChanged) {
|
|
23712
|
+
tableStoreService.setPageParams(target.pageIndex, target.pageSize, totalCount);
|
|
23713
|
+
}
|
|
23714
|
+
if (isFirstEmit) {
|
|
23715
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
23716
|
+
isFirstEmit = false;
|
|
23717
|
+
}
|
|
23718
|
+
});
|
|
23719
|
+
}
|
|
23720
|
+
subscribeToStoreChanges() {
|
|
23721
|
+
const { tableStoreService } = this._connection;
|
|
23722
|
+
this._writeSubscription = tableStoreService
|
|
23723
|
+
.pageChangeInfo$()
|
|
23724
|
+
.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))))
|
|
23725
|
+
.subscribe(info => this.writeUrl(info.pageIndex, info.pageSize));
|
|
23726
|
+
}
|
|
23727
|
+
writeUrl(pageIndex, pageSize) {
|
|
23728
|
+
const replaceUrl = !this._hasInitialUrlBeenSet;
|
|
23729
|
+
this._hasInitialUrlBeenSet = true;
|
|
23730
|
+
const targetPage = String(pageIndex + 1);
|
|
23731
|
+
const targetSize = String(pageSize);
|
|
23732
|
+
const urlAlreadyMatches = this.hub.snapshotQueryParam(PAGE_PARAM_NAME) === targetPage &&
|
|
23733
|
+
this.hub.snapshotQueryParam(SIZE_PARAM_NAME) === targetSize;
|
|
23734
|
+
if (urlAlreadyMatches)
|
|
23735
|
+
return;
|
|
23736
|
+
this.hub.write({ [PAGE_PARAM_NAME]: targetPage, [SIZE_PARAM_NAME]: targetSize }, replaceUrl);
|
|
23737
|
+
}
|
|
23738
|
+
parseUrlParams(queryParams) {
|
|
23739
|
+
const result = {};
|
|
23740
|
+
const rawPage = queryParams[PAGE_PARAM_NAME];
|
|
23741
|
+
if (typeof rawPage === 'string' && this.isValidPositiveIntegerString(rawPage)) {
|
|
23742
|
+
result.page = Number(rawPage);
|
|
23743
|
+
}
|
|
23744
|
+
const rawSize = queryParams[SIZE_PARAM_NAME];
|
|
23745
|
+
if (typeof rawSize === 'string' &&
|
|
23746
|
+
this.isValidPositiveIntegerString(rawSize) &&
|
|
23747
|
+
this.isValidSize(Number(rawSize))) {
|
|
23748
|
+
result.size = Number(rawSize);
|
|
23749
|
+
}
|
|
23750
|
+
return result;
|
|
23751
|
+
}
|
|
23752
|
+
isValidPositiveIntegerString(raw) {
|
|
23753
|
+
return /^[1-9]\d*$/.test(raw);
|
|
23754
|
+
}
|
|
23755
|
+
isValidSize(value) {
|
|
23756
|
+
const pageSizes = this.getConfiguredPageSizes();
|
|
23757
|
+
if (pageSizes && pageSizes.length > 0) {
|
|
23758
|
+
return pageSizes.includes(value);
|
|
23759
|
+
}
|
|
23760
|
+
return value <= SIZE_SANITY_MAX;
|
|
23761
|
+
}
|
|
23762
|
+
getConfiguredPageSizes() {
|
|
23763
|
+
const pagination = this._connection?.paginator.config?.pagination;
|
|
23764
|
+
return typeof pagination === 'object' ? pagination.pageSizes : undefined;
|
|
23765
|
+
}
|
|
23766
|
+
toStoreState(params) {
|
|
23767
|
+
const { paginator } = this._connection;
|
|
23768
|
+
return {
|
|
23769
|
+
pageIndex: params.page !== undefined ? params.page - 1 : 0,
|
|
23770
|
+
pageSize: params.size ?? paginator.getPageSizeDefault()
|
|
23771
|
+
};
|
|
23772
|
+
}
|
|
23773
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
23774
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService });
|
|
23775
|
+
}
|
|
23776
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginationRouterConnectorService, decorators: [{
|
|
23777
|
+
type: Injectable
|
|
23778
|
+
}], ctorParameters: () => [] });
|
|
23779
|
+
|
|
23591
23780
|
class QdScrollingService {
|
|
23592
23781
|
scrollIntoViewIfNeeded(element, borderDirection = 'top', targetBorderDistance = 0) {
|
|
23593
23782
|
this.scrollIntoView(element, borderDirection, targetBorderDistance, true);
|
|
@@ -23816,6 +24005,7 @@ const PAGE_SIZE_DEFAULT = 25;
|
|
|
23816
24005
|
class QdTablePaginatorComponent {
|
|
23817
24006
|
tableDataResolver = inject(QD_TABLE_DATA_RESOLVER_TOKEN, { optional: true });
|
|
23818
24007
|
tableStoreService = inject(QdTableStoreService);
|
|
24008
|
+
routerConnector = inject(QdTablePaginationRouterConnectorService);
|
|
23819
24009
|
/**
|
|
23820
24010
|
* @description Configuration Model for Qd-Table.
|
|
23821
24011
|
*/
|
|
@@ -23852,11 +24042,39 @@ class QdTablePaginatorComponent {
|
|
|
23852
24042
|
this.totalCount$ = this.tableStoreService.totalCount$();
|
|
23853
24043
|
this.selectedRowsCount$ = this.tableStoreService.selectedRows$().pipe(map(ids => ids?.length ?? 0));
|
|
23854
24044
|
if (this.isConfigValid())
|
|
23855
|
-
this.
|
|
24045
|
+
this.startPagination();
|
|
23856
24046
|
}
|
|
23857
24047
|
ngOnDestroy() {
|
|
24048
|
+
this.routerConnector.disconnectPaginationFromRouter(this);
|
|
24049
|
+
this._destroyed$.next(null);
|
|
23858
24050
|
this._destroyed$.complete();
|
|
23859
24051
|
}
|
|
24052
|
+
/**
|
|
24053
|
+
* @description Whether this paginator should sync its state with the URL. Reads
|
|
24054
|
+
* `pagination.connectWithRouter` (default `false` — URL sync is opt-in and
|
|
24055
|
+
* requires an explicit `pagination: { connectWithRouter: true }`).
|
|
24056
|
+
*
|
|
24057
|
+
* Used by `QdTablePaginationRouterConnectorService` to decide whether to claim
|
|
24058
|
+
* the router-singleton for this paginator.
|
|
24059
|
+
*/
|
|
24060
|
+
shouldConnectWithRouter() {
|
|
24061
|
+
const pagination = this.config?.pagination;
|
|
24062
|
+
if (typeof pagination !== 'object')
|
|
24063
|
+
return false;
|
|
24064
|
+
return pagination.connectWithRouter === true;
|
|
24065
|
+
}
|
|
24066
|
+
/**
|
|
24067
|
+
* @description The effective default page size for this paginator. Resolves
|
|
24068
|
+
* `pagination.pageSizeDefault` first, then falls back to the first entry of
|
|
24069
|
+
* `pagination.pageSizes`, finally to the framework constant `PAGE_SIZE_DEFAULT`.
|
|
24070
|
+
*/
|
|
24071
|
+
getPageSizeDefault() {
|
|
24072
|
+
if (typeof this.config?.pagination !== 'object')
|
|
24073
|
+
return PAGE_SIZE_DEFAULT;
|
|
24074
|
+
const { pageSizeDefault, pageSizes } = this.config.pagination;
|
|
24075
|
+
const pageSize = pageSizes && pageSizes.length ? pageSizes[0] : PAGE_SIZE_DEFAULT;
|
|
24076
|
+
return pageSizeDefault || pageSize;
|
|
24077
|
+
}
|
|
23860
24078
|
navigateToPage(direction) {
|
|
23861
24079
|
if (!this.paginatorButtons)
|
|
23862
24080
|
return;
|
|
@@ -23877,16 +24095,22 @@ class QdTablePaginatorComponent {
|
|
|
23877
24095
|
}
|
|
23878
24096
|
return true;
|
|
23879
24097
|
}
|
|
24098
|
+
startPagination() {
|
|
24099
|
+
if (!this.shouldConnectWithRouter()) {
|
|
24100
|
+
this.initPagination();
|
|
24101
|
+
return;
|
|
24102
|
+
}
|
|
24103
|
+
this.routerConnector
|
|
24104
|
+
.connectPaginationWithRouter(this, this.tableStoreService)
|
|
24105
|
+
.pipe(takeUntil(this._destroyed$), first())
|
|
24106
|
+
.subscribe(connected => {
|
|
24107
|
+
if (!connected)
|
|
24108
|
+
this.initPagination();
|
|
24109
|
+
});
|
|
24110
|
+
}
|
|
23880
24111
|
initPagination() {
|
|
23881
24112
|
this.tableStoreService.setupPagination(this.getPageSizeDefault());
|
|
23882
24113
|
}
|
|
23883
|
-
getPageSizeDefault() {
|
|
23884
|
-
if (typeof this.config?.pagination !== 'object')
|
|
23885
|
-
return PAGE_SIZE_DEFAULT;
|
|
23886
|
-
const { pageSizeDefault, pageSizes } = this.config.pagination;
|
|
23887
|
-
const pageSize = pageSizes && pageSizes.length ? pageSizes[0] : PAGE_SIZE_DEFAULT;
|
|
23888
|
-
return pageSizeDefault || pageSize;
|
|
23889
|
-
}
|
|
23890
24114
|
calculatePageNumber(direction, totalCount, pageSize, currentPage) {
|
|
23891
24115
|
switch (direction) {
|
|
23892
24116
|
case QdPaginatorDirection.NextPage: {
|
|
@@ -23905,11 +24129,11 @@ class QdTablePaginatorComponent {
|
|
|
23905
24129
|
}
|
|
23906
24130
|
}
|
|
23907
24131
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23908
|
-
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 });
|
|
24132
|
+
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 });
|
|
23909
24133
|
}
|
|
23910
24134
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTablePaginatorComponent, decorators: [{
|
|
23911
24135
|
type: Component,
|
|
23912
|
-
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"] }]
|
|
24136
|
+
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"] }]
|
|
23913
24137
|
}], propDecorators: { config: [{
|
|
23914
24138
|
type: Input
|
|
23915
24139
|
}], testId: [{
|
|
@@ -23920,6 +24144,147 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
23920
24144
|
args: ['paginatorButtons']
|
|
23921
24145
|
}] } });
|
|
23922
24146
|
|
|
24147
|
+
const SORT_PARAM_NAME = 'sort';
|
|
24148
|
+
const OWNED_PARAMS = [SORT_PARAM_NAME];
|
|
24149
|
+
const SEGMENT_SEPARATOR = ',';
|
|
24150
|
+
const COLUMN_DIRECTION_SEPARATOR = '.';
|
|
24151
|
+
class QdTableSortRouterConnectorService {
|
|
24152
|
+
hub = inject(QdRouterQueryParamHubService);
|
|
24153
|
+
destroyRef = inject(DestroyRef);
|
|
24154
|
+
_connection;
|
|
24155
|
+
_readSubscription;
|
|
24156
|
+
_writeSubscription;
|
|
24157
|
+
_activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
24158
|
+
_activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
24159
|
+
_hasInitialUrlBeenSet = false;
|
|
24160
|
+
_hasWarnedMultiSegment = false;
|
|
24161
|
+
constructor() {
|
|
24162
|
+
this.destroyRef.onDestroy(() => {
|
|
24163
|
+
this.tearDownConnection();
|
|
24164
|
+
this.hub.release(OWNED_PARAMS, this);
|
|
24165
|
+
});
|
|
24166
|
+
}
|
|
24167
|
+
connectSortWithRouter(table, tableStoreService) {
|
|
24168
|
+
if (!this.shouldConnect(table) || !this.hub.isAvailable())
|
|
24169
|
+
return of(false);
|
|
24170
|
+
if (!this.hub.claim(OWNED_PARAMS, this))
|
|
24171
|
+
return of(false);
|
|
24172
|
+
this._connection = {
|
|
24173
|
+
table: table,
|
|
24174
|
+
tableStoreService: tableStoreService,
|
|
24175
|
+
configuredColumns: table.config.columns
|
|
24176
|
+
};
|
|
24177
|
+
this._hasInitialUrlBeenSet = false;
|
|
24178
|
+
this._hasWarnedMultiSegment = false;
|
|
24179
|
+
this._activatedRouteCheckedSubject = new ReplaySubject(1);
|
|
24180
|
+
this._activatedRouteChecked$ = this._activatedRouteCheckedSubject.asObservable();
|
|
24181
|
+
this.subscribeToUrlChanges();
|
|
24182
|
+
this.subscribeToStoreChanges();
|
|
24183
|
+
return this._activatedRouteChecked$;
|
|
24184
|
+
}
|
|
24185
|
+
disconnectSortFromRouter(table) {
|
|
24186
|
+
if (this._connection?.table !== table)
|
|
24187
|
+
return;
|
|
24188
|
+
this.tearDownConnection();
|
|
24189
|
+
this.hub.release(OWNED_PARAMS, this);
|
|
24190
|
+
}
|
|
24191
|
+
tearDownConnection() {
|
|
24192
|
+
this._connection = undefined;
|
|
24193
|
+
this._hasInitialUrlBeenSet = false;
|
|
24194
|
+
this._hasWarnedMultiSegment = false;
|
|
24195
|
+
this._readSubscription?.unsubscribe();
|
|
24196
|
+
this._writeSubscription?.unsubscribe();
|
|
24197
|
+
}
|
|
24198
|
+
subscribeToUrlChanges() {
|
|
24199
|
+
const { tableStoreService } = this._connection;
|
|
24200
|
+
let isFirstEmit = true;
|
|
24201
|
+
this._readSubscription = this.hub.navigationSettled$
|
|
24202
|
+
.pipe(switchMap(() => this.hub.queryParams()), map(queryParams => (typeof queryParams[SORT_PARAM_NAME] === 'string' ? queryParams[SORT_PARAM_NAME] : '')), distinctUntilChanged(), map(raw => this.parseRawSortValue(raw)))
|
|
24203
|
+
.subscribe(segments => {
|
|
24204
|
+
if (segments.length === 1) {
|
|
24205
|
+
const [{ column, direction }] = segments;
|
|
24206
|
+
tableStoreService.setSort(column, direction);
|
|
24207
|
+
}
|
|
24208
|
+
if (isFirstEmit) {
|
|
24209
|
+
this._activatedRouteCheckedSubject.next(true);
|
|
24210
|
+
isFirstEmit = false;
|
|
24211
|
+
}
|
|
24212
|
+
});
|
|
24213
|
+
}
|
|
24214
|
+
subscribeToStoreChanges() {
|
|
24215
|
+
const { tableStoreService } = this._connection;
|
|
24216
|
+
this._writeSubscription = tableStoreService
|
|
24217
|
+
.tableSort$()
|
|
24218
|
+
.pipe(filter((sort) => Array.isArray(sort)), map(sort => this.serializeSort(sort)), distinctUntilChanged(), switchMap(serialized => this.hub.navigationSettled$.pipe(take(1), map(() => serialized))))
|
|
24219
|
+
.subscribe(serialized => this.writeUrl(serialized));
|
|
24220
|
+
}
|
|
24221
|
+
writeUrl(serialized) {
|
|
24222
|
+
const replaceUrl = !this._hasInitialUrlBeenSet;
|
|
24223
|
+
this._hasInitialUrlBeenSet = true;
|
|
24224
|
+
if (this.hub.snapshotQueryParam(SORT_PARAM_NAME) === serialized)
|
|
24225
|
+
return;
|
|
24226
|
+
this.hub.write({ [SORT_PARAM_NAME]: serialized }, replaceUrl);
|
|
24227
|
+
}
|
|
24228
|
+
shouldConnect(table) {
|
|
24229
|
+
const sortConfig = table.config.sort;
|
|
24230
|
+
if (sortConfig === true || sortConfig === undefined)
|
|
24231
|
+
return false;
|
|
24232
|
+
return sortConfig.connectWithRouter === true;
|
|
24233
|
+
}
|
|
24234
|
+
parseRawSortValue(raw) {
|
|
24235
|
+
if (raw.length === 0)
|
|
24236
|
+
return [];
|
|
24237
|
+
const rawSegments = raw.split(SEGMENT_SEPARATOR);
|
|
24238
|
+
const validSegments = rawSegments
|
|
24239
|
+
.map(segment => this.parseSegment(segment))
|
|
24240
|
+
.filter((segment) => segment !== undefined);
|
|
24241
|
+
if (validSegments.length > 1) {
|
|
24242
|
+
if (!this._hasWarnedMultiSegment) {
|
|
24243
|
+
console.warn('Quadrel Framework | QdTable - Multi-column sort URL is not yet supported. Using first valid segment only.');
|
|
24244
|
+
this._hasWarnedMultiSegment = true;
|
|
24245
|
+
}
|
|
24246
|
+
return [validSegments[0]];
|
|
24247
|
+
}
|
|
24248
|
+
return validSegments;
|
|
24249
|
+
}
|
|
24250
|
+
parseSegment(segment) {
|
|
24251
|
+
if (segment.length === 0)
|
|
24252
|
+
return undefined;
|
|
24253
|
+
const separatorIndex = segment.indexOf(COLUMN_DIRECTION_SEPARATOR);
|
|
24254
|
+
if (separatorIndex <= 0 || separatorIndex === segment.length - 1)
|
|
24255
|
+
return undefined;
|
|
24256
|
+
const column = segment.slice(0, separatorIndex);
|
|
24257
|
+
const directionRaw = segment.slice(separatorIndex + 1).toLowerCase();
|
|
24258
|
+
if (!this.isValidColumn(column))
|
|
24259
|
+
return undefined;
|
|
24260
|
+
if (directionRaw === 'asc')
|
|
24261
|
+
return { column, direction: QdSortDirection.ASC };
|
|
24262
|
+
if (directionRaw === 'desc')
|
|
24263
|
+
return { column, direction: QdSortDirection.DESC };
|
|
24264
|
+
return undefined;
|
|
24265
|
+
}
|
|
24266
|
+
isValidColumn(column) {
|
|
24267
|
+
const config = this._connection?.configuredColumns.find(c => c.column === column);
|
|
24268
|
+
return !!config && config.sort !== undefined && config.sort.isDisabled !== true;
|
|
24269
|
+
}
|
|
24270
|
+
serializeSort(sort) {
|
|
24271
|
+
const active = sort.filter((entry) => entry.direction === QdSortDirection.ASC || entry.direction === QdSortDirection.DESC);
|
|
24272
|
+
if (active.length === 0)
|
|
24273
|
+
return undefined;
|
|
24274
|
+
return active
|
|
24275
|
+
.map(entry => `${entry.column}${COLUMN_DIRECTION_SEPARATOR}${this.directionToString(entry.direction)}`)
|
|
24276
|
+
.join(SEGMENT_SEPARATOR);
|
|
24277
|
+
}
|
|
24278
|
+
directionToString(direction) {
|
|
24279
|
+
return direction === QdSortDirection.ASC ? 'asc' : 'desc';
|
|
24280
|
+
}
|
|
24281
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
24282
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService });
|
|
24283
|
+
}
|
|
24284
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableSortRouterConnectorService, decorators: [{
|
|
24285
|
+
type: Injectable
|
|
24286
|
+
}], ctorParameters: () => [] });
|
|
24287
|
+
|
|
23923
24288
|
class QdTableRowActionsSecondaryMenuComponent {
|
|
23924
24289
|
actionsService = inject(QdTableSecondaryActionsService);
|
|
23925
24290
|
tableStore = inject(QdTableStoreService);
|
|
@@ -24535,6 +24900,7 @@ class QdTableComponent {
|
|
|
24535
24900
|
breakpointService = inject(QdBreakpointService);
|
|
24536
24901
|
resolverService = inject(QdTableResolverService);
|
|
24537
24902
|
confirmationDialogService = inject(QdConfirmationDialogOpenerService);
|
|
24903
|
+
sortRouterConnector = inject(QdTableSortRouterConnectorService);
|
|
24538
24904
|
/**
|
|
24539
24905
|
* Configuration of the table. The generic type specifies the column definition. <br />
|
|
24540
24906
|
*
|
|
@@ -24642,6 +25008,7 @@ class QdTableComponent {
|
|
|
24642
25008
|
this.tableStoreService.initTableState(this._data, this.hasResolver, this._connectors, this.hasPagination);
|
|
24643
25009
|
this.tableStoreService.updateTableStateRecentSecondaryAction(undefined);
|
|
24644
25010
|
this.tableStoreService.setupSort(this.config.columns);
|
|
25011
|
+
this.sortRouterConnector.connectSortWithRouter(this, this.tableStoreService).pipe(take(1)).subscribe();
|
|
24645
25012
|
this.resolverService.init(this.config.refreshOnLanguageChange, this.hasPagination);
|
|
24646
25013
|
this.data$ = this.tableStoreService.tableDataEntries$();
|
|
24647
25014
|
this.initializeResponsiveRowService();
|
|
@@ -24672,6 +25039,7 @@ class QdTableComponent {
|
|
|
24672
25039
|
}
|
|
24673
25040
|
}
|
|
24674
25041
|
ngOnDestroy() {
|
|
25042
|
+
this.sortRouterConnector.disconnectSortFromRouter(this);
|
|
24675
25043
|
this.tableStoreService.updateTableStateRecentSecondaryAction(undefined);
|
|
24676
25044
|
this.tableStoreService.resetConnectorStates();
|
|
24677
25045
|
this.fillingWidthService.destroy();
|
|
@@ -24841,7 +25209,8 @@ class QdTableComponent {
|
|
|
24841
25209
|
QdTableRowSelectionService,
|
|
24842
25210
|
QdTableFillingWidthService,
|
|
24843
25211
|
QdTableResolverService,
|
|
24844
|
-
QdTableExternalActionResultService
|
|
25212
|
+
QdTableExternalActionResultService,
|
|
25213
|
+
QdTableSortRouterConnectorService
|
|
24845
25214
|
], 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 });
|
|
24846
25215
|
}
|
|
24847
25216
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdTableComponent, decorators: [{
|
|
@@ -24855,7 +25224,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
24855
25224
|
QdTableRowSelectionService,
|
|
24856
25225
|
QdTableFillingWidthService,
|
|
24857
25226
|
QdTableResolverService,
|
|
24858
|
-
QdTableExternalActionResultService
|
|
25227
|
+
QdTableExternalActionResultService,
|
|
25228
|
+
QdTableSortRouterConnectorService
|
|
24859
25229
|
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
24860
25230
|
'[class.qd-table]': 'true',
|
|
24861
25231
|
'[class.main-column-fills-width]': 'whichColumnFillsWidth === "main"',
|
|
@@ -30550,147 +30920,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
30550
30920
|
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"] }]
|
|
30551
30921
|
}] });
|
|
30552
30922
|
|
|
30553
|
-
// @ts-strict-ignore
|
|
30554
|
-
class QdNavigationService {
|
|
30555
|
-
router = inject(Router);
|
|
30556
|
-
activatedRoute = inject(ActivatedRoute);
|
|
30557
|
-
routeLeafSnapshot$;
|
|
30558
|
-
routeData$;
|
|
30559
|
-
routeComponentInstanceSubject = new ReplaySubject(1);
|
|
30560
|
-
constructor() {
|
|
30561
|
-
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'));
|
|
30562
|
-
this.routeData$ = this.routeLeafSnapshot$.pipe(map((snapshot) => snapshot.routeConfig?.data || {}), shareReplay(1));
|
|
30563
|
-
}
|
|
30564
|
-
getLeafRoute(route) {
|
|
30565
|
-
if (!route.firstChild)
|
|
30566
|
-
return route;
|
|
30567
|
-
return this.getLeafRoute(route.firstChild);
|
|
30568
|
-
}
|
|
30569
|
-
isHome$() {
|
|
30570
|
-
return this.routeData$.pipe(map(({ isHome }) => isHome ?? false));
|
|
30571
|
-
}
|
|
30572
|
-
getRouteParams$() {
|
|
30573
|
-
return this.routeLeafSnapshot$.pipe(map(this.getMergedRouteParams.bind(this)));
|
|
30574
|
-
}
|
|
30575
|
-
getMergedRouteParams(snapshot) {
|
|
30576
|
-
if (!snapshot)
|
|
30577
|
-
return {};
|
|
30578
|
-
return {
|
|
30579
|
-
...this.getMergedRouteParams(snapshot.parent),
|
|
30580
|
-
...(snapshot.params || {})
|
|
30581
|
-
};
|
|
30582
|
-
}
|
|
30583
|
-
getPreviousHref$() {
|
|
30584
|
-
return this.routeData$.pipe(map(({ previousHref }) => previousHref));
|
|
30585
|
-
}
|
|
30586
|
-
navigate(commands, extras) {
|
|
30587
|
-
return this.router.navigate(commands, extras);
|
|
30588
|
-
}
|
|
30589
|
-
navigateByUrl(url, extras) {
|
|
30590
|
-
return this.router.navigateByUrl(url, extras);
|
|
30591
|
-
}
|
|
30592
|
-
updateRouteComponentInstance(routeComponentInstance) {
|
|
30593
|
-
this.routeComponentInstanceSubject.next(routeComponentInstance);
|
|
30594
|
-
}
|
|
30595
|
-
getRouteComponentInstance$() {
|
|
30596
|
-
return this.routeComponentInstanceSubject.asObservable();
|
|
30597
|
-
}
|
|
30598
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30599
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService });
|
|
30600
|
-
}
|
|
30601
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, decorators: [{
|
|
30602
|
-
type: Injectable
|
|
30603
|
-
}], ctorParameters: () => [] });
|
|
30604
|
-
|
|
30605
|
-
// @ts-strict-ignore
|
|
30606
|
-
class QdShellLeftService {
|
|
30607
|
-
_hasNavigation = new BehaviorSubject(false);
|
|
30608
|
-
_isNavigationPinned = new BehaviorSubject(false);
|
|
30609
|
-
_isNavigationRolledOver = new BehaviorSubject(false);
|
|
30610
|
-
hasNavigation$ = this._hasNavigation.asObservable();
|
|
30611
|
-
isNavigationPinned$ = this._isNavigationPinned.asObservable();
|
|
30612
|
-
isNavigationRolledOver$ = this._isNavigationRolledOver.asObservable();
|
|
30613
|
-
set config(config) {
|
|
30614
|
-
this._hasNavigation.next(config.navigation?.length > 0);
|
|
30615
|
-
}
|
|
30616
|
-
set isNavigationRolledOver(value) {
|
|
30617
|
-
this._isNavigationRolledOver.next(value);
|
|
30618
|
-
}
|
|
30619
|
-
togglePinnedNavigation() {
|
|
30620
|
-
this._isNavigationPinned.next(!this._isNavigationPinned.value);
|
|
30621
|
-
}
|
|
30622
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30623
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService });
|
|
30624
|
-
}
|
|
30625
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, decorators: [{
|
|
30626
|
-
type: Injectable
|
|
30627
|
-
}] });
|
|
30628
|
-
|
|
30629
|
-
class QdShellRightService {
|
|
30630
|
-
notificationsService = inject(QdNotificationsService);
|
|
30631
|
-
_open = new BehaviorSubject(false);
|
|
30632
|
-
_pinned = new BehaviorSubject(false);
|
|
30633
|
-
_hasNotificationsToggle = new BehaviorSubject(false);
|
|
30634
|
-
open$ = this._open.asObservable();
|
|
30635
|
-
pinned$ = this._pinned.asObservable();
|
|
30636
|
-
notifications$;
|
|
30637
|
-
set open(open) {
|
|
30638
|
-
this._open.next(open);
|
|
30639
|
-
}
|
|
30640
|
-
get hasNotificationsToggle$() {
|
|
30641
|
-
return combineLatest([this._hasNotificationsToggle, this.hasNotifications$]).pipe(map(([hasNotificationsToggle, hasNotifications]) => hasNotificationsToggle || hasNotifications));
|
|
30642
|
-
}
|
|
30643
|
-
get hasNotifications$() {
|
|
30644
|
-
return this.notifications$.pipe(map(notifications => notifications.length > 0));
|
|
30645
|
-
}
|
|
30646
|
-
set config(config) {
|
|
30647
|
-
this._hasNotificationsToggle.next(config.hasNotificationsToggle ?? false);
|
|
30648
|
-
}
|
|
30649
|
-
constructor() {
|
|
30650
|
-
const notificationsService = this.notificationsService;
|
|
30651
|
-
this.notifications$ = notificationsService.getNotificationsForContext('shell');
|
|
30652
|
-
this._open.pipe(filter(open => open)).subscribe(() => {
|
|
30653
|
-
this._pinned.next(false);
|
|
30654
|
-
});
|
|
30655
|
-
}
|
|
30656
|
-
toggleOpen() {
|
|
30657
|
-
this._open.next(!this._open.value);
|
|
30658
|
-
}
|
|
30659
|
-
togglePinned() {
|
|
30660
|
-
this._pinned.next(!this._pinned.value);
|
|
30661
|
-
}
|
|
30662
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30663
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService });
|
|
30664
|
-
}
|
|
30665
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, decorators: [{
|
|
30666
|
-
type: Injectable
|
|
30667
|
-
}], ctorParameters: () => [] });
|
|
30668
|
-
|
|
30669
|
-
// @ts-strict-ignore
|
|
30670
|
-
class QdShellHeaderMinimizationService {
|
|
30671
|
-
navigationService = inject(QdNavigationService);
|
|
30672
|
-
breakpointService = inject(QdBreakpointService);
|
|
30673
|
-
_headerMinimizedBreakpoints = ['sm', 'xs'];
|
|
30674
|
-
_config;
|
|
30675
|
-
_isInternal$ = new BehaviorSubject(false);
|
|
30676
|
-
set config(config) {
|
|
30677
|
-
this._config = config;
|
|
30678
|
-
this._isInternal$.next(config.isInternal);
|
|
30679
|
-
}
|
|
30680
|
-
isHeaderMinimized$() {
|
|
30681
|
-
const isMinimizedForAllBreakpoints$ = this._isInternal$.pipe(combineLatestWith(this.navigationService.isHome$()), map(([isInternal, isHomePage]) => isInternal ?? !isHomePage));
|
|
30682
|
-
return isMinimizedForAllBreakpoints$.pipe(combineLatestWith(this.breakpointService.getMatchingBreakpoint()), map(([isMinimizedForAllBreakpoints, breakpoint]) => isMinimizedForAllBreakpoints || this._isMinimizedBreakpoint(breakpoint)));
|
|
30683
|
-
}
|
|
30684
|
-
_isMinimizedBreakpoint(breakpoint) {
|
|
30685
|
-
return this._headerMinimizedBreakpoints.includes(breakpoint);
|
|
30686
|
-
}
|
|
30687
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
30688
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService });
|
|
30689
|
-
}
|
|
30690
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, decorators: [{
|
|
30691
|
-
type: Injectable
|
|
30692
|
-
}] });
|
|
30693
|
-
|
|
30694
30923
|
// @ts-strict-ignore
|
|
30695
30924
|
const loadJavascriptAsset = (path, scriptElementAttributes = {}) => {
|
|
30696
30925
|
const scriptElement = document.createElement('script');
|
|
@@ -31058,7 +31287,6 @@ class QdShellServiceNavigationComponent {
|
|
|
31058
31287
|
_config;
|
|
31059
31288
|
_destroyed$ = new Subject();
|
|
31060
31289
|
_attributesHaveBeenSet$ = new ReplaySubject(1);
|
|
31061
|
-
localeService = inject(QdLocaleService);
|
|
31062
31290
|
ngOnInit() {
|
|
31063
31291
|
loadJavascriptAsset(this.config?.javascriptAssetPath ?? DEFAULT_JAVASCRIPT_ASSET_PATH$1, {
|
|
31064
31292
|
defer: '',
|
|
@@ -31101,7 +31329,6 @@ class QdShellServiceNavigationComponent {
|
|
|
31101
31329
|
this._destroyed$.complete();
|
|
31102
31330
|
}
|
|
31103
31331
|
handleLanguageChange($event) {
|
|
31104
|
-
this.localeService.setServiceNavigationLanguage($event.detail);
|
|
31105
31332
|
this.useLanguage($event.detail);
|
|
31106
31333
|
}
|
|
31107
31334
|
handleLoginStatusChange($event) {
|
|
@@ -31148,6 +31375,162 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
31148
31375
|
args: ['serviceNavigation']
|
|
31149
31376
|
}] } });
|
|
31150
31377
|
|
|
31378
|
+
class QdShellServiceNavigationModule {
|
|
31379
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
31380
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, declarations: [QdShellServiceNavigationComponent], imports: [CommonModule], exports: [QdShellServiceNavigationComponent] });
|
|
31381
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, imports: [CommonModule] });
|
|
31382
|
+
}
|
|
31383
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, decorators: [{
|
|
31384
|
+
type: NgModule,
|
|
31385
|
+
args: [{
|
|
31386
|
+
imports: [CommonModule],
|
|
31387
|
+
declarations: [QdShellServiceNavigationComponent],
|
|
31388
|
+
exports: [QdShellServiceNavigationComponent],
|
|
31389
|
+
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
31390
|
+
}]
|
|
31391
|
+
}] });
|
|
31392
|
+
|
|
31393
|
+
// @ts-strict-ignore
|
|
31394
|
+
class QdNavigationService {
|
|
31395
|
+
router = inject(Router);
|
|
31396
|
+
activatedRoute = inject(ActivatedRoute);
|
|
31397
|
+
routeLeafSnapshot$;
|
|
31398
|
+
routeData$;
|
|
31399
|
+
routeComponentInstanceSubject = new ReplaySubject(1);
|
|
31400
|
+
constructor() {
|
|
31401
|
+
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'));
|
|
31402
|
+
this.routeData$ = this.routeLeafSnapshot$.pipe(map((snapshot) => snapshot.routeConfig?.data || {}), shareReplay(1));
|
|
31403
|
+
}
|
|
31404
|
+
getLeafRoute(route) {
|
|
31405
|
+
if (!route.firstChild)
|
|
31406
|
+
return route;
|
|
31407
|
+
return this.getLeafRoute(route.firstChild);
|
|
31408
|
+
}
|
|
31409
|
+
isHome$() {
|
|
31410
|
+
return this.routeData$.pipe(map(({ isHome }) => isHome ?? false));
|
|
31411
|
+
}
|
|
31412
|
+
getRouteParams$() {
|
|
31413
|
+
return this.routeLeafSnapshot$.pipe(map(this.getMergedRouteParams.bind(this)));
|
|
31414
|
+
}
|
|
31415
|
+
getMergedRouteParams(snapshot) {
|
|
31416
|
+
if (!snapshot)
|
|
31417
|
+
return {};
|
|
31418
|
+
return {
|
|
31419
|
+
...this.getMergedRouteParams(snapshot.parent),
|
|
31420
|
+
...(snapshot.params || {})
|
|
31421
|
+
};
|
|
31422
|
+
}
|
|
31423
|
+
getPreviousHref$() {
|
|
31424
|
+
return this.routeData$.pipe(map(({ previousHref }) => previousHref));
|
|
31425
|
+
}
|
|
31426
|
+
navigate(commands, extras) {
|
|
31427
|
+
return this.router.navigate(commands, extras);
|
|
31428
|
+
}
|
|
31429
|
+
navigateByUrl(url, extras) {
|
|
31430
|
+
return this.router.navigateByUrl(url, extras);
|
|
31431
|
+
}
|
|
31432
|
+
updateRouteComponentInstance(routeComponentInstance) {
|
|
31433
|
+
this.routeComponentInstanceSubject.next(routeComponentInstance);
|
|
31434
|
+
}
|
|
31435
|
+
getRouteComponentInstance$() {
|
|
31436
|
+
return this.routeComponentInstanceSubject.asObservable();
|
|
31437
|
+
}
|
|
31438
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31439
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService });
|
|
31440
|
+
}
|
|
31441
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdNavigationService, decorators: [{
|
|
31442
|
+
type: Injectable
|
|
31443
|
+
}], ctorParameters: () => [] });
|
|
31444
|
+
|
|
31445
|
+
// @ts-strict-ignore
|
|
31446
|
+
class QdShellLeftService {
|
|
31447
|
+
_hasNavigation = new BehaviorSubject(false);
|
|
31448
|
+
_isNavigationPinned = new BehaviorSubject(false);
|
|
31449
|
+
_isNavigationRolledOver = new BehaviorSubject(false);
|
|
31450
|
+
hasNavigation$ = this._hasNavigation.asObservable();
|
|
31451
|
+
isNavigationPinned$ = this._isNavigationPinned.asObservable();
|
|
31452
|
+
isNavigationRolledOver$ = this._isNavigationRolledOver.asObservable();
|
|
31453
|
+
set config(config) {
|
|
31454
|
+
this._hasNavigation.next(config.navigation?.length > 0);
|
|
31455
|
+
}
|
|
31456
|
+
set isNavigationRolledOver(value) {
|
|
31457
|
+
this._isNavigationRolledOver.next(value);
|
|
31458
|
+
}
|
|
31459
|
+
togglePinnedNavigation() {
|
|
31460
|
+
this._isNavigationPinned.next(!this._isNavigationPinned.value);
|
|
31461
|
+
}
|
|
31462
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31463
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService });
|
|
31464
|
+
}
|
|
31465
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellLeftService, decorators: [{
|
|
31466
|
+
type: Injectable
|
|
31467
|
+
}] });
|
|
31468
|
+
|
|
31469
|
+
class QdShellRightService {
|
|
31470
|
+
notificationsService = inject(QdNotificationsService);
|
|
31471
|
+
_open = new BehaviorSubject(false);
|
|
31472
|
+
_pinned = new BehaviorSubject(false);
|
|
31473
|
+
_hasNotificationsToggle = new BehaviorSubject(false);
|
|
31474
|
+
open$ = this._open.asObservable();
|
|
31475
|
+
pinned$ = this._pinned.asObservable();
|
|
31476
|
+
notifications$;
|
|
31477
|
+
set open(open) {
|
|
31478
|
+
this._open.next(open);
|
|
31479
|
+
}
|
|
31480
|
+
get hasNotificationsToggle$() {
|
|
31481
|
+
return combineLatest([this._hasNotificationsToggle, this.hasNotifications$]).pipe(map(([hasNotificationsToggle, hasNotifications]) => hasNotificationsToggle || hasNotifications));
|
|
31482
|
+
}
|
|
31483
|
+
get hasNotifications$() {
|
|
31484
|
+
return this.notifications$.pipe(map(notifications => notifications.length > 0));
|
|
31485
|
+
}
|
|
31486
|
+
set config(config) {
|
|
31487
|
+
this._hasNotificationsToggle.next(config.hasNotificationsToggle ?? false);
|
|
31488
|
+
}
|
|
31489
|
+
constructor() {
|
|
31490
|
+
const notificationsService = this.notificationsService;
|
|
31491
|
+
this.notifications$ = notificationsService.getNotificationsForContext('shell');
|
|
31492
|
+
this._open.pipe(filter(open => open)).subscribe(() => {
|
|
31493
|
+
this._pinned.next(false);
|
|
31494
|
+
});
|
|
31495
|
+
}
|
|
31496
|
+
toggleOpen() {
|
|
31497
|
+
this._open.next(!this._open.value);
|
|
31498
|
+
}
|
|
31499
|
+
togglePinned() {
|
|
31500
|
+
this._pinned.next(!this._pinned.value);
|
|
31501
|
+
}
|
|
31502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31503
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService });
|
|
31504
|
+
}
|
|
31505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellRightService, decorators: [{
|
|
31506
|
+
type: Injectable
|
|
31507
|
+
}], ctorParameters: () => [] });
|
|
31508
|
+
|
|
31509
|
+
// @ts-strict-ignore
|
|
31510
|
+
class QdShellHeaderMinimizationService {
|
|
31511
|
+
navigationService = inject(QdNavigationService);
|
|
31512
|
+
breakpointService = inject(QdBreakpointService);
|
|
31513
|
+
_headerMinimizedBreakpoints = ['sm', 'xs'];
|
|
31514
|
+
_config;
|
|
31515
|
+
_isInternal$ = new BehaviorSubject(false);
|
|
31516
|
+
set config(config) {
|
|
31517
|
+
this._config = config;
|
|
31518
|
+
this._isInternal$.next(config.isInternal);
|
|
31519
|
+
}
|
|
31520
|
+
isHeaderMinimized$() {
|
|
31521
|
+
const isMinimizedForAllBreakpoints$ = this._isInternal$.pipe(combineLatestWith(this.navigationService.isHome$()), map(([isInternal, isHomePage]) => isInternal ?? !isHomePage));
|
|
31522
|
+
return isMinimizedForAllBreakpoints$.pipe(combineLatestWith(this.breakpointService.getMatchingBreakpoint()), map(([isMinimizedForAllBreakpoints, breakpoint]) => isMinimizedForAllBreakpoints || this._isMinimizedBreakpoint(breakpoint)));
|
|
31523
|
+
}
|
|
31524
|
+
_isMinimizedBreakpoint(breakpoint) {
|
|
31525
|
+
return this._headerMinimizedBreakpoints.includes(breakpoint);
|
|
31526
|
+
}
|
|
31527
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
31528
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService });
|
|
31529
|
+
}
|
|
31530
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellHeaderMinimizationService, decorators: [{
|
|
31531
|
+
type: Injectable
|
|
31532
|
+
}] });
|
|
31533
|
+
|
|
31151
31534
|
// @ts-strict-ignore
|
|
31152
31535
|
const DEFAULT_LANGUAGE_LIST$1 = ['de', 'fr', 'it', 'en'];
|
|
31153
31536
|
class QdShellHeaderWidgetService {
|
|
@@ -32230,21 +32613,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
32230
32613
|
args: [QdCommentsComponent]
|
|
32231
32614
|
}] } });
|
|
32232
32615
|
|
|
32233
|
-
class QdShellServiceNavigationModule {
|
|
32234
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
32235
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, declarations: [QdShellServiceNavigationComponent], imports: [CommonModule], exports: [QdShellServiceNavigationComponent] });
|
|
32236
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, imports: [CommonModule] });
|
|
32237
|
-
}
|
|
32238
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdShellServiceNavigationModule, decorators: [{
|
|
32239
|
-
type: NgModule,
|
|
32240
|
-
args: [{
|
|
32241
|
-
imports: [CommonModule],
|
|
32242
|
-
declarations: [QdShellServiceNavigationComponent],
|
|
32243
|
-
exports: [QdShellServiceNavigationComponent],
|
|
32244
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
|
32245
|
-
}]
|
|
32246
|
-
}] });
|
|
32247
|
-
|
|
32248
32616
|
function initializeBreadcrumbServices(breadcrumbsService, dialogBreadcrumbsService) {
|
|
32249
32617
|
return () => {
|
|
32250
32618
|
breadcrumbsService.initialize();
|
|
@@ -33497,5 +33865,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
33497
33865
|
* Generated bundle index. Do not edit.
|
|
33498
33866
|
*/
|
|
33499
33867
|
|
|
33500
|
-
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,
|
|
33868
|
+
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 };
|
|
33501
33869
|
//# sourceMappingURL=quadrel-enterprise-ui-framework.mjs.map
|