@quadrel-enterprise-ui/framework 20.6.1 → 20.7.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 +325 -133
- package/fesm2022/quadrel-enterprise-ui-framework.mjs.map +1 -1
- package/index.d.ts +78 -47
- package/package.json +1 -1
- package/src/assets/styles/components/_components.all.scss +0 -1
- package/src/assets/styles/components/_components.filter.scss +0 -52
|
@@ -3,7 +3,7 @@ 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, combineLatestWith, forkJoin, delayWhen, withLatestFrom, async
|
|
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, combineLatestWith, forkJoin, delayWhen, withLatestFrom, async } from 'rxjs';
|
|
7
7
|
import { map, takeUntil, take, filter, catchError, debounceTime, startWith, distinctUntilChanged, concatMap, tap, skip, 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';
|
|
@@ -1161,6 +1161,7 @@ class QdConfirmationDialogOpenerService {
|
|
|
1161
1161
|
open(component, config) {
|
|
1162
1162
|
config.panelClass = 'qd-custom-panel';
|
|
1163
1163
|
config.width = config.dialogSize || QdDialogSize.Default;
|
|
1164
|
+
config.disableClose = true;
|
|
1164
1165
|
return this.dialog.open(component, config);
|
|
1165
1166
|
}
|
|
1166
1167
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdConfirmationDialogOpenerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
@@ -1222,8 +1223,8 @@ class QdDialogService {
|
|
|
1222
1223
|
open(component, config) {
|
|
1223
1224
|
config.panelClass = 'qd-custom-panel';
|
|
1224
1225
|
config.width = config.dialogSize || QdDialogSize.Default;
|
|
1226
|
+
config.disableClose = true;
|
|
1225
1227
|
if (config.dialogSize === QdDialogSize.FullWidth) {
|
|
1226
|
-
config.disableClose = true;
|
|
1227
1228
|
config.maxWidth = '100vw';
|
|
1228
1229
|
config.width = '100vw';
|
|
1229
1230
|
config.maxHeight = '100vh';
|
|
@@ -1435,8 +1436,7 @@ class QdDialogComponent {
|
|
|
1435
1436
|
this.dialogService.pageDialogCanClose$.pipe(takeUntil(this._destroyed$)).subscribe(entry => {
|
|
1436
1437
|
this._pageDialogCanCloseFn = entry?.owner === this.dialogRef ? entry.fn : null;
|
|
1437
1438
|
});
|
|
1438
|
-
|
|
1439
|
-
this.bindEscToClose();
|
|
1439
|
+
this.bindEscToClose();
|
|
1440
1440
|
}
|
|
1441
1441
|
ngAfterContentChecked() {
|
|
1442
1442
|
const children = Array.from(this.body?.nativeElement?.children ?? []);
|
|
@@ -6855,185 +6855,230 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
6855
6855
|
}] });
|
|
6856
6856
|
|
|
6857
6857
|
/**
|
|
6858
|
-
*
|
|
6858
|
+
* Manages a server-sent event (SSE) connection with automatic reconnection and heartbeat monitoring.
|
|
6859
6859
|
*
|
|
6860
|
-
*
|
|
6860
|
+
* All service endpoints — including SSE — must be protected. The connection is therefore secured
|
|
6861
|
+
* via Quadrel Auth (Bearer token) by default. When the access token refreshes, the connection is
|
|
6862
|
+
* transparently rebuilt. Only disable authentication for endpoints that are explicitly public.
|
|
6861
6863
|
*
|
|
6862
|
-
*
|
|
6863
|
-
*
|
|
6864
|
-
* - **
|
|
6865
|
-
* - **
|
|
6864
|
+
* ### Reconnection behavior
|
|
6865
|
+
*
|
|
6866
|
+
* - **Heartbeat timeout**: If no HEARTBEAT event arrives within the expected interval, the service reconnects.
|
|
6867
|
+
* - **401 Unauthorized**: Triggers exponential-backoff reconnection (max 5 attempts, capped at 30 s).
|
|
6868
|
+
* - **Other errors**: Reconnects immediately when the EventSource transitions to CLOSED.
|
|
6869
|
+
*
|
|
6870
|
+
* Existing `observe()` subscriptions are preserved across reconnections.
|
|
6866
6871
|
*
|
|
6867
6872
|
* ### Usage
|
|
6868
6873
|
*
|
|
6869
6874
|
* ```ts
|
|
6870
|
-
*
|
|
6871
|
-
* pushEventsService.connect('http://service-endpint/events');
|
|
6872
|
-
* // or start without authentication in case you don't need:
|
|
6873
|
-
* pushEventsService.connect('http://service-endpint/events', { disableAuthentication: true });
|
|
6875
|
+
* pushEventsService.connect('https://api.example.com/events');
|
|
6874
6876
|
*
|
|
6875
|
-
*
|
|
6876
|
-
* const subscription = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
|
|
6877
|
+
* const sub = pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleEvent(event));
|
|
6877
6878
|
*
|
|
6878
|
-
*
|
|
6879
|
-
* subscription.unsubscribe();
|
|
6880
|
-
*
|
|
6881
|
-
* // Disconnect the connection
|
|
6879
|
+
* sub.unsubscribe();
|
|
6882
6880
|
* pushEventsService.disconnect();
|
|
6883
6881
|
* ```
|
|
6884
6882
|
*/
|
|
6885
6883
|
class QdPushEventsService {
|
|
6886
6884
|
authenticationService = inject('QdAuthenticationService', { optional: true });
|
|
6887
6885
|
_eventSource;
|
|
6888
|
-
|
|
6886
|
+
_subjects = new Map();
|
|
6889
6887
|
_listeners = [];
|
|
6890
|
-
_heartbeatTimeout;
|
|
6891
|
-
_reconnectDelayTime = 10000;
|
|
6892
|
-
_heartbeatReconnectDelayTime = 100;
|
|
6893
6888
|
_accessTokenSub;
|
|
6894
6889
|
_options;
|
|
6890
|
+
_heartbeatTimeout;
|
|
6891
|
+
_heartbeatGracePeriod = 100;
|
|
6892
|
+
_initialHeartbeatTimeout = 10000;
|
|
6895
6893
|
_isUnauthorized = false;
|
|
6894
|
+
_reconnectAttempts = 0;
|
|
6895
|
+
_maxReconnectAttempts = 5;
|
|
6896
|
+
_backoffTimer;
|
|
6896
6897
|
/**
|
|
6897
|
-
*
|
|
6898
|
-
*
|
|
6899
|
-
*
|
|
6898
|
+
* Opens an SSE connection to the given URL.
|
|
6899
|
+
*
|
|
6900
|
+
* With authentication enabled (default), the service subscribes to the `accessToken$` observable
|
|
6901
|
+
* provided by Quadrel Auth and rebuilds the connection whenever the token changes.
|
|
6902
|
+
* No-op if already connected.
|
|
6903
|
+
*
|
|
6904
|
+
* @param url The SSE endpoint URL.
|
|
6905
|
+
* @param options Set `{ disableAuthentication: true }` only for explicitly public endpoints.
|
|
6906
|
+
*
|
|
6907
|
+
* @example
|
|
6908
|
+
* ```ts
|
|
6909
|
+
* // Authenticated (default — requires Quadrel Auth)
|
|
6910
|
+
* pushEventsService.connect('https://api.example.com/events');
|
|
6900
6911
|
*
|
|
6901
|
-
*
|
|
6902
|
-
*
|
|
6912
|
+
* // Without authentication (only for public endpoints)
|
|
6913
|
+
* pushEventsService.connect('https://api.example.com/public-events', { disableAuthentication: true });
|
|
6914
|
+
* ```
|
|
6903
6915
|
*/
|
|
6904
6916
|
connect(url, options) {
|
|
6905
6917
|
if (this.isConnectedOrConnecting())
|
|
6906
6918
|
return;
|
|
6907
|
-
|
|
6908
|
-
|
|
6909
|
-
|
|
6910
|
-
return;
|
|
6911
|
-
}
|
|
6912
|
-
if (this._accessTokenSub)
|
|
6913
|
-
this._accessTokenSub.unsubscribe();
|
|
6914
|
-
this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
|
|
6915
|
-
this._options = { url, options };
|
|
6916
|
-
this.connectEventSource(url, {
|
|
6917
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
6918
|
-
}, true);
|
|
6919
|
-
});
|
|
6919
|
+
this._options = { url, options };
|
|
6920
|
+
if (options?.disableAuthentication) {
|
|
6921
|
+
this.openEventSource(url);
|
|
6920
6922
|
}
|
|
6921
6923
|
else {
|
|
6922
|
-
this.
|
|
6923
|
-
this.connectEventSource(url);
|
|
6924
|
+
this.connectWithAuth(url);
|
|
6924
6925
|
}
|
|
6925
6926
|
}
|
|
6926
6927
|
/**
|
|
6927
|
-
* Closes the EventSource connection
|
|
6928
|
-
*
|
|
6928
|
+
* Closes the EventSource connection, clears all event listeners, and cancels pending backoff timers.
|
|
6929
|
+
* Subscription subjects are preserved so that a subsequent `connect()` re-attaches them.
|
|
6930
|
+
*
|
|
6931
|
+
* @example
|
|
6932
|
+
* ```ts
|
|
6933
|
+
* pushEventsService.disconnect();
|
|
6934
|
+
* // Subjects survive — a new connect() will re-attach existing observe() subscriptions.
|
|
6935
|
+
* ```
|
|
6929
6936
|
*/
|
|
6930
6937
|
disconnect() {
|
|
6931
6938
|
if (!this._eventSource) {
|
|
6932
6939
|
this.logWarn('No active connection to disconnect.');
|
|
6933
6940
|
return;
|
|
6934
6941
|
}
|
|
6935
|
-
this.
|
|
6942
|
+
if (this._accessTokenSub) {
|
|
6943
|
+
this._accessTokenSub.unsubscribe();
|
|
6944
|
+
this._accessTokenSub = undefined;
|
|
6945
|
+
}
|
|
6946
|
+
if (this._heartbeatTimeout)
|
|
6947
|
+
clearTimeout(this._heartbeatTimeout);
|
|
6948
|
+
if (this._backoffTimer) {
|
|
6949
|
+
clearTimeout(this._backoffTimer);
|
|
6950
|
+
this._backoffTimer = undefined;
|
|
6951
|
+
}
|
|
6952
|
+
this.removeAllListeners();
|
|
6936
6953
|
this._eventSource.close();
|
|
6937
6954
|
}
|
|
6938
6955
|
/**
|
|
6939
|
-
* Returns an Observable
|
|
6940
|
-
* If not connected, returns `NEVER` and logs an error.
|
|
6941
|
-
* Automatically adds a listener for the event if needed.
|
|
6956
|
+
* Returns an Observable that emits whenever the server sends an event of the given type.
|
|
6942
6957
|
*
|
|
6943
|
-
*
|
|
6944
|
-
*
|
|
6958
|
+
* Lazily registers an EventSource listener on first call per event name.
|
|
6959
|
+
* Returns `NEVER` and logs an error if no connection exists.
|
|
6960
|
+
*
|
|
6961
|
+
* @param eventName The SSE event type to listen for.
|
|
6962
|
+
*
|
|
6963
|
+
* @example
|
|
6964
|
+
* ```ts
|
|
6965
|
+
* pushEventsService.observe('RESOURCE_UPDATED').subscribe(event => handleUpdate(event));
|
|
6966
|
+
* ```
|
|
6945
6967
|
*/
|
|
6946
6968
|
observe(eventName) {
|
|
6947
6969
|
if (!this._eventSource) {
|
|
6948
|
-
this.
|
|
6970
|
+
this.logWarn('Cannot observe events without a connection. Call connect() first.');
|
|
6949
6971
|
return NEVER;
|
|
6950
6972
|
}
|
|
6951
|
-
if (!this.
|
|
6952
|
-
this.
|
|
6953
|
-
this.
|
|
6973
|
+
if (!this._subjects.has(eventName)) {
|
|
6974
|
+
this._subjects.set(eventName, new Subject());
|
|
6975
|
+
this.addListener(eventName, (event) => this._subjects.get(eventName).next(event));
|
|
6954
6976
|
}
|
|
6955
|
-
return this.
|
|
6977
|
+
return this._subjects.get(eventName).asObservable();
|
|
6956
6978
|
}
|
|
6957
6979
|
/**
|
|
6958
|
-
* Removes all listeners and clears all
|
|
6959
|
-
*
|
|
6980
|
+
* Removes all event listeners and clears all subscription subjects. The connection stays open.
|
|
6981
|
+
* Use this to reset all subscriptions without disconnecting the SSE stream.
|
|
6982
|
+
*
|
|
6983
|
+
* @example
|
|
6984
|
+
* ```ts
|
|
6985
|
+
* pushEventsService.unobserveAll();
|
|
6986
|
+
* // Connection remains open, but no events are forwarded until observe() is called again.
|
|
6987
|
+
* ```
|
|
6960
6988
|
*/
|
|
6961
6989
|
unobserveAll() {
|
|
6962
|
-
this.
|
|
6963
|
-
this.
|
|
6990
|
+
this.removeAllListeners();
|
|
6991
|
+
this._subjects.clear();
|
|
6964
6992
|
}
|
|
6965
|
-
/**
|
|
6966
|
-
* Checks if the EventSource is connected or in the process of connecting.
|
|
6967
|
-
*/
|
|
6993
|
+
/** Returns `true` when the EventSource is in state OPEN or CONNECTING. */
|
|
6968
6994
|
isConnectedOrConnecting() {
|
|
6969
6995
|
return (this._eventSource &&
|
|
6970
6996
|
(this._eventSource.readyState === EventSource.OPEN || this._eventSource.readyState === EventSource.CONNECTING));
|
|
6971
6997
|
}
|
|
6972
|
-
|
|
6973
|
-
if (this.
|
|
6998
|
+
connectWithAuth(url) {
|
|
6999
|
+
if (!this.authenticationService) {
|
|
7000
|
+
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.");
|
|
6974
7001
|
return;
|
|
6975
|
-
|
|
7002
|
+
}
|
|
7003
|
+
this._accessTokenSub = this.authenticationService.accessToken$.subscribe((token) => {
|
|
7004
|
+
this.openEventSource(url, { headers: { Authorization: `Bearer ${token}` } });
|
|
7005
|
+
});
|
|
7006
|
+
}
|
|
7007
|
+
openEventSource(url, options = {}) {
|
|
7008
|
+
this._isUnauthorized = false;
|
|
7009
|
+
if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
|
|
7010
|
+
this._eventSource.close();
|
|
7011
|
+
this._eventSource = new EventSourcePolyfill(url, options);
|
|
7012
|
+
this._eventSource.onerror = (err) => this.handleError(err);
|
|
7013
|
+
this._eventSource.addEventListener('HEARTBEAT', (message) => this.handleHeartbeat(message));
|
|
7014
|
+
if (this._heartbeatTimeout)
|
|
7015
|
+
clearTimeout(this._heartbeatTimeout);
|
|
7016
|
+
this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._initialHeartbeatTimeout);
|
|
7017
|
+
if (this._backoffTimer) {
|
|
7018
|
+
clearTimeout(this._backoffTimer);
|
|
7019
|
+
this._backoffTimer = undefined;
|
|
7020
|
+
}
|
|
7021
|
+
this._listeners = [];
|
|
7022
|
+
this.reattachListeners();
|
|
7023
|
+
}
|
|
7024
|
+
reconnect() {
|
|
7025
|
+
if (this.isConnectedOrConnecting() || this._isUnauthorized)
|
|
6976
7026
|
return;
|
|
6977
7027
|
this.disconnect();
|
|
6978
7028
|
this.connect(this._options.url, this._options.options);
|
|
6979
7029
|
}
|
|
6980
|
-
|
|
6981
|
-
const
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
7030
|
+
handleError(err) {
|
|
7031
|
+
const status = err?.status || err?.target?.status;
|
|
7032
|
+
if (status === 401) {
|
|
7033
|
+
this._isUnauthorized = true;
|
|
7034
|
+
this.logError('SSE connection unauthorized (401):', err);
|
|
7035
|
+
this._eventSource.close();
|
|
7036
|
+
this.scheduleRetry();
|
|
7037
|
+
return;
|
|
7038
|
+
}
|
|
7039
|
+
if (this._eventSource.readyState === EventSource.CLOSED)
|
|
7040
|
+
this.reconnect();
|
|
7041
|
+
this.logError('SSE connection error:', err);
|
|
7042
|
+
}
|
|
7043
|
+
scheduleRetry() {
|
|
7044
|
+
if (this._reconnectAttempts >= this._maxReconnectAttempts) {
|
|
7045
|
+
this.logError(`SSE reconnect aborted after ${this._maxReconnectAttempts} failed attempts.`);
|
|
7046
|
+
return;
|
|
7047
|
+
}
|
|
7048
|
+
const delay = Math.min(1000 * Math.pow(2, this._reconnectAttempts), 30000);
|
|
7049
|
+
this._reconnectAttempts++;
|
|
7050
|
+
this._backoffTimer = setTimeout(() => {
|
|
7051
|
+
this._isUnauthorized = false;
|
|
7052
|
+
this.reconnect();
|
|
7053
|
+
}, delay);
|
|
6988
7054
|
}
|
|
6989
|
-
|
|
6990
|
-
|
|
7055
|
+
handleHeartbeat(message) {
|
|
7056
|
+
if (this._isUnauthorized)
|
|
7057
|
+
return;
|
|
7058
|
+
if (this._heartbeatTimeout)
|
|
7059
|
+
clearTimeout(this._heartbeatTimeout);
|
|
7060
|
+
this._reconnectAttempts = 0;
|
|
7061
|
+
const interval = JSON.parse(message.data).interval;
|
|
7062
|
+
this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatGracePeriod);
|
|
6991
7063
|
}
|
|
6992
|
-
|
|
7064
|
+
addListener(eventName, callback) {
|
|
6993
7065
|
this._eventSource.addEventListener(eventName, callback);
|
|
6994
7066
|
this._listeners.push([eventName, callback]);
|
|
6995
7067
|
}
|
|
6996
|
-
|
|
6997
|
-
|
|
6998
|
-
|
|
7068
|
+
reattachListeners() {
|
|
7069
|
+
this._subjects.forEach((subject, eventName) => this.addListener(eventName, (event) => subject.next(event)));
|
|
7070
|
+
}
|
|
7071
|
+
removeAllListeners() {
|
|
7072
|
+
if (!this._eventSource)
|
|
6999
7073
|
return;
|
|
7000
|
-
}
|
|
7001
7074
|
this._listeners.forEach(([eventName, callback]) => this._eventSource.removeEventListener(eventName, callback));
|
|
7002
7075
|
this._listeners = [];
|
|
7003
7076
|
}
|
|
7004
7077
|
logWarn(message) {
|
|
7005
|
-
console.warn(`QD-UI |
|
|
7078
|
+
console.warn(`QD-UI | QdPushEvents - ${message}`);
|
|
7006
7079
|
}
|
|
7007
7080
|
logError(message, err) {
|
|
7008
|
-
console.error(`QD-UI |
|
|
7009
|
-
}
|
|
7010
|
-
connectEventSource(url, options = {}, reconnect) {
|
|
7011
|
-
if (this._eventSource && this._eventSource.readyState !== EventSource.CLOSED)
|
|
7012
|
-
this._eventSource.close();
|
|
7013
|
-
if (!this._eventSource || this._eventSource.readyState === EventSource.CLOSED || reconnect)
|
|
7014
|
-
this._eventSource = new EventSourcePolyfill(url, options);
|
|
7015
|
-
this._eventSource.onerror = (err) => {
|
|
7016
|
-
const status = err?.status || err?.target?.status;
|
|
7017
|
-
if (status === 401) {
|
|
7018
|
-
this._isUnauthorized = true;
|
|
7019
|
-
this.logError('SSE connection unauthorized (401):', err);
|
|
7020
|
-
this._eventSource.close();
|
|
7021
|
-
return;
|
|
7022
|
-
}
|
|
7023
|
-
if (this._eventSource.readyState === EventSource.CLOSED)
|
|
7024
|
-
this.reconnect();
|
|
7025
|
-
this.logError('SSE connection error:', err);
|
|
7026
|
-
};
|
|
7027
|
-
this._eventSource.addEventListener('HEARTBEAT', (message) => {
|
|
7028
|
-
if (this._isUnauthorized)
|
|
7029
|
-
return;
|
|
7030
|
-
if (this._heartbeatTimeout)
|
|
7031
|
-
clearTimeout(this._heartbeatTimeout);
|
|
7032
|
-
const interval = JSON.parse(message.data).interval;
|
|
7033
|
-
this._heartbeatTimeout = setTimeout(() => this.reconnect(), interval + this._heartbeatReconnectDelayTime);
|
|
7034
|
-
});
|
|
7035
|
-
this._heartbeatTimeout = setTimeout(() => this.reconnect(), this._reconnectDelayTime);
|
|
7036
|
-
this.addEventListenersForExistingSubscriptions();
|
|
7081
|
+
console.error(`QD-UI | QdPushEvents - ${message}`, err);
|
|
7037
7082
|
}
|
|
7038
7083
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
7039
7084
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPushEventsService, providedIn: 'root' });
|
|
@@ -20736,11 +20781,11 @@ class QdFilterItemSelectCategoryComponent {
|
|
|
20736
20781
|
}));
|
|
20737
20782
|
}
|
|
20738
20783
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterItemSelectCategoryComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20739
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterItemSelectCategoryComponent, isStandalone: false, selector: "qd-filter-category-select", inputs: { filterId: "filterId", categoryIndex: "categoryIndex", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-filter__category-select" }, viewQueries: [{ propertyName: "popoverDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: QdChipComponent, selector: "qd-chip", inputs: ["state", "close", "data", "data-test-id"], outputs: ["closeClickEmitter"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "positionStrategy", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdFilterItemMultiSelectComponent, selector: "qd-filter-item-multi-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"] }, { kind: "component", type: QdFilterItemSingleSelectComponent, selector: "qd-filter-item-single-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"], outputs: ["closeEventEmitter"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20784
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFilterItemSelectCategoryComponent, isStandalone: false, selector: "qd-filter-category-select", inputs: { filterId: "filterId", categoryIndex: "categoryIndex", testId: ["data-test-id", "testId"] }, host: { classAttribute: "qd-filter__category-select" }, viewQueries: [{ propertyName: "popoverDirective", first: true, predicate: QdPopoverOnClickDirective, descendants: true }], ngImport: i0, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:1rem 0 0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:1rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "component", type: QdChipComponent, selector: "qd-chip", inputs: ["state", "close", "data", "data-test-id"], outputs: ["closeClickEmitter"] }, { kind: "component", type: QdFilterFormItemsComponent, selector: "qd-filter-form-items", inputs: ["inputFilterValue", "data-test-id"], outputs: ["filterValueChange"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }, { kind: "directive", type: QdPopoverOnClickDirective, selector: "[qdPopoverOnClick]", inputs: ["qdPopoverOnClick", "positionStrategy", "qdPopoverCloseStrategy", "qdPopoverDisabled", "qdPopoverStopPropagation", "qdPopoverBackgroundColor", "qdPopoverMaxHeight", "qdPopoverMinWidth", "qdPopoverMaxWidth", "qdPopoverAutoSize", "qdPopoverEnableKeyControl"], outputs: ["opened", "closed"], exportAs: ["qdPopoverOnClick"] }, { kind: "component", type: QdFilterItemMultiSelectComponent, selector: "qd-filter-item-multi-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"] }, { kind: "component", type: QdFilterItemSingleSelectComponent, selector: "qd-filter-item-single-select", inputs: ["filterId", "categoryIndex", "itemIndex", "data-test-id"], outputs: ["closeEventEmitter"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
20740
20785
|
}
|
|
20741
20786
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFilterItemSelectCategoryComponent, decorators: [{
|
|
20742
20787
|
type: Component,
|
|
20743
|
-
args: [{ selector: 'qd-filter-category-select', host: { class: 'qd-filter__category-select' }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n" }]
|
|
20788
|
+
args: [{ selector: 'qd-filter-category-select', host: { class: 'qd-filter__category-select' }, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<div\n *ngIf=\"showSelectButton$ | async\"\n [class]=\"buttonClassName\"\n [qdPopoverOnClick]=\"filterLayer\"\n [qdPopoverCloseStrategy]=\"'onOutsideClick'\"\n [qdPopoverStopPropagation]=\"true\"\n [qdPopoverMaxHeight]=\"maxFlyoutHeight\"\n [positionStrategy]=\"positionStrategy\"\n (opened)=\"onLayerOpened()\"\n (closed)=\"onLayerClosed()\"\n [attr.data-test-id]=\"testId + '-select-button'\"\n>\n <qd-icon\n *ngIf=\"!open\"\n [icon]=\"'ctrlDown'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--closed'\"\n [attr.data-test-id]=\"testId + '-closed'\"\n ></qd-icon>\n <qd-icon\n *ngIf=\"open\"\n [icon]=\"'ctrlTop'\"\n [class]=\"'qd-filter__category-icon qd-filter__category-icon--open'\"\n [attr.data-test-id]=\"testId + '-opened'\"\n ></qd-icon>\n\n <div class=\"qd-filter__category-button-caption\">\n <span>\n {{ i18n | translate }}\n </span>\n </div>\n\n <ng-container *ngTemplateOutlet=\"SelectedChip\"></ng-container>\n</div>\n\n<ng-template #filterLayer>\n <div [class]=\"layerContentClassName\">\n <qd-icon\n *ngIf=\"closeButton\"\n [class]=\"'qd-filter__category-layer-close'\"\n (click)=\"closeLayer()\"\n [icon]=\"'timesLargeLight'\"\n [attr.data-test-id]=\"testId + '-layer-close'\"\n ></qd-icon>\n\n <ng-container [ngSwitch]=\"type\">\n <ng-container *ngSwitchCase=\"'multiSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-multi-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-multi-select>\n </ng-container>\n </div>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'singleSelect'\">\n <qd-filter-form-items\n *ngIf=\"filter\"\n [inputFilterValue]=\"filterCategoryValue$ | async\"\n (filterValueChange)=\"changeValue($event)\"\n [data-test-id]=\"testId\"\n ></qd-filter-form-items>\n\n <div class=\"qd-filter__category-layer-items\">\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <qd-filter-item-single-select\n *ngIf=\"!item.hidden\"\n [categoryIndex]=\"categoryIndex\"\n [itemIndex]=\"itemIndex\"\n (closeEventEmitter)=\"closeLayer()\"\n [filterId]=\"filterId\"\n [data-test-id]=\"testId + '-item-' + itemIndex + '-' + item.item\"\n >\n </qd-filter-item-single-select>\n </ng-container>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</ng-template>\n\n<ng-template #SelectedChip>\n <ng-container *ngFor=\"let item of items; let itemIndex = index\">\n <!-- TODO: Add tooltip-->\n <qd-chip\n *ngIf=\"item.active\"\n [state]=\"'filter'\"\n [close]=\"true\"\n (closeClickEmitter)=\"close($event)\"\n [data]=\"itemIndex\"\n [data-test-id]=\"testId + '-selected-chip-' + item.item\"\n >{{ item.i18n | translate }}</qd-chip\n >\n </ng-container>\n</ng-template>\n", styles: ["::ng-deep .qd-filter__category-layer{display:flex;overflow:hidden;min-width:16.25rem;max-width:56.25rem;height:100%;flex-direction:column;padding:1rem 0 0;border:.0625rem solid rgb(151,151,151);background:#fff;box-shadow:#d5d5d5 .125rem .25rem .4375rem}::ng-deep .qd-filter__category-layer .qd-filter-form-items__filter{flex-shrink:0;margin-bottom:0}::ng-deep .qd-filter__category-layer .qd-checkbox__label{display:flex;height:2.5rem}::ng-deep .qd-filter__category-layer .qd-checkbox__indicator,::ng-deep .qd-filter__category-layer .qd-radio-buttons__indicator{transform:translateY(-.0625rem)}::ng-deep .qd-filter__category-layer-items{flex:1;overflow-y:auto}::ng-deep .qd-filter__category-layer-container{position:relative}::ng-deep .qd-filter__category-layer-close{position:absolute;z-index:1;top:1rem;right:1rem;color:#757575;cursor:pointer}::ng-deep .qd-filter__category-layer-close:before{position:absolute;content:\"\";inset:-.5rem}::ng-deep .qd-filter__category-layer-close:hover,::ng-deep .qd-filter__category-layer-close:focus{color:#171717}\n"] }]
|
|
20744
20789
|
}], propDecorators: { filterId: [{
|
|
20745
20790
|
type: Input
|
|
20746
20791
|
}], categoryIndex: [{
|
|
@@ -27158,18 +27203,24 @@ class QdFormGroupManagerService {
|
|
|
27158
27203
|
const snapshot = this._formGroupsSnapshot.get(key);
|
|
27159
27204
|
if (!snapshot)
|
|
27160
27205
|
return;
|
|
27161
|
-
|
|
27162
|
-
const newValue = snapshot[ctrlKey];
|
|
27163
|
-
if (ctrl instanceof FormArray && Array.isArray(newValue)) {
|
|
27164
|
-
this.resetFormArrayToValues(ctrl, newValue);
|
|
27165
|
-
}
|
|
27166
|
-
else {
|
|
27167
|
-
ctrl.reset(newValue);
|
|
27168
|
-
}
|
|
27169
|
-
});
|
|
27206
|
+
this.restoreFormGroup(fg, snapshot);
|
|
27170
27207
|
});
|
|
27171
27208
|
this.cancelPendingAsyncValidation();
|
|
27172
27209
|
}
|
|
27210
|
+
restoreFormGroup(fg, snapshot) {
|
|
27211
|
+
Object.entries(fg.controls).forEach(([ctrlKey, ctrl]) => {
|
|
27212
|
+
const newValue = snapshot[ctrlKey];
|
|
27213
|
+
if (ctrl instanceof FormArray && Array.isArray(newValue)) {
|
|
27214
|
+
this.resetFormArrayToValues(ctrl, newValue);
|
|
27215
|
+
}
|
|
27216
|
+
else if (ctrl instanceof FormGroup && newValue && typeof newValue === 'object') {
|
|
27217
|
+
this.restoreFormGroup(ctrl, newValue);
|
|
27218
|
+
}
|
|
27219
|
+
else {
|
|
27220
|
+
ctrl.reset(newValue);
|
|
27221
|
+
}
|
|
27222
|
+
});
|
|
27223
|
+
}
|
|
27173
27224
|
/**
|
|
27174
27225
|
* Cancels any in-flight async validators on all registered form groups.
|
|
27175
27226
|
*
|
|
@@ -28536,6 +28587,121 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
28536
28587
|
type: Output
|
|
28537
28588
|
}] } });
|
|
28538
28589
|
|
|
28590
|
+
/**
|
|
28591
|
+
* Intercepts router navigation when unsaved form changes exist on a QdPage.
|
|
28592
|
+
*
|
|
28593
|
+
* Provided per `QdPageComponent`. Activated automatically when the page enters an editable state
|
|
28594
|
+
* (create pages or inspect pages in edit mode). Deactivated when the page returns to view mode.
|
|
28595
|
+
*
|
|
28596
|
+
* #### When navigation is intercepted
|
|
28597
|
+
*
|
|
28598
|
+
* - The user has unsaved form changes (tracked via `QdFormGroupManagerService`).
|
|
28599
|
+
* - A `NavigationStart` event occurs (browser back, shell back button, or programmatic navigation).
|
|
28600
|
+
*
|
|
28601
|
+
* The current navigation is cancelled, and a confirmation dialog is shown. The user can either
|
|
28602
|
+
* discard changes and proceed or cancel and stay on the page.
|
|
28603
|
+
*
|
|
28604
|
+
* #### When navigation is allowed
|
|
28605
|
+
*
|
|
28606
|
+
* - No unsaved changes exist — navigation proceeds silently.
|
|
28607
|
+
* - A framework action (Submit, SaveDraft) wraps its handler via `executeWithBypass()`.
|
|
28608
|
+
* - A confirmed discard sets `allowNextNavigation()` before the cancel handler navigates.
|
|
28609
|
+
* - The page switches to view mode via `deactivate()`.
|
|
28610
|
+
*
|
|
28611
|
+
* Custom actions defined by the application are not bypassed. If a custom action navigates away
|
|
28612
|
+
* while unsaved changes exist, the confirmation dialog is shown.
|
|
28613
|
+
*/
|
|
28614
|
+
class QdPageNavigationInterceptorService {
|
|
28615
|
+
router = inject(Router);
|
|
28616
|
+
formGroupManager = inject(QdFormGroupManagerService);
|
|
28617
|
+
confirmationDialog = inject(QdConfirmationDialogOpenerService);
|
|
28618
|
+
_destroy$ = new Subject();
|
|
28619
|
+
_deactivate$ = new Subject();
|
|
28620
|
+
_bypassInterception = false;
|
|
28621
|
+
_allowedTargetUrls = new Set();
|
|
28622
|
+
_confirmationMessage;
|
|
28623
|
+
ngOnDestroy() {
|
|
28624
|
+
this._allowedTargetUrls.clear();
|
|
28625
|
+
this._destroy$.next();
|
|
28626
|
+
this._destroy$.complete();
|
|
28627
|
+
this._deactivate$.complete();
|
|
28628
|
+
}
|
|
28629
|
+
/**
|
|
28630
|
+
* Starts intercepting navigation events. Replaces any previously active listener.
|
|
28631
|
+
*/
|
|
28632
|
+
activate(confirmationMessage) {
|
|
28633
|
+
this._confirmationMessage = confirmationMessage;
|
|
28634
|
+
this._deactivate$.next();
|
|
28635
|
+
this.listenForUnsavedNavigationAttempts();
|
|
28636
|
+
}
|
|
28637
|
+
/**
|
|
28638
|
+
* Stops intercepting and clears all pending URL bypasses.
|
|
28639
|
+
*/
|
|
28640
|
+
deactivate() {
|
|
28641
|
+
this._deactivate$.next();
|
|
28642
|
+
this._allowedTargetUrls.clear();
|
|
28643
|
+
}
|
|
28644
|
+
/**
|
|
28645
|
+
* Whitelists the next navigation so it bypasses interception.
|
|
28646
|
+
* Without a URL, any next navigation is bypassed (wildcard). With a URL, only that
|
|
28647
|
+
* specific navigation is bypassed — non-matching navigations are still intercepted.
|
|
28648
|
+
*/
|
|
28649
|
+
allowNextNavigation(targetUrl) {
|
|
28650
|
+
this._allowedTargetUrls.add(targetUrl ?? '*');
|
|
28651
|
+
}
|
|
28652
|
+
/**
|
|
28653
|
+
* Executes the callback with interception temporarily disabled.
|
|
28654
|
+
* The callback must navigate synchronously — async navigation after the callback returns
|
|
28655
|
+
* will not be bypassed. This works because Angular's router emits NavigationStart
|
|
28656
|
+
* synchronously within the navigateByUrl() / navigate() call.
|
|
28657
|
+
*/
|
|
28658
|
+
executeWithBypass(fn) {
|
|
28659
|
+
this._bypassInterception = true;
|
|
28660
|
+
try {
|
|
28661
|
+
fn();
|
|
28662
|
+
}
|
|
28663
|
+
finally {
|
|
28664
|
+
this._bypassInterception = false;
|
|
28665
|
+
}
|
|
28666
|
+
}
|
|
28667
|
+
listenForUnsavedNavigationAttempts() {
|
|
28668
|
+
this.router.events
|
|
28669
|
+
.pipe(filter$1((event) => event instanceof NavigationStart), filter$1(() => !this._bypassInterception), filter$1(event => this.shouldIntercept(event)), concatMap$1(event => this.checkForPendingChanges(event)), filter$1(({ hasChanges }) => hasChanges), exhaustMap(({ event }) => this.cancelNavigationAndConfirm(event)), filter$1(({ confirmed }) => confirmed), takeUntil$1(this._deactivate$), takeUntil$1(this._destroy$))
|
|
28670
|
+
.subscribe(({ targetUrl }) => this.navigateToConfirmedTarget(targetUrl));
|
|
28671
|
+
}
|
|
28672
|
+
shouldIntercept(event) {
|
|
28673
|
+
if (this._allowedTargetUrls.has('*')) {
|
|
28674
|
+
this._allowedTargetUrls.clear();
|
|
28675
|
+
return false;
|
|
28676
|
+
}
|
|
28677
|
+
if (this._allowedTargetUrls.has(event.url)) {
|
|
28678
|
+
this._allowedTargetUrls.delete(event.url);
|
|
28679
|
+
return false;
|
|
28680
|
+
}
|
|
28681
|
+
return true;
|
|
28682
|
+
}
|
|
28683
|
+
checkForPendingChanges(event) {
|
|
28684
|
+
return this.formGroupManager.$hasValuesChanged().pipe(take$1(1), map$1(hasChanges => ({ event, hasChanges })));
|
|
28685
|
+
}
|
|
28686
|
+
cancelNavigationAndConfirm(event) {
|
|
28687
|
+
this._bypassInterception = true;
|
|
28688
|
+
void this.router.navigateByUrl(this.router.url, { skipLocationChange: true });
|
|
28689
|
+
return this.confirmationDialog
|
|
28690
|
+
.showCancelConfirmation({ cancel: { confirmationMessage: this._confirmationMessage } })
|
|
28691
|
+
.pipe(map$1(confirmed => ({ confirmed, targetUrl: event.url })), finalize(() => (this._bypassInterception = false)));
|
|
28692
|
+
}
|
|
28693
|
+
navigateToConfirmedTarget(targetUrl) {
|
|
28694
|
+
this._bypassInterception = false;
|
|
28695
|
+
this._allowedTargetUrls.add(targetUrl);
|
|
28696
|
+
void this.router.navigateByUrl(targetUrl);
|
|
28697
|
+
}
|
|
28698
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
28699
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService });
|
|
28700
|
+
}
|
|
28701
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageNavigationInterceptorService, decorators: [{
|
|
28702
|
+
type: Injectable
|
|
28703
|
+
}] });
|
|
28704
|
+
|
|
28539
28705
|
class QdPageSubmitActionService {
|
|
28540
28706
|
footerService = inject(QdPageFooterService);
|
|
28541
28707
|
formGroupManagerService = inject(QdFormGroupManagerService);
|
|
@@ -28997,6 +29163,7 @@ class QdPageComponent {
|
|
|
28997
29163
|
dialog = inject(QdDialogService);
|
|
28998
29164
|
bottomOffset$ = inject(QD_SAFE_BOTTOM_OFFSET, { optional: true });
|
|
28999
29165
|
dialogRef = inject(DialogRef, { optional: true });
|
|
29166
|
+
navigationInterceptor = inject(QdPageNavigationInterceptorService);
|
|
29000
29167
|
/**
|
|
29001
29168
|
* This property defines the configuration for the QdPage component, including the page type,
|
|
29002
29169
|
* title, and specific configurations for each type of page.
|
|
@@ -29064,8 +29231,10 @@ class QdPageComponent {
|
|
|
29064
29231
|
]);
|
|
29065
29232
|
}
|
|
29066
29233
|
ngAfterViewInit() {
|
|
29067
|
-
if (this.config.pageType === 'create')
|
|
29234
|
+
if (this.config.pageType === 'create') {
|
|
29068
29235
|
this.setupCreatePageFooterActions();
|
|
29236
|
+
this.navigationInterceptor.activate(this.config.pageTypeConfig?.cancel?.confirmationMessage);
|
|
29237
|
+
}
|
|
29069
29238
|
if (this.config.pageType === 'create' && this.config?.pageTypeConfig?.cancel !== undefined)
|
|
29070
29239
|
this.handleCancelActionWithFormChanges();
|
|
29071
29240
|
if (this.config.pageType === 'create' && this.config?.pageTypeConfig?.saveDraft !== undefined)
|
|
@@ -29115,8 +29284,12 @@ class QdPageComponent {
|
|
|
29115
29284
|
actionKey: 'cancel',
|
|
29116
29285
|
partialAction: {
|
|
29117
29286
|
handler: hasChanged
|
|
29118
|
-
? () => this.
|
|
29119
|
-
: () =>
|
|
29287
|
+
? () => this.setupCancelConfirmation()
|
|
29288
|
+
: () => {
|
|
29289
|
+
this.navigationInterceptor.executeWithBypass(() => {
|
|
29290
|
+
this.config?.pageTypeConfig?.cancel?.handler();
|
|
29291
|
+
});
|
|
29292
|
+
}
|
|
29120
29293
|
}
|
|
29121
29294
|
}
|
|
29122
29295
|
]);
|
|
@@ -29130,7 +29303,7 @@ class QdPageComponent {
|
|
|
29130
29303
|
action: {
|
|
29131
29304
|
titleI18n: pageTypeConfig.saveDraft?.label?.i18n ?? 'i18n.qd.page.footer.saveDraft',
|
|
29132
29305
|
type: QdFooterActionType.Secondary,
|
|
29133
|
-
handler: (
|
|
29306
|
+
handler: this.generateFooterActionHandler(pageTypeConfig?.saveDraft?.handler),
|
|
29134
29307
|
isVisible: true,
|
|
29135
29308
|
isDisabled: false
|
|
29136
29309
|
}
|
|
@@ -29138,6 +29311,12 @@ class QdPageComponent {
|
|
|
29138
29311
|
]);
|
|
29139
29312
|
}
|
|
29140
29313
|
updateInspectPageOperationMode(pageTypeConfig, mode) {
|
|
29314
|
+
if (mode === 'edit') {
|
|
29315
|
+
this.navigationInterceptor.activate(pageTypeConfig?.cancel?.confirmationMessage);
|
|
29316
|
+
}
|
|
29317
|
+
else {
|
|
29318
|
+
this.navigationInterceptor.deactivate();
|
|
29319
|
+
}
|
|
29141
29320
|
if (mode === 'view') {
|
|
29142
29321
|
this.formGroupManagerService.cancelPendingAsyncValidation();
|
|
29143
29322
|
setTimeout(() => this.formGroupManagerService.cancelPendingAsyncValidation());
|
|
@@ -29155,18 +29334,19 @@ class QdPageComponent {
|
|
|
29155
29334
|
return (...args) => {
|
|
29156
29335
|
if (!handler)
|
|
29157
29336
|
return;
|
|
29158
|
-
|
|
29337
|
+
const values = this.formGroupManagerService.hasFormGroups() ? this.formGroupManagerService.getAllValues() : args;
|
|
29338
|
+
this.navigationInterceptor.executeWithBypass(() => handler(values));
|
|
29159
29339
|
};
|
|
29160
29340
|
}
|
|
29161
|
-
|
|
29341
|
+
setupCancelConfirmation() {
|
|
29162
29342
|
this.dialog
|
|
29163
29343
|
.open(QdPageCancelConfirmationDialogComponent, {
|
|
29164
29344
|
title: { i18n: 'i18n.qd.page.cancel.confirmation.dialog.title' },
|
|
29165
29345
|
dialogSize: QdDialogSize.Small,
|
|
29166
29346
|
data: this.config.pageTypeConfig
|
|
29167
29347
|
})
|
|
29168
|
-
.closed.pipe(takeUntil(this._destroyed$))
|
|
29169
|
-
.subscribe();
|
|
29348
|
+
.closed.pipe(filter$1(result => !!result), takeUntil(this._destroyed$))
|
|
29349
|
+
.subscribe(() => this.navigationInterceptor.allowNextNavigation());
|
|
29170
29350
|
}
|
|
29171
29351
|
initSubmitValidation() {
|
|
29172
29352
|
this._cancelSubmitValidation$.next();
|
|
@@ -29203,11 +29383,23 @@ class QdPageComponent {
|
|
|
29203
29383
|
}))), this.dialogRef);
|
|
29204
29384
|
}
|
|
29205
29385
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
29206
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageComponent, isStandalone: false, selector: "qd-page", inputs: { config: "config", testId: ["data-test-id", "testId"] }, outputs: { operationModeChanged: "operationModeChanged" }, host: { properties: { "class.has-control-panel": "isControlPanelVisible", "class.control-panel-broad": "isControlPanelBroad", "class.has-footer": "this.footerVisible", "class.has-info-banners": "this.hasInfoBanners" } }, providers: [
|
|
29386
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdPageComponent, isStandalone: false, selector: "qd-page", inputs: { config: "config", testId: ["data-test-id", "testId"] }, outputs: { operationModeChanged: "operationModeChanged" }, host: { properties: { "class.has-control-panel": "isControlPanelVisible", "class.control-panel-broad": "isControlPanelBroad", "class.has-footer": "this.footerVisible", "class.has-info-banners": "this.hasInfoBanners" } }, providers: [
|
|
29387
|
+
QdPageFooterService,
|
|
29388
|
+
QdFormGroupManagerService,
|
|
29389
|
+
QdPageSubmitActionService,
|
|
29390
|
+
QdResolverTriggerService,
|
|
29391
|
+
QdPageNavigationInterceptorService
|
|
29392
|
+
], queries: [{ propertyName: "controlPanel", first: true, predicate: QdPageControlPanelComponent, descendants: true }, { propertyName: "stepperComponent", first: true, predicate: QdPageStepperComponent, descendants: true }, { propertyName: "tabsComponent", first: true, predicate: QdPageTabsComponent, descendants: true }, { propertyName: "stepperAdapterDirective", first: true, predicate: QdPageStepperAdapterDirective, descendants: true }, { propertyName: "tabsAdapterDirective", first: true, predicate: QdPageTabsAdapterDirective, descendants: true }, { propertyName: "sections", predicate: QdSectionComponent }, { propertyName: "infoBanners", predicate: QdPageInfoBannerComponent }], usesOnChanges: true, ngImport: i0, template: "<main qdSnackbarListener>\n <qd-page-object-header\n [data-test-id]=\"testId\"\n [attr.data-test-id]=\"testId + 'object-header'\"\n [config]=\"config\"\n [hasNavigation]=\"hasNavigation\"\n ></qd-page-object-header>\n\n <div class=\"page-info-banners\">\n <ng-content select=\"qd-page-info-banner\"></ng-content>\n </div>\n\n <ng-container *ngIf=\"config.pageType === 'create' || config.pageType === 'custom'\">\n <ng-content select=\"qd-page-stepper\"></ng-content>\n <ng-content select=\"[qdPageStepperAdapter]\"></ng-content>\n </ng-container>\n\n <ng-container *ngIf=\"config.pageType === 'overview' || config.pageType === 'inspect' || config.pageType === 'custom'\">\n <ng-content select=\"qd-page-tabs\"></ng-content>\n <ng-content select=\"[qdPageTabsAdapter]\"></ng-content>\n <ng-content select=\"qd-section\"></ng-content>\n <ng-content select=\"[qdSectionAdapter]\"></ng-content>\n </ng-container>\n\n <ng-container *ngIf=\"config.pageType === 'custom'\">\n <ng-container *ngTemplateOutlet=\"projectedContent\"></ng-container>\n </ng-container>\n</main>\n\n<footer *ngIf=\"footerHasContent$ | async\">\n <qd-page-footer [attr.data-test-id]=\"testId + '-footer'\">\n <ng-content select=\"[qdPageFooter]\"></ng-content>\n </qd-page-footer>\n</footer>\n\n<aside *ngIf=\"isControlPanelVisible\">\n <ng-content select=\"qd-page-control-panel\"></ng-content>\n</aside>\n\n<qd-projection-guard *ngIf=\"config.pageType !== 'custom'\" [warningMessage]=\"projectionGuardMessage\">\n <ng-container *ngTemplateOutlet=\"projectedContent\"></ng-container>\n</qd-projection-guard>\n\n<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n", styles: [":host{position:absolute;display:grid;overflow:hidden;width:100%;height:100%;background:#efefef;grid-template-areas:\"main\";grid-template-columns:1fr;grid-template-rows:1fr}:host.has-control-panel{grid-template-areas:\"main aside\";grid-template-columns:1fr 18.75rem}:host.control-panel-broad{grid-template-columns:1fr 27rem}:host.has-info-banners .page-info-banners{padding:1rem 1.25rem .5rem;border-bottom:rgb(213,213,213) solid .0625rem;background-color:#fff}@media (max-width: 599.98px){:host.has-info-banners .page-info-banners{padding-right:.9375rem;padding-left:.9375rem}}:host.has-info-banners qd-page-info-banner:last-child{margin-bottom:0}:host.has-footer{grid-template-areas:\"main\" \"footer\";grid-template-rows:calc(100% - 4rem) 4rem}:host.has-control-panel.has-footer{grid-template-areas:\"main aside\" \"footer aside\"}:host main{position:relative;grid-area:main;overflow-y:auto}:host aside{border-left:rgb(213,213,213) solid .0625rem;background:#fff;grid-area:aside}:host footer{grid-area:footer}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success{position:relative;top:-.5rem;padding-top:0rem;padding-bottom:0rem;border-top-width:0;margin-bottom:0rem}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info .icon,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning .icon,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical .icon,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success .icon{display:none}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info .title,:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info .message,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning .title,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning .message,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical .title,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical .message,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success .title,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success .message{position:relative;top:-.625rem}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info:before,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning:before,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical:before,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success:before{position:relative;top:-.625rem;left:-2.75rem;display:block;width:calc(100% + 4.75rem);height:.625rem;background-color:#fff;content:\"\"}\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: "component", type: QdProjectionGuardComponent, selector: "qd-projection-guard", inputs: ["isDisabled", "warningMessage"] }, { kind: "component", type: QdPageFooterComponent, selector: "qd-page-footer" }, { kind: "component", type: QdPageObjectHeaderComponent, selector: "qd-page-object-header", inputs: ["config", "hasNavigation", "data-test-id"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] });
|
|
29207
29393
|
}
|
|
29208
29394
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdPageComponent, decorators: [{
|
|
29209
29395
|
type: Component,
|
|
29210
|
-
args: [{ selector: 'qd-page', providers: [
|
|
29396
|
+
args: [{ selector: 'qd-page', providers: [
|
|
29397
|
+
QdPageFooterService,
|
|
29398
|
+
QdFormGroupManagerService,
|
|
29399
|
+
QdPageSubmitActionService,
|
|
29400
|
+
QdResolverTriggerService,
|
|
29401
|
+
QdPageNavigationInterceptorService
|
|
29402
|
+
], host: { '[class.has-control-panel]': 'isControlPanelVisible', '[class.control-panel-broad]': 'isControlPanelBroad' }, standalone: false, template: "<main qdSnackbarListener>\n <qd-page-object-header\n [data-test-id]=\"testId\"\n [attr.data-test-id]=\"testId + 'object-header'\"\n [config]=\"config\"\n [hasNavigation]=\"hasNavigation\"\n ></qd-page-object-header>\n\n <div class=\"page-info-banners\">\n <ng-content select=\"qd-page-info-banner\"></ng-content>\n </div>\n\n <ng-container *ngIf=\"config.pageType === 'create' || config.pageType === 'custom'\">\n <ng-content select=\"qd-page-stepper\"></ng-content>\n <ng-content select=\"[qdPageStepperAdapter]\"></ng-content>\n </ng-container>\n\n <ng-container *ngIf=\"config.pageType === 'overview' || config.pageType === 'inspect' || config.pageType === 'custom'\">\n <ng-content select=\"qd-page-tabs\"></ng-content>\n <ng-content select=\"[qdPageTabsAdapter]\"></ng-content>\n <ng-content select=\"qd-section\"></ng-content>\n <ng-content select=\"[qdSectionAdapter]\"></ng-content>\n </ng-container>\n\n <ng-container *ngIf=\"config.pageType === 'custom'\">\n <ng-container *ngTemplateOutlet=\"projectedContent\"></ng-container>\n </ng-container>\n</main>\n\n<footer *ngIf=\"footerHasContent$ | async\">\n <qd-page-footer [attr.data-test-id]=\"testId + '-footer'\">\n <ng-content select=\"[qdPageFooter]\"></ng-content>\n </qd-page-footer>\n</footer>\n\n<aside *ngIf=\"isControlPanelVisible\">\n <ng-content select=\"qd-page-control-panel\"></ng-content>\n</aside>\n\n<qd-projection-guard *ngIf=\"config.pageType !== 'custom'\" [warningMessage]=\"projectionGuardMessage\">\n <ng-container *ngTemplateOutlet=\"projectedContent\"></ng-container>\n</qd-projection-guard>\n\n<ng-template #projectedContent>\n <ng-content></ng-content>\n</ng-template>\n", styles: [":host{position:absolute;display:grid;overflow:hidden;width:100%;height:100%;background:#efefef;grid-template-areas:\"main\";grid-template-columns:1fr;grid-template-rows:1fr}:host.has-control-panel{grid-template-areas:\"main aside\";grid-template-columns:1fr 18.75rem}:host.control-panel-broad{grid-template-columns:1fr 27rem}:host.has-info-banners .page-info-banners{padding:1rem 1.25rem .5rem;border-bottom:rgb(213,213,213) solid .0625rem;background-color:#fff}@media (max-width: 599.98px){:host.has-info-banners .page-info-banners{padding-right:.9375rem;padding-left:.9375rem}}:host.has-info-banners qd-page-info-banner:last-child{margin-bottom:0}:host.has-footer{grid-template-areas:\"main\" \"footer\";grid-template-rows:calc(100% - 4rem) 4rem}:host.has-control-panel.has-footer{grid-template-areas:\"main aside\" \"footer aside\"}:host main{position:relative;grid-area:main;overflow-y:auto}:host aside{border-left:rgb(213,213,213) solid .0625rem;background:#fff;grid-area:aside}:host footer{grid-area:footer}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success{position:relative;top:-.5rem;padding-top:0rem;padding-bottom:0rem;border-top-width:0;margin-bottom:0rem}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info .icon,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning .icon,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical .icon,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success .icon{display:none}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info .title,:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info .message,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning .title,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning .message,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical .title,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical .message,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success .title,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success .message{position:relative;top:-.625rem}:host ::ng-deep .qd-page-info-banner-info+.qd-page-info-banner-info:before,:host ::ng-deep .qd-page-info-banner-warning+.qd-page-info-banner-warning:before,:host ::ng-deep .qd-page-info-banner-critical+.qd-page-info-banner-critical:before,:host ::ng-deep .qd-page-info-banner-success+.qd-page-info-banner-success:before{position:relative;top:-.625rem;left:-2.75rem;display:block;width:calc(100% + 4.75rem);height:.625rem;background-color:#fff;content:\"\"}\n"] }]
|
|
29211
29403
|
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
29212
29404
|
type: Input,
|
|
29213
29405
|
args: [{ required: true }]
|