@quadrel-enterprise-ui/framework 20.6.0 → 20.6.1-beta.127.1
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 +334 -152
- package/fesm2022/quadrel-enterprise-ui-framework.mjs.map +1 -1
- package/index.d.ts +168 -85
- package/package.json +1 -1
- package/src/assets/i18n/de.json +4 -4
- package/src/assets/i18n/en.json +4 -4
- package/src/assets/i18n/fr.json +4 -4
- package/src/assets/i18n/it.json +4 -4
- package/src/lib/filter/shared/filter.constants.scss +32 -0
|
@@ -3,8 +3,8 @@ 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, combineLatestWith, forkJoin, delayWhen, withLatestFrom, async, filter as filter$1 } from 'rxjs';
|
|
7
|
-
import { map, takeUntil, take, filter, catchError, debounceTime, startWith, distinctUntilChanged, concatMap, tap, skip,
|
|
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, filter as filter$1 } from 'rxjs';
|
|
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';
|
|
10
10
|
import { TranslateService, TranslateModule } from '@ngx-translate/core';
|
|
@@ -2162,15 +2162,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2162
2162
|
}]
|
|
2163
2163
|
}] });
|
|
2164
2164
|
|
|
2165
|
-
// @ts-strict-ignore
|
|
2166
2165
|
class QdMockFileCollectorItemComponent {
|
|
2167
2166
|
progress;
|
|
2168
|
-
newlyUploaded;
|
|
2167
|
+
newlyUploaded = false;
|
|
2169
2168
|
collectedFile;
|
|
2170
2169
|
error;
|
|
2171
|
-
readonly;
|
|
2172
|
-
viewonly;
|
|
2173
|
-
downloadFilesWithHttpClient;
|
|
2170
|
+
readonly = false;
|
|
2171
|
+
viewonly = false;
|
|
2172
|
+
downloadFilesWithHttpClient = false;
|
|
2174
2173
|
uploadTimestamp;
|
|
2175
2174
|
testId;
|
|
2176
2175
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -2204,11 +2203,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2204
2203
|
args: ['data-test-id']
|
|
2205
2204
|
}] } });
|
|
2206
2205
|
|
|
2207
|
-
// @ts-strict-ignore
|
|
2208
2206
|
class QdMockFileCollectorItemNameComponent {
|
|
2209
2207
|
name;
|
|
2208
|
+
testId;
|
|
2210
2209
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemNameComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2211
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorItemNameComponent, isStandalone: false, selector: "qd-file-collector-item-name", inputs: { name: "name" }, ngImport: i0, template: 'name: {{ name }}', isInline: true });
|
|
2210
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorItemNameComponent, isStandalone: false, selector: "qd-file-collector-item-name", inputs: { name: "name", testId: ["data-test-id", "testId"] }, ngImport: i0, template: 'name: {{ name }}', isInline: true });
|
|
2212
2211
|
}
|
|
2213
2212
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemNameComponent, decorators: [{
|
|
2214
2213
|
type: Component,
|
|
@@ -2219,13 +2218,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2219
2218
|
}]
|
|
2220
2219
|
}], propDecorators: { name: [{
|
|
2221
2220
|
type: Input
|
|
2221
|
+
}], testId: [{
|
|
2222
|
+
type: Input,
|
|
2223
|
+
args: ['data-test-id']
|
|
2222
2224
|
}] } });
|
|
2223
2225
|
|
|
2224
|
-
// @ts-strict-ignore
|
|
2225
2226
|
class QdMockFileCollectorItemSizeComponent {
|
|
2226
2227
|
size;
|
|
2228
|
+
testId;
|
|
2227
2229
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemSizeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2228
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorItemSizeComponent, isStandalone: false, selector: "qd-file-collector-item-size", inputs: { size: "size" }, ngImport: i0, template: 'size: {{ size }}', isInline: true });
|
|
2230
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorItemSizeComponent, isStandalone: false, selector: "qd-file-collector-item-size", inputs: { size: "size", testId: ["data-test-id", "testId"] }, ngImport: i0, template: 'size: {{ size }}', isInline: true });
|
|
2229
2231
|
}
|
|
2230
2232
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemSizeComponent, decorators: [{
|
|
2231
2233
|
type: Component,
|
|
@@ -2236,18 +2238,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2236
2238
|
}]
|
|
2237
2239
|
}], propDecorators: { size: [{
|
|
2238
2240
|
type: Input
|
|
2241
|
+
}], testId: [{
|
|
2242
|
+
type: Input,
|
|
2243
|
+
args: ['data-test-id']
|
|
2239
2244
|
}] } });
|
|
2240
2245
|
|
|
2241
|
-
// @ts-strict-ignore
|
|
2242
2246
|
class QdMockFileCollectorItemToolsComponent {
|
|
2243
2247
|
progress;
|
|
2244
2248
|
collectedFile;
|
|
2245
2249
|
error;
|
|
2246
|
-
readonly;
|
|
2247
|
-
viewonly;
|
|
2248
|
-
downloadFilesWithHttpClient;
|
|
2250
|
+
readonly = false;
|
|
2251
|
+
viewonly = false;
|
|
2252
|
+
downloadFilesWithHttpClient = false;
|
|
2253
|
+
testId;
|
|
2249
2254
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemToolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2250
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorItemToolsComponent, isStandalone: false, selector: "qd-file-collector-item-tools", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error", readonly: "readonly", viewonly: "viewonly", downloadFilesWithHttpClient: "downloadFilesWithHttpClient" }, ngImport: i0, template: 'progress: {{ progress }}, collectedFile: {{ collectedFile | json }}, error: {{ error | json }}, readonly: {{ readonly ? "true" : "false" }}, viewonly: {{ viewonly ? "true" : "false" }}, downloadFilesWithHttpClient: {{ downloadFilesWithHttpClient ? "true" : "false" }}', isInline: true, dependencies: [{ kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
2255
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorItemToolsComponent, isStandalone: false, selector: "qd-file-collector-item-tools", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error", readonly: "readonly", viewonly: "viewonly", downloadFilesWithHttpClient: "downloadFilesWithHttpClient", testId: ["data-test-id", "testId"] }, ngImport: i0, template: 'progress: {{ progress }}, collectedFile: {{ collectedFile | json }}, error: {{ error | json }}, readonly: {{ readonly ? "true" : "false" }}, viewonly: {{ viewonly ? "true" : "false" }}, downloadFilesWithHttpClient: {{ downloadFilesWithHttpClient ? "true" : "false" }}', isInline: true, dependencies: [{ kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
2251
2256
|
}
|
|
2252
2257
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorItemToolsComponent, decorators: [{
|
|
2253
2258
|
type: Component,
|
|
@@ -2268,15 +2273,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2268
2273
|
type: Input
|
|
2269
2274
|
}], downloadFilesWithHttpClient: [{
|
|
2270
2275
|
type: Input
|
|
2276
|
+
}], testId: [{
|
|
2277
|
+
type: Input,
|
|
2278
|
+
args: ['data-test-id']
|
|
2271
2279
|
}] } });
|
|
2272
2280
|
|
|
2273
|
-
// @ts-strict-ignore
|
|
2274
2281
|
class QdMockFileCollectorDialogItemComponent {
|
|
2275
2282
|
progress;
|
|
2276
2283
|
collectedFile;
|
|
2277
2284
|
error;
|
|
2285
|
+
testId;
|
|
2278
2286
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorDialogItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2279
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorDialogItemComponent, isStandalone: false, selector: "qd-file-collector-dialog-item", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error" }, ngImport: i0, template: 'progress: {{ progress }}, collectedFile: {{ collectedFile | json }}, error: {{ error | json }}', isInline: true, dependencies: [{ kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
2287
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorDialogItemComponent, isStandalone: false, selector: "qd-file-collector-dialog-item", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error", testId: ["data-test-id", "testId"] }, ngImport: i0, template: 'progress: {{ progress }}, collectedFile: {{ collectedFile | json }}, error: {{ error | json }}', isInline: true, dependencies: [{ kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
2280
2288
|
}
|
|
2281
2289
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorDialogItemComponent, decorators: [{
|
|
2282
2290
|
type: Component,
|
|
@@ -2291,13 +2299,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2291
2299
|
type: Input
|
|
2292
2300
|
}], error: [{
|
|
2293
2301
|
type: Input
|
|
2302
|
+
}], testId: [{
|
|
2303
|
+
type: Input,
|
|
2304
|
+
args: ['data-test-id']
|
|
2294
2305
|
}] } });
|
|
2295
2306
|
|
|
2296
|
-
// @ts-strict-ignore
|
|
2297
2307
|
class QdMockFileCollectorDialogItemErrorComponent {
|
|
2298
2308
|
error;
|
|
2309
|
+
testId;
|
|
2299
2310
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorDialogItemErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2300
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorDialogItemErrorComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-error", inputs: { error: "error" }, ngImport: i0, template: 'error: {{ error | json }}', isInline: true, dependencies: [{ kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
2311
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorDialogItemErrorComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-error", inputs: { error: "error", testId: ["data-test-id", "testId"] }, ngImport: i0, template: 'error: {{ error | json }}', isInline: true, dependencies: [{ kind: "pipe", type: i1.JsonPipe, name: "json" }] });
|
|
2301
2312
|
}
|
|
2302
2313
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorDialogItemErrorComponent, decorators: [{
|
|
2303
2314
|
type: Component,
|
|
@@ -2308,14 +2319,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2308
2319
|
}]
|
|
2309
2320
|
}], propDecorators: { error: [{
|
|
2310
2321
|
type: Input
|
|
2322
|
+
}], testId: [{
|
|
2323
|
+
type: Input,
|
|
2324
|
+
args: ['data-test-id']
|
|
2311
2325
|
}] } });
|
|
2312
2326
|
|
|
2313
|
-
// @ts-strict-ignore
|
|
2314
2327
|
class QdMockFileCollectorDialogItemProgressComponent {
|
|
2315
|
-
progress;
|
|
2328
|
+
progress = 0;
|
|
2316
2329
|
error;
|
|
2330
|
+
testId;
|
|
2317
2331
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorDialogItemProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2318
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorDialogItemProgressComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-progress", inputs: { progress: "progress", error: "error" }, ngImport: i0, template: 'progress: {{ progress }}', isInline: true });
|
|
2332
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdMockFileCollectorDialogItemProgressComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-progress", inputs: { progress: "progress", error: "error", testId: ["data-test-id", "testId"] }, ngImport: i0, template: 'progress: {{ progress }}', isInline: true });
|
|
2319
2333
|
}
|
|
2320
2334
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdMockFileCollectorDialogItemProgressComponent, decorators: [{
|
|
2321
2335
|
type: Component,
|
|
@@ -2328,6 +2342,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
2328
2342
|
type: Input
|
|
2329
2343
|
}], error: [{
|
|
2330
2344
|
type: Input
|
|
2345
|
+
}], testId: [{
|
|
2346
|
+
type: Input,
|
|
2347
|
+
args: ['data-test-id']
|
|
2331
2348
|
}] } });
|
|
2332
2349
|
|
|
2333
2350
|
class QdMockFileCollectorModule {
|
|
@@ -6029,16 +6046,20 @@ class QdDataFacetsCurrencyComponent {
|
|
|
6029
6046
|
return '';
|
|
6030
6047
|
// Swiss speciality with a period instead of a comma
|
|
6031
6048
|
const localeWithSuffix = ['de', 'fr', 'it'].includes(lang) ? `${lang}-CH` : lang;
|
|
6049
|
+
// Normalize U+0027 (apostrophe) to U+2019 (right single quotation mark), which is the
|
|
6050
|
+
// correct Swiss thousands separator. Older ICU versions (used in some CI environments)
|
|
6051
|
+
// incorrectly emit U+0027 instead.
|
|
6052
|
+
const normalize = (s) => s.replace(/\u0027/g, '\u2019');
|
|
6032
6053
|
if (this.config?.showCurrencyUnit) {
|
|
6033
|
-
return new Intl.NumberFormat(localeWithSuffix, {
|
|
6054
|
+
return normalize(new Intl.NumberFormat(localeWithSuffix, {
|
|
6034
6055
|
style: 'currency',
|
|
6035
6056
|
currency: this.config?.currency ?? 'chf'
|
|
6036
|
-
}).format(this.data);
|
|
6057
|
+
}).format(this.data));
|
|
6037
6058
|
}
|
|
6038
|
-
return new Intl.NumberFormat(localeWithSuffix, {
|
|
6059
|
+
return normalize(new Intl.NumberFormat(localeWithSuffix, {
|
|
6039
6060
|
minimumFractionDigits: 2,
|
|
6040
6061
|
maximumFractionDigits: 2
|
|
6041
|
-
}).format(this.data);
|
|
6062
|
+
}).format(this.data));
|
|
6042
6063
|
}
|
|
6043
6064
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdDataFacetsCurrencyComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6044
6065
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdDataFacetsCurrencyComponent, isStandalone: false, selector: "qd-data-facets-currency", inputs: { config: "config", data: "data", testId: "testId" }, host: { properties: { "attr.data-test-id": "testId" }, classAttribute: "qd-data-facets" }, usesOnChanges: true, ngImport: i0, template: "{{ currency$ | async }}\n", styles: [":host{text-align:right}\n"], dependencies: [{ kind: "pipe", type: i1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -17345,7 +17366,13 @@ class QdPageStoreService {
|
|
|
17345
17366
|
}
|
|
17346
17367
|
initPageState(config) {
|
|
17347
17368
|
this.config = config;
|
|
17348
|
-
this.config?.pageType === 'inspect'
|
|
17369
|
+
if (this.config?.pageType === 'inspect') {
|
|
17370
|
+
const operationMode = this.config.pageTypeConfig?.operationMode;
|
|
17371
|
+
this.toggleViewonly(operationMode !== 'edit');
|
|
17372
|
+
}
|
|
17373
|
+
else {
|
|
17374
|
+
this.toggleViewonly(false);
|
|
17375
|
+
}
|
|
17349
17376
|
}
|
|
17350
17377
|
getConfig() {
|
|
17351
17378
|
return this.config;
|
|
@@ -18305,7 +18332,6 @@ var QdUploadErrorType;
|
|
|
18305
18332
|
QdUploadErrorType["UNKNOWN_ERROR"] = "UNKNOWN_ERROR";
|
|
18306
18333
|
})(QdUploadErrorType || (QdUploadErrorType = {}));
|
|
18307
18334
|
|
|
18308
|
-
// @ts-strict-ignore
|
|
18309
18335
|
class QdFileCollectorValidationService {
|
|
18310
18336
|
_config;
|
|
18311
18337
|
get allowedMimeTypes() {
|
|
@@ -18342,7 +18368,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18342
18368
|
type: Injectable
|
|
18343
18369
|
}] });
|
|
18344
18370
|
|
|
18345
|
-
// @ts-strict-ignore
|
|
18346
18371
|
class QdFileCollectorService {
|
|
18347
18372
|
fileManager = inject(QD_FILE_MANAGER_TOKEN);
|
|
18348
18373
|
fileCollectorValidationService = inject(QdFileCollectorValidationService);
|
|
@@ -18386,8 +18411,8 @@ class QdFileCollectorService {
|
|
|
18386
18411
|
}
|
|
18387
18412
|
if (uploadProgress?.error) {
|
|
18388
18413
|
fileUpload.error = {
|
|
18389
|
-
|
|
18390
|
-
|
|
18414
|
+
...uploadProgress.error,
|
|
18415
|
+
type: uploadProgress.error.type ?? QdUploadErrorType.UNKNOWN_SERVER_ERROR
|
|
18391
18416
|
};
|
|
18392
18417
|
}
|
|
18393
18418
|
this.changeDetectorRef.detectChanges();
|
|
@@ -18403,7 +18428,10 @@ class QdFileCollectorService {
|
|
|
18403
18428
|
this.fileManager.delete(collectedFile).subscribe(deleted => {
|
|
18404
18429
|
if (!deleted)
|
|
18405
18430
|
return;
|
|
18406
|
-
this.fileUploads.
|
|
18431
|
+
const index = this.fileUploads.findIndex(fileUpload => fileUpload.collectedFile === collectedFile);
|
|
18432
|
+
if (index === -1)
|
|
18433
|
+
return;
|
|
18434
|
+
this.fileUploads.splice(index, 1);
|
|
18407
18435
|
this.changeDetectorRef.detectChanges();
|
|
18408
18436
|
});
|
|
18409
18437
|
}
|
|
@@ -18452,7 +18480,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18452
18480
|
}]
|
|
18453
18481
|
}] });
|
|
18454
18482
|
|
|
18455
|
-
// @ts-strict-ignore
|
|
18456
18483
|
class QdFileCollectorAllowedFilesDescriptionComponent {
|
|
18457
18484
|
fileCollectorService = inject(QdFileCollectorService);
|
|
18458
18485
|
get allowedFileTypes() {
|
|
@@ -18487,10 +18514,13 @@ var QdUploadProgressState;
|
|
|
18487
18514
|
QdUploadProgressState["ERROR"] = "error";
|
|
18488
18515
|
})(QdUploadProgressState || (QdUploadProgressState = {}));
|
|
18489
18516
|
|
|
18490
|
-
// @ts-strict-ignore
|
|
18491
18517
|
class QdFileCollectorDialogItemProgressComponent {
|
|
18492
18518
|
progress = 0;
|
|
18493
18519
|
error;
|
|
18520
|
+
testId;
|
|
18521
|
+
get hostTestId() {
|
|
18522
|
+
return this.testId;
|
|
18523
|
+
}
|
|
18494
18524
|
_uploadStateSubject = new BehaviorSubject(QdUploadProgressState.STARTING);
|
|
18495
18525
|
_destroyed$ = new Subject();
|
|
18496
18526
|
uploadState$ = this._uploadStateSubject.asObservable();
|
|
@@ -18533,7 +18563,7 @@ class QdFileCollectorDialogItemProgressComponent {
|
|
|
18533
18563
|
}
|
|
18534
18564
|
QdUploadState = QdUploadProgressState;
|
|
18535
18565
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogItemProgressComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18536
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogItemProgressComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-progress", inputs: { progress: "progress", error: "error" }, host: { classAttribute: "qd-file-collector-dialog-item-progress" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"uploadState$ | async as uploadState\">\n <span\n [class]=\"'upload-progress-bar-container'\"\n *ngIf=\"\n [QdUploadState.STARTING, QdUploadState.IN_PROGRESS, QdUploadState.FINISHING].includes(uploadState);\n else completed\n \"\n >\n <span\n [ngClass]=\"{\n 'upload-progress-bar-progress': true,\n filled: [QdUploadState.IN_PROGRESS, QdUploadState.FINISHING].includes(uploadState),\n success: QdUploadState.FINISHING === uploadState\n }\"\n [class]=\"'upload-progress-bar-progress'\"\n [ngStyle]=\"{ minWidth: progress + '%' }\"\n >\n {{ progress ? progress : 0 }}%\n </span>\n </span>\n <ng-template #completed>\n <span [class]=\"'upload-state-chip ' + uploadState\">\n {{ \"i18n.qd.fileCollector.uploadState.\" + uploadState | translate }}\n </span>\n </ng-template>\n</ng-container>\n", styles: [":host{position:relative;display:flex;margin-top:.0625rem}:host .upload-progress-bar-container{width:12.5rem}:host .upload-progress-bar-progress,:host .upload-state-chip{color:#e97e00;font-size:.625rem;font-weight:500;line-height:1rem;display:inline-block;padding-right:.375rem;padding-left:.5rem;border:solid .0625rem rgb(233,126,0);border-radius:.5rem;background:#fff;transition:min-width 1s}:host .upload-progress-bar-progress.filled,:host .upload-state-chip.filled{border-color:#e97e00;background:#e97e00;color:#fff}:host .upload-progress-bar-progress.success,:host .upload-state-chip.success{border-color:#00813a;background:#fff;color:#00813a}:host .upload-progress-bar-progress.success.filled,:host .upload-state-chip.success.filled{border-color:#00813a;background:#00813a;color:#fff}:host .upload-progress-bar-progress.error,:host .upload-state-chip.error{border-color:#c70023;background:#fff;color:#c70023}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18566
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogItemProgressComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-progress", inputs: { progress: "progress", error: "error", testId: ["data-test-id", "testId"] }, host: { properties: { "attr.data-test-id": "this.hostTestId" }, classAttribute: "qd-file-collector-dialog-item-progress" }, usesOnChanges: true, ngImport: i0, template: "<ng-container *ngIf=\"uploadState$ | async as uploadState\">\n <span\n [class]=\"'upload-progress-bar-container'\"\n *ngIf=\"\n [QdUploadState.STARTING, QdUploadState.IN_PROGRESS, QdUploadState.FINISHING].includes(uploadState);\n else completed\n \"\n >\n <span\n [ngClass]=\"{\n 'upload-progress-bar-progress': true,\n filled: [QdUploadState.IN_PROGRESS, QdUploadState.FINISHING].includes(uploadState),\n success: QdUploadState.FINISHING === uploadState\n }\"\n [class]=\"'upload-progress-bar-progress'\"\n [ngStyle]=\"{ minWidth: progress + '%' }\"\n >\n {{ progress ? progress : 0 }}%\n </span>\n </span>\n <ng-template #completed>\n <span [class]=\"'upload-state-chip ' + uploadState\">\n {{ \"i18n.qd.fileCollector.uploadState.\" + uploadState | translate }}\n </span>\n </ng-template>\n</ng-container>\n", styles: [":host{position:relative;display:flex;margin-top:.0625rem}:host .upload-progress-bar-container{width:12.5rem}:host .upload-progress-bar-progress,:host .upload-state-chip{color:#e97e00;font-size:.625rem;font-weight:500;line-height:1rem;display:inline-block;padding-right:.375rem;padding-left:.5rem;border:solid .0625rem rgb(233,126,0);border-radius:.5rem;background:#fff;transition:min-width 1s}:host .upload-progress-bar-progress.filled,:host .upload-state-chip.filled{border-color:#e97e00;background:#e97e00;color:#fff}:host .upload-progress-bar-progress.success,:host .upload-state-chip.success{border-color:#00813a;background:#fff;color:#00813a}:host .upload-progress-bar-progress.success.filled,:host .upload-state-chip.success.filled{border-color:#00813a;background:#00813a;color:#fff}:host .upload-progress-bar-progress.error,:host .upload-state-chip.error{border-color:#c70023;background:#fff;color:#c70023}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18537
18567
|
}
|
|
18538
18568
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogItemProgressComponent, decorators: [{
|
|
18539
18569
|
type: Component,
|
|
@@ -18542,12 +18572,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18542
18572
|
type: Input
|
|
18543
18573
|
}], error: [{
|
|
18544
18574
|
type: Input
|
|
18575
|
+
}], testId: [{
|
|
18576
|
+
type: Input,
|
|
18577
|
+
args: [{ required: true, alias: 'data-test-id' }]
|
|
18578
|
+
}], hostTestId: [{
|
|
18579
|
+
type: HostBinding,
|
|
18580
|
+
args: ['attr.data-test-id']
|
|
18545
18581
|
}] } });
|
|
18546
18582
|
|
|
18547
|
-
// @ts-strict-ignore
|
|
18548
18583
|
class QdFileCollectorDialogItemErrorComponent {
|
|
18549
18584
|
fileCollectorService = inject(QdFileCollectorService);
|
|
18550
18585
|
error;
|
|
18586
|
+
testId;
|
|
18587
|
+
get hostTestId() {
|
|
18588
|
+
return this.testId;
|
|
18589
|
+
}
|
|
18551
18590
|
QdUploadErrorType = QdUploadErrorType;
|
|
18552
18591
|
get maxFileSizeInBytes() {
|
|
18553
18592
|
return this.config?.maxFileSizeInBytes;
|
|
@@ -18562,41 +18601,53 @@ class QdFileCollectorDialogItemErrorComponent {
|
|
|
18562
18601
|
return this.fileCollectorService.config;
|
|
18563
18602
|
}
|
|
18564
18603
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogItemErrorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18565
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogItemErrorComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-error", inputs: { error: "error" }, ngImport: i0, template: "<span *ngIf=\"error.message; else errorMessageNotGiven\">{{ error.message }}</span>\n<ng-template #errorMessageNotGiven [ngSwitch]=\"error.type\">\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_MIME_TYPE\">{{\n invalidMimeTypeErrorMessageI18n || \"i18n.qd.fileCollector.invalid.fileType\" | translate\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_FILE_SIZE\">{{\n \"i18n.qd.fileCollector.invalid.fileSize\"\n | translate\n | placeholder : \"maxFileSize\" : (maxFileSizeInBytes | filesize | async)\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_FILE_NAME\">{{\n invalidFileNameErrorMessageI18n || \"i18n.qd.fileCollector.invalid.fileName\" | translate\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.UNKNOWN_ERROR\">{{ \"i18n.qd.fileCollector.invalid.unknown\" | translate }}</span>\n</ng-template>\n", styles: [":host{display:flex;width:100%;align-items:center}:host span{color:#c70023}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: QdPlaceholderPipe, name: "placeholder" }, { kind: "pipe", type: QdFileSizePipe, name: "filesize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18604
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogItemErrorComponent, isStandalone: false, selector: "qd-file-collector-dialog-item-error", inputs: { error: "error", testId: ["data-test-id", "testId"] }, host: { properties: { "attr.data-test-id": "this.hostTestId" } }, ngImport: i0, template: "<span *ngIf=\"error.message; else errorMessageNotGiven\">{{ error.message }}</span>\n<ng-template #errorMessageNotGiven [ngSwitch]=\"error.type\">\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_MIME_TYPE\">{{\n invalidMimeTypeErrorMessageI18n || \"i18n.qd.fileCollector.invalid.fileType\" | translate\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_FILE_SIZE\">{{\n \"i18n.qd.fileCollector.invalid.fileSize\"\n | translate\n | placeholder : \"maxFileSize\" : (maxFileSizeInBytes | filesize | async)\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_FILE_NAME\">{{\n invalidFileNameErrorMessageI18n || \"i18n.qd.fileCollector.invalid.fileName\" | translate\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.UNKNOWN_ERROR\">{{ \"i18n.qd.fileCollector.invalid.unknown\" | translate }}</span>\n</ng-template>\n", styles: [":host{display:flex;width:100%;align-items:center}:host span{color:#c70023}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "pipe", type: QdPlaceholderPipe, name: "placeholder" }, { kind: "pipe", type: QdFileSizePipe, name: "filesize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18566
18605
|
}
|
|
18567
18606
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogItemErrorComponent, decorators: [{
|
|
18568
18607
|
type: Component,
|
|
18569
18608
|
args: [{ selector: 'qd-file-collector-dialog-item-error', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<span *ngIf=\"error.message; else errorMessageNotGiven\">{{ error.message }}</span>\n<ng-template #errorMessageNotGiven [ngSwitch]=\"error.type\">\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_MIME_TYPE\">{{\n invalidMimeTypeErrorMessageI18n || \"i18n.qd.fileCollector.invalid.fileType\" | translate\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_FILE_SIZE\">{{\n \"i18n.qd.fileCollector.invalid.fileSize\"\n | translate\n | placeholder : \"maxFileSize\" : (maxFileSizeInBytes | filesize | async)\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.INVALID_FILE_NAME\">{{\n invalidFileNameErrorMessageI18n || \"i18n.qd.fileCollector.invalid.fileName\" | translate\n }}</span>\n <span *ngSwitchCase=\"QdUploadErrorType.UNKNOWN_ERROR\">{{ \"i18n.qd.fileCollector.invalid.unknown\" | translate }}</span>\n</ng-template>\n", styles: [":host{display:flex;width:100%;align-items:center}:host span{color:#c70023}\n"] }]
|
|
18570
18609
|
}], propDecorators: { error: [{
|
|
18571
18610
|
type: Input
|
|
18611
|
+
}], testId: [{
|
|
18612
|
+
type: Input,
|
|
18613
|
+
args: [{ required: true, alias: 'data-test-id' }]
|
|
18614
|
+
}], hostTestId: [{
|
|
18615
|
+
type: HostBinding,
|
|
18616
|
+
args: ['attr.data-test-id']
|
|
18572
18617
|
}] } });
|
|
18573
18618
|
|
|
18574
|
-
// @ts-strict-ignore
|
|
18575
18619
|
class QdFileCollectorDialogItemComponent {
|
|
18576
18620
|
progress;
|
|
18577
18621
|
collectedFile;
|
|
18578
18622
|
error;
|
|
18623
|
+
testId;
|
|
18624
|
+
get hostTestId() {
|
|
18625
|
+
return this.testId;
|
|
18626
|
+
}
|
|
18579
18627
|
get isSuccessful() {
|
|
18580
18628
|
return !this.error && this.progress === 100;
|
|
18581
18629
|
}
|
|
18582
18630
|
get hasError() {
|
|
18583
18631
|
return !!this.error;
|
|
18584
18632
|
}
|
|
18585
|
-
canUpload() {
|
|
18586
|
-
return false; // TODO discuss whether we want this feature; return !!this.error;
|
|
18587
|
-
}
|
|
18588
18633
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18589
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogItemComponent, isStandalone: false, selector: "qd-file-collector-dialog-item", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error" }, host: { properties: { "class.success": "this.isSuccessful", "class.error": "this.hasError" } }, ngImport: i0, template: "<span class=\"name\">{{ this.collectedFile.name }}</span>\n<qd-file-collector-dialog-item-progress\n [progress]=\"this.progress\"\n [error]=\"this.error\"\n></qd-file-collector-dialog-item-progress>\n<span class=\"filesize\">{{ this.collectedFile.size | filesize | async }}</span>\n<qd-
|
|
18634
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogItemComponent, isStandalone: false, selector: "qd-file-collector-dialog-item", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error", testId: ["data-test-id", "testId"] }, host: { properties: { "attr.data-test-id": "this.hostTestId", "class.success": "this.isSuccessful", "class.error": "this.hasError" } }, ngImport: i0, template: "<span class=\"name\" [attr.data-test-id]=\"testId + '-name'\">{{ this.collectedFile.name }}</span>\n<qd-file-collector-dialog-item-progress\n [progress]=\"this.progress\"\n [error]=\"this.error\"\n [data-test-id]=\"testId + '-progress'\"\n></qd-file-collector-dialog-item-progress>\n<span class=\"filesize\" [attr.data-test-id]=\"testId + '-size'\">{{ this.collectedFile.size | filesize | async }}</span>\n<qd-file-collector-dialog-item-error\n [error]=\"this.error\"\n *ngIf=\"!!this.error\"\n [data-test-id]=\"testId + '-error'\"\n></qd-file-collector-dialog-item-error>\n", styles: [":host{color:#333;font-size:.875rem;font-weight:400;line-height:1.3125rem;position:relative;display:grid;align-items:self-start;padding:.625rem 1rem .625rem 2.875rem;border-left:transparent .1875rem solid;margin-bottom:.75rem;background:#fff;gap:.25rem 1rem;grid-template-columns:30rem auto max-content;outline:rgb(151,151,151) .0625rem solid}:host qd-file-collector-dialog-item-error{grid-column:span 2}:host .filesize{text-align:right}@media (max-width: 959.98px){:host{grid-template-columns:18.75rem auto max-content}:host .name{overflow:auto;overflow-wrap:break-word}}@media (max-width: 599.98px){:host{grid-template-columns:auto auto auto}:host .name,:host qd-file-collector-dialog-item-progress{grid-column:span 2}:host qd-file-collector-dialog-item-progress,:host .filesize{order:-1}}:host:last-child{margin-bottom:0}:host.error{border-left-color:#c70023}:host.success{border-left-color:#00813a}:host:before{position:absolute;top:.5625rem;left:.875rem;content:\"\\e964\";font-family:Quadrel-Icon,sans-serif;font-size:1.25rem}:host .upload{color:#454545;cursor:pointer;font-size:1rem}:host .upload:hover,:host .upload:focus{color:#171717}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdFileCollectorDialogItemProgressComponent, selector: "qd-file-collector-dialog-item-progress", inputs: ["progress", "error", "data-test-id"] }, { kind: "component", type: QdFileCollectorDialogItemErrorComponent, selector: "qd-file-collector-dialog-item-error", inputs: ["error", "data-test-id"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: QdFileSizePipe, name: "filesize" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18590
18635
|
}
|
|
18591
18636
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogItemComponent, decorators: [{
|
|
18592
18637
|
type: Component,
|
|
18593
|
-
args: [{ selector: 'qd-file-collector-dialog-item', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<span class=\"name\">{{ this.collectedFile.name }}</span>\n<qd-file-collector-dialog-item-progress\n [progress]=\"this.progress\"\n [error]=\"this.error\"\n></qd-file-collector-dialog-item-progress>\n<span class=\"filesize\">{{ this.collectedFile.size | filesize | async }}</span>\n<qd-
|
|
18638
|
+
args: [{ selector: 'qd-file-collector-dialog-item', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<span class=\"name\" [attr.data-test-id]=\"testId + '-name'\">{{ this.collectedFile.name }}</span>\n<qd-file-collector-dialog-item-progress\n [progress]=\"this.progress\"\n [error]=\"this.error\"\n [data-test-id]=\"testId + '-progress'\"\n></qd-file-collector-dialog-item-progress>\n<span class=\"filesize\" [attr.data-test-id]=\"testId + '-size'\">{{ this.collectedFile.size | filesize | async }}</span>\n<qd-file-collector-dialog-item-error\n [error]=\"this.error\"\n *ngIf=\"!!this.error\"\n [data-test-id]=\"testId + '-error'\"\n></qd-file-collector-dialog-item-error>\n", styles: [":host{color:#333;font-size:.875rem;font-weight:400;line-height:1.3125rem;position:relative;display:grid;align-items:self-start;padding:.625rem 1rem .625rem 2.875rem;border-left:transparent .1875rem solid;margin-bottom:.75rem;background:#fff;gap:.25rem 1rem;grid-template-columns:30rem auto max-content;outline:rgb(151,151,151) .0625rem solid}:host qd-file-collector-dialog-item-error{grid-column:span 2}:host .filesize{text-align:right}@media (max-width: 959.98px){:host{grid-template-columns:18.75rem auto max-content}:host .name{overflow:auto;overflow-wrap:break-word}}@media (max-width: 599.98px){:host{grid-template-columns:auto auto auto}:host .name,:host qd-file-collector-dialog-item-progress{grid-column:span 2}:host qd-file-collector-dialog-item-progress,:host .filesize{order:-1}}:host:last-child{margin-bottom:0}:host.error{border-left-color:#c70023}:host.success{border-left-color:#00813a}:host:before{position:absolute;top:.5625rem;left:.875rem;content:\"\\e964\";font-family:Quadrel-Icon,sans-serif;font-size:1.25rem}:host .upload{color:#454545;cursor:pointer;font-size:1rem}:host .upload:hover,:host .upload:focus{color:#171717}\n"] }]
|
|
18594
18639
|
}], propDecorators: { progress: [{
|
|
18595
18640
|
type: Input
|
|
18596
18641
|
}], collectedFile: [{
|
|
18597
18642
|
type: Input
|
|
18598
18643
|
}], error: [{
|
|
18599
18644
|
type: Input
|
|
18645
|
+
}], testId: [{
|
|
18646
|
+
type: Input,
|
|
18647
|
+
args: [{ required: true, alias: 'data-test-id' }]
|
|
18648
|
+
}], hostTestId: [{
|
|
18649
|
+
type: HostBinding,
|
|
18650
|
+
args: ['attr.data-test-id']
|
|
18600
18651
|
}], isSuccessful: [{
|
|
18601
18652
|
type: HostBinding,
|
|
18602
18653
|
args: ['class.success']
|
|
@@ -18622,17 +18673,17 @@ class QdFileCollectorDialogComponent {
|
|
|
18622
18673
|
this.dialogRef.close(this.fileUploads);
|
|
18623
18674
|
}
|
|
18624
18675
|
isCloseButtonDisabled() {
|
|
18625
|
-
return !this.fileUploads.every(this.
|
|
18676
|
+
return !this.fileUploads.every(this.isFileUploadCompleted);
|
|
18626
18677
|
}
|
|
18627
|
-
|
|
18678
|
+
isFileUploadCompleted(fileUpload) {
|
|
18628
18679
|
return !!fileUpload.error || fileUpload.progress === 100;
|
|
18629
18680
|
}
|
|
18630
18681
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18631
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogComponent, isStandalone: false, selector: "qd-file-collector-dialog", providers: [QdFileCollectorService], ngImport: i0, template: "<qd-dialog>\n <qd-file-collector-dialog-item\n *ngFor=\"let fileUpload of this.fileUploads\"\n [progress]=\"fileUpload.progress\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n ></qd-file-collector-dialog-item>\n <qd-dialog-action>\n <button
|
|
18682
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorDialogComponent, isStandalone: false, selector: "qd-file-collector-dialog", providers: [QdFileCollectorService], ngImport: i0, template: "<qd-dialog>\n <qd-file-collector-dialog-item\n *ngFor=\"let fileUpload of this.fileUploads; let i = index\"\n [progress]=\"fileUpload.progress\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [data-test-id]=\"'file-collector-dialog-item-' + i\"\n ></qd-file-collector-dialog-item>\n <qd-dialog-action>\n <button\n qdButton\n (click)=\"close()\"\n [disabled]=\"isCloseButtonDisabled()\"\n data-test-id=\"file-collector-dialog-button-finish\"\n >\n {{ \"i18n.qd.fileCollector.button.finish\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "component", type: QdFileCollectorDialogItemComponent, selector: "qd-file-collector-dialog-item", inputs: ["progress", "collectedFile", "error", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
18632
18683
|
}
|
|
18633
18684
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorDialogComponent, decorators: [{
|
|
18634
18685
|
type: Component,
|
|
18635
|
-
args: [{ selector: 'qd-file-collector-dialog', providers: [QdFileCollectorService], standalone: false, template: "<qd-dialog>\n <qd-file-collector-dialog-item\n *ngFor=\"let fileUpload of this.fileUploads\"\n [progress]=\"fileUpload.progress\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n ></qd-file-collector-dialog-item>\n <qd-dialog-action>\n <button
|
|
18686
|
+
args: [{ selector: 'qd-file-collector-dialog', providers: [QdFileCollectorService], standalone: false, template: "<qd-dialog>\n <qd-file-collector-dialog-item\n *ngFor=\"let fileUpload of this.fileUploads; let i = index\"\n [progress]=\"fileUpload.progress\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [data-test-id]=\"'file-collector-dialog-item-' + i\"\n ></qd-file-collector-dialog-item>\n <qd-dialog-action>\n <button\n qdButton\n (click)=\"close()\"\n [disabled]=\"isCloseButtonDisabled()\"\n data-test-id=\"file-collector-dialog-button-finish\"\n >\n {{ \"i18n.qd.fileCollector.button.finish\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n" }]
|
|
18636
18687
|
}], ctorParameters: () => [] });
|
|
18637
18688
|
|
|
18638
18689
|
class QdSectionToolbarActionService {
|
|
@@ -18768,7 +18819,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18768
18819
|
}]
|
|
18769
18820
|
}] });
|
|
18770
18821
|
|
|
18771
|
-
// @ts-strict-ignore
|
|
18772
18822
|
class QdFileCollectorItemNameComponent {
|
|
18773
18823
|
name;
|
|
18774
18824
|
testId;
|
|
@@ -18791,7 +18841,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18791
18841
|
args: ['attr.data-test-id']
|
|
18792
18842
|
}] } });
|
|
18793
18843
|
|
|
18794
|
-
// @ts-strict-ignore
|
|
18795
18844
|
class QdFileCollectorItemSizeComponent {
|
|
18796
18845
|
size;
|
|
18797
18846
|
testId;
|
|
@@ -18828,14 +18877,13 @@ class QdFileDeleteDialogComponent {
|
|
|
18828
18877
|
this.dialogRef.close(true);
|
|
18829
18878
|
}
|
|
18830
18879
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileDeleteDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18831
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileDeleteDialogComponent, isStandalone: false, selector: "qd-file-delete-dialog", ngImport: i0, template: "<qd-dialog>\n {{ deleteHint }}\n\n <qd-dialog-action>\n <button (click)=\"cancel()\" qdButton qdButtonGhost color=\"secondary\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.cancel\" | translate }}\n </button>\n\n <button (click)=\"delete()\" qdButton color=\"error\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.delete\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host{overflow-wrap:break-word}\n"], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
18880
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileDeleteDialogComponent, isStandalone: false, selector: "qd-file-delete-dialog", ngImport: i0, template: "<qd-dialog>\n {{ deleteHint }}\n\n <qd-dialog-action>\n <button (click)=\"cancel()\" qdButton qdButtonGhost color=\"secondary\" data-test-id=\"file-delete-dialog-button-cancel\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.cancel\" | translate }}\n </button>\n\n <button (click)=\"delete()\" qdButton color=\"error\" data-test-id=\"file-delete-dialog-button-delete\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.delete\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host{overflow-wrap:break-word}\n"], dependencies: [{ kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdDialogActionComponent, selector: "qd-dialog-action" }, { kind: "component", type: QdDialogComponent, selector: "qd-dialog" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
18832
18881
|
}
|
|
18833
18882
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileDeleteDialogComponent, decorators: [{
|
|
18834
18883
|
type: Component,
|
|
18835
|
-
args: [{ selector: 'qd-file-delete-dialog', standalone: false, template: "<qd-dialog>\n {{ deleteHint }}\n\n <qd-dialog-action>\n <button (click)=\"cancel()\" qdButton qdButtonGhost color=\"secondary\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.cancel\" | translate }}\n </button>\n\n <button (click)=\"delete()\" qdButton color=\"error\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.delete\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host{overflow-wrap:break-word}\n"] }]
|
|
18884
|
+
args: [{ selector: 'qd-file-delete-dialog', standalone: false, template: "<qd-dialog>\n {{ deleteHint }}\n\n <qd-dialog-action>\n <button (click)=\"cancel()\" qdButton qdButtonGhost color=\"secondary\" data-test-id=\"file-delete-dialog-button-cancel\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.cancel\" | translate }}\n </button>\n\n <button (click)=\"delete()\" qdButton color=\"error\" data-test-id=\"file-delete-dialog-button-delete\">\n {{ \"i18n.qd.fileCollector.deleteConfirmation.button.delete\" | translate }}\n </button>\n </qd-dialog-action>\n</qd-dialog>\n", styles: [":host{overflow-wrap:break-word}\n"] }]
|
|
18836
18885
|
}] });
|
|
18837
18886
|
|
|
18838
|
-
// @ts-strict-ignore
|
|
18839
18887
|
class QdFileCollectorItemToolsComponent {
|
|
18840
18888
|
fileCollectorService = inject(QdFileCollectorService);
|
|
18841
18889
|
dialogService = inject(QdDialogService);
|
|
@@ -18843,16 +18891,13 @@ class QdFileCollectorItemToolsComponent {
|
|
|
18843
18891
|
progress;
|
|
18844
18892
|
collectedFile;
|
|
18845
18893
|
error;
|
|
18846
|
-
readonly;
|
|
18847
|
-
viewonly;
|
|
18848
|
-
downloadFilesWithHttpClient;
|
|
18894
|
+
readonly = false;
|
|
18895
|
+
viewonly = false;
|
|
18896
|
+
downloadFilesWithHttpClient = false;
|
|
18849
18897
|
testId;
|
|
18850
18898
|
get dataTestId() {
|
|
18851
18899
|
return this.testId;
|
|
18852
18900
|
}
|
|
18853
|
-
canDownload() {
|
|
18854
|
-
return !!this.collectedFile.downloadUrl;
|
|
18855
|
-
}
|
|
18856
18901
|
downloadFile(event) {
|
|
18857
18902
|
if (!this.downloadFilesWithHttpClient)
|
|
18858
18903
|
return;
|
|
@@ -18880,11 +18925,11 @@ class QdFileCollectorItemToolsComponent {
|
|
|
18880
18925
|
});
|
|
18881
18926
|
}
|
|
18882
18927
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorItemToolsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18883
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorItemToolsComponent, isStandalone: false, selector: "qd-file-collector-item-tools", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error", readonly: "readonly", viewonly: "viewonly", downloadFilesWithHttpClient: "downloadFilesWithHttpClient", testId: ["data-test-id", "testId"] }, host: { properties: { "attr.data-test-id": "this.dataTestId" } }, ngImport: i0, template: "<a\n (click)=\"downloadFile($event)\"\n [href]=\"collectedFile.downloadUrl\"\n target=\"_blank\"\n [ngClass]=\"{ hidden: !
|
|
18928
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorItemToolsComponent, isStandalone: false, selector: "qd-file-collector-item-tools", inputs: { progress: "progress", collectedFile: "collectedFile", error: "error", readonly: "readonly", viewonly: "viewonly", downloadFilesWithHttpClient: "downloadFilesWithHttpClient", testId: ["data-test-id", "testId"] }, host: { properties: { "attr.data-test-id": "this.dataTestId" } }, ngImport: i0, template: "<a\n (click)=\"downloadFile($event)\"\n [href]=\"collectedFile.downloadUrl\"\n target=\"_blank\"\n [ngClass]=\"{ hidden: !collectedFile.downloadUrl }\"\n [attr.data-test-id]=\"testId + '-download'\"\n>\n <qd-icon icon=\"dataDownload\"></qd-icon>\n</a>\n\n<qd-icon\n icon=\"trash\"\n (click)=\"deleteFile()\"\n *ngIf=\"!readonly && !viewonly\"\n [attr.data-test-id]=\"testId + '-delete'\"\n></qd-icon>\n", styles: [":host qd-icon{color:#454545;cursor:pointer;font-size:1rem}:host qd-icon:hover,:host qd-icon:focus{color:#171717}:host *+*{margin-left:.5rem}:host .hidden{cursor:none;pointer-events:none;visibility:hidden}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdIconComponent, selector: "qd-icon", inputs: ["icon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
18884
18929
|
}
|
|
18885
18930
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorItemToolsComponent, decorators: [{
|
|
18886
18931
|
type: Component,
|
|
18887
|
-
args: [{ selector: 'qd-file-collector-item-tools', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<a\n (click)=\"downloadFile($event)\"\n [href]=\"collectedFile.downloadUrl\"\n target=\"_blank\"\n [ngClass]=\"{ hidden: !
|
|
18932
|
+
args: [{ selector: 'qd-file-collector-item-tools', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, template: "<a\n (click)=\"downloadFile($event)\"\n [href]=\"collectedFile.downloadUrl\"\n target=\"_blank\"\n [ngClass]=\"{ hidden: !collectedFile.downloadUrl }\"\n [attr.data-test-id]=\"testId + '-download'\"\n>\n <qd-icon icon=\"dataDownload\"></qd-icon>\n</a>\n\n<qd-icon\n icon=\"trash\"\n (click)=\"deleteFile()\"\n *ngIf=\"!readonly && !viewonly\"\n [attr.data-test-id]=\"testId + '-delete'\"\n></qd-icon>\n", styles: [":host qd-icon{color:#454545;cursor:pointer;font-size:1rem}:host qd-icon:hover,:host qd-icon:focus{color:#171717}:host *+*{margin-left:.5rem}:host .hidden{cursor:none;pointer-events:none;visibility:hidden}\n"] }]
|
|
18888
18933
|
}], propDecorators: { progress: [{
|
|
18889
18934
|
type: Input
|
|
18890
18935
|
}], collectedFile: [{
|
|
@@ -18927,7 +18972,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18927
18972
|
}]
|
|
18928
18973
|
}] });
|
|
18929
18974
|
|
|
18930
|
-
// @ts-strict-ignore
|
|
18931
18975
|
class QdFileCollectorUploadTimestampComponent {
|
|
18932
18976
|
value;
|
|
18933
18977
|
testId;
|
|
@@ -18950,15 +18994,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18950
18994
|
args: ['attr.data-test-id']
|
|
18951
18995
|
}] } });
|
|
18952
18996
|
|
|
18953
|
-
// @ts-strict-ignore
|
|
18954
18997
|
class QdFileCollectorItemComponent {
|
|
18955
18998
|
progress;
|
|
18956
|
-
newlyUploaded;
|
|
18999
|
+
newlyUploaded = false;
|
|
18957
19000
|
collectedFile;
|
|
18958
19001
|
error;
|
|
18959
|
-
readonly;
|
|
18960
|
-
viewonly;
|
|
18961
|
-
downloadFilesWithHttpClient;
|
|
19002
|
+
readonly = false;
|
|
19003
|
+
viewonly = false;
|
|
19004
|
+
downloadFilesWithHttpClient = false;
|
|
18962
19005
|
testId;
|
|
18963
19006
|
get hostTestId() {
|
|
18964
19007
|
return this.testId;
|
|
@@ -18997,88 +19040,152 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
18997
19040
|
args: ['class.newly-uploaded']
|
|
18998
19041
|
}] } });
|
|
18999
19042
|
|
|
19000
|
-
// @ts-strict-ignore
|
|
19001
19043
|
/**
|
|
19002
|
-
* **QdFileCollectorComponent**
|
|
19003
|
-
* It supports uploading, downloading, and displaying files, offering various options for customization and configuration.
|
|
19044
|
+
* **QdFileCollectorComponent** lets users view, upload, download, and remove files.
|
|
19004
19045
|
*
|
|
19005
19046
|
* #### **Features**
|
|
19006
19047
|
*
|
|
19007
|
-
* - **Upload**:
|
|
19008
|
-
* - **Download**:
|
|
19009
|
-
* - **
|
|
19010
|
-
* - **
|
|
19011
|
-
* - **
|
|
19012
|
-
*
|
|
19013
|
-
*
|
|
19014
|
-
*
|
|
19015
|
-
* File interactions are managed through several key functions:
|
|
19016
|
-
*
|
|
19017
|
-
* - **upload**: Adds a file to the files list if validation is successful.
|
|
19018
|
-
* - **delete**: Opens a confirmation dialog that, if confirmed, removes the file from the list.
|
|
19019
|
-
* - **readonly/viewonly**: In read-only or view-only mode, upload and delete functions are disabled, limiting user actions.
|
|
19048
|
+
* - **Upload**: select files, validate them, and upload with progress tracking via a custom file manager
|
|
19049
|
+
* - **Download**: directly via URL or through `HttpClient` (e.g. for authorization)
|
|
19050
|
+
* - **Delete**: with confirmation dialog
|
|
19051
|
+
* - **Upload Timestamp**: shows the upload date next to the file name when `uploadTimestamp` is set
|
|
19052
|
+
* - **Validation**: restricts file type, size, and name pattern with customizable error messages
|
|
19053
|
+
* - **Readonly / Viewonly**: disables upload and delete, allows only viewing and downloading
|
|
19054
|
+
* - **Standalone / Section**: works independently with its own add button, or inside a `QdSection` via the toolbar action
|
|
19020
19055
|
*
|
|
19021
|
-
* #### **
|
|
19056
|
+
* #### **Quick start**
|
|
19022
19057
|
*
|
|
19023
|
-
*
|
|
19024
|
-
* It automatically detects when used outside a QLS section structure and, in standalone mode, displays an "Add New" button to support file uploads.
|
|
19058
|
+
* **1. Add the collector to the template**
|
|
19025
19059
|
*
|
|
19026
|
-
*
|
|
19027
|
-
*
|
|
19028
|
-
*
|
|
19029
|
-
* - **maxFileSizeInBytes** sets a maximum file size allowed for uploads.
|
|
19030
|
-
* - **allowedFileNamePattern** defines a regex pattern for file names; files that don’t match the pattern are rejected.
|
|
19060
|
+
* ```html
|
|
19061
|
+
* <qd-file-collector [config]="myFileCollectorConfig"></qd-file-collector>
|
|
19062
|
+
* ```
|
|
19031
19063
|
*
|
|
19032
|
-
*
|
|
19064
|
+
* **2. Define the config in your component**
|
|
19033
19065
|
*
|
|
19034
|
-
*
|
|
19035
|
-
*
|
|
19036
|
-
* -
|
|
19037
|
-
*
|
|
19066
|
+
* ```typescript
|
|
19067
|
+
* @Component({
|
|
19068
|
+
* template: `<qd-file-collector [config]="myFileCollectorConfig"></qd-file-collector>`
|
|
19069
|
+
* })
|
|
19070
|
+
* export class MyComponent {
|
|
19071
|
+
* myFiles: QdCollectedFile[] = [
|
|
19072
|
+
* {
|
|
19073
|
+
* name: 'report.pdf',
|
|
19074
|
+
* size: 9432,
|
|
19075
|
+
* type: 'application/pdf',
|
|
19076
|
+
* downloadUrl: '/api/files/report.pdf',
|
|
19077
|
+
* uploadTimestamp: new Date()
|
|
19078
|
+
* }
|
|
19079
|
+
* ];
|
|
19038
19080
|
*
|
|
19039
|
-
*
|
|
19040
|
-
*
|
|
19041
|
-
*
|
|
19081
|
+
* myFileCollectorConfig: QdFileCollectorConfig = {
|
|
19082
|
+
* files: this.myFiles
|
|
19083
|
+
* };
|
|
19084
|
+
* }
|
|
19085
|
+
* ```
|
|
19042
19086
|
*
|
|
19043
|
-
*
|
|
19087
|
+
* This is enough to show already existing files.
|
|
19044
19088
|
*
|
|
19045
|
-
*
|
|
19046
|
-
* To use it with QdFileCollectorComponent, implement this interface in a custom service and provide it via the `QD_FILE_MANAGER_TOKEN` token.
|
|
19047
|
-
* This service enables you to create custom file-handling logic.
|
|
19089
|
+
* **3. Connect a file manager**
|
|
19048
19090
|
*
|
|
19049
|
-
*
|
|
19091
|
+
* To enable upload and delete, provide a `QdFileManager` via `QD_FILE_MANAGER_TOKEN`.
|
|
19050
19092
|
*
|
|
19051
19093
|
* ```typescript
|
|
19052
19094
|
* @Injectable()
|
|
19053
19095
|
* export class MyFileManager implements QdFileManager {
|
|
19096
|
+
* private http = inject(HttpClient);
|
|
19097
|
+
*
|
|
19054
19098
|
* upload(file: File): Observable<QdUploadProgress> {
|
|
19055
|
-
* //
|
|
19099
|
+
* // Emit progress values from 0 to 100.
|
|
19100
|
+
* // When done, return the final QdCollectedFile from your backend response.
|
|
19101
|
+
* return this.http.post('/api/files', file).pipe(
|
|
19102
|
+
* map(response => {
|
|
19103
|
+
*
|
|
19104
|
+
* const myCollectedFile: QdCollectedFile = {
|
|
19105
|
+
* name: response.fileName,
|
|
19106
|
+
* size: response.fileSize,
|
|
19107
|
+
* type: response.mimeType,
|
|
19108
|
+
* downloadUrl: response.downloadUrl,
|
|
19109
|
+
* uploadTimestamp: new Date(response.storedAt)
|
|
19110
|
+
* };
|
|
19111
|
+
*
|
|
19112
|
+
* return { progress: 100, collectedFile: myCollectedFile };
|
|
19113
|
+
* })
|
|
19114
|
+
* );
|
|
19056
19115
|
* }
|
|
19057
19116
|
*
|
|
19058
19117
|
* delete(collectedFile: QdCollectedFile): Observable<boolean> {
|
|
19059
|
-
*
|
|
19118
|
+
* return this.http.delete('/api/files/' + collectedFile.name).pipe(map(() => true));
|
|
19060
19119
|
* }
|
|
19061
19120
|
* }
|
|
19121
|
+
* ```
|
|
19062
19122
|
*
|
|
19123
|
+
* Register the file manager in your component:
|
|
19124
|
+
*
|
|
19125
|
+
* ```typescript
|
|
19063
19126
|
* @Component({
|
|
19064
|
-
*
|
|
19065
|
-
*
|
|
19066
|
-
*
|
|
19067
|
-
* provide: QD_FILE_MANAGER_TOKEN,
|
|
19068
|
-
* useClass: MyFileManager
|
|
19069
|
-
* }
|
|
19070
|
-
* ]
|
|
19127
|
+
* template: `<qd-file-collector [config]="myFileCollectorConfig"></qd-file-collector>`,
|
|
19128
|
+
* // Add the file manager here to connect the collector to your backend.
|
|
19129
|
+
* providers: [{ provide: QD_FILE_MANAGER_TOKEN, useClass: MyFileManager }]
|
|
19071
19130
|
* })
|
|
19072
|
-
* class
|
|
19073
|
-
*
|
|
19074
|
-
* // configuration options here
|
|
19075
|
-
* };
|
|
19131
|
+
* export class MyComponent {
|
|
19132
|
+
* // ...
|
|
19076
19133
|
* }
|
|
19077
19134
|
* ```
|
|
19078
19135
|
*
|
|
19079
|
-
*
|
|
19080
|
-
*
|
|
19081
|
-
*
|
|
19136
|
+
* #### **How the file manager works**
|
|
19137
|
+
*
|
|
19138
|
+
* The file manager connects the collector to your backend.
|
|
19139
|
+
*
|
|
19140
|
+
* It must support these two actions:
|
|
19141
|
+
*
|
|
19142
|
+
* - `upload(file)`: uploads a file and emits upload progress
|
|
19143
|
+
* - `delete(collectedFile)`: deletes a file and emits `true` if the deletion was successful
|
|
19144
|
+
*
|
|
19145
|
+
* For uploads:
|
|
19146
|
+
*
|
|
19147
|
+
* - emit `{ progress }` values from `0` to `100`
|
|
19148
|
+
* - when the upload is complete, return the final `collectedFile`
|
|
19149
|
+
*
|
|
19150
|
+
* > The example above uses a simple POST and returns one final result with `progress: 100`.
|
|
19151
|
+
* If you need a progress bar, use `HttpClient` with `reportProgress: true` to emit intermediate progress values.
|
|
19152
|
+
*
|
|
19153
|
+
* #### **Validation and file type rules**
|
|
19154
|
+
*
|
|
19155
|
+
* A file is rejected if:
|
|
19156
|
+
*
|
|
19157
|
+
* - its type is not allowed
|
|
19158
|
+
* - it is too large
|
|
19159
|
+
* - its name does not match the expected pattern
|
|
19160
|
+
*
|
|
19161
|
+
* You can provide custom error messages in the config.
|
|
19162
|
+
*
|
|
19163
|
+
* For file type validation, use one of these approaches:
|
|
19164
|
+
*
|
|
19165
|
+
* - `allowedFileTypes`
|
|
19166
|
+
* - `allowedMimeTypes` together with `allowedFileNamePattern`
|
|
19167
|
+
*
|
|
19168
|
+
* > Do not mix both approaches unless they describe the same rules.
|
|
19169
|
+
* > If the settings do not match, the component logs an error and does not use the config.
|
|
19170
|
+
*
|
|
19171
|
+
* #### **Upload behavior**
|
|
19172
|
+
*
|
|
19173
|
+
* Upload is triggered differently depending on where the component is used:
|
|
19174
|
+
*
|
|
19175
|
+
* - **outside a `QdSection`**: the component shows its own add button
|
|
19176
|
+
* - **inside a `QdSection`**: the component listens to the section action and opens the file picker when `addNew` is triggered
|
|
19177
|
+
*
|
|
19178
|
+
* In `readonly` or `viewonly` mode, upload and delete are disabled.
|
|
19179
|
+
*
|
|
19180
|
+
* If the component is connected to operation mode changes through the event broker,
|
|
19181
|
+
* `viewonly` can also change dynamically.
|
|
19182
|
+
*
|
|
19183
|
+
* #### **Download**
|
|
19184
|
+
*
|
|
19185
|
+
* Files can be downloaded directly from their `downloadUrl`.
|
|
19186
|
+
*
|
|
19187
|
+
* If your application needs authorization or custom download logic,
|
|
19188
|
+
* handle the download through your backend or file manager.
|
|
19082
19189
|
*/
|
|
19083
19190
|
class QdFileCollectorComponent {
|
|
19084
19191
|
sectionActionService = inject(QdSectionToolbarActionService, { optional: true });
|
|
@@ -19128,14 +19235,16 @@ class QdFileCollectorComponent {
|
|
|
19128
19235
|
title: { i18n: 'i18n.qd.fileCollector.title' },
|
|
19129
19236
|
viewContainerRef: this.viewContainerRef
|
|
19130
19237
|
});
|
|
19131
|
-
dialogRef.closed.subscribe((
|
|
19132
|
-
fileUploads
|
|
19238
|
+
dialogRef.closed.subscribe((result) => {
|
|
19239
|
+
const fileUploads = result;
|
|
19240
|
+
(fileUploads ?? [])
|
|
19133
19241
|
.filter(fileUpload => !fileUpload.error && fileUpload.progress === 100)
|
|
19134
19242
|
.forEach(fileUpload => this.fileUploads.push({ ...fileUpload, newlyUploaded: true }));
|
|
19135
19243
|
});
|
|
19136
19244
|
const fileCollectorDialog = dialogRef.componentInstance;
|
|
19137
|
-
|
|
19138
|
-
|
|
19245
|
+
const inputElement = event.target;
|
|
19246
|
+
fileCollectorDialog.uploadFiles(Array.from(inputElement.files ?? []));
|
|
19247
|
+
inputElement.value = '';
|
|
19139
19248
|
}
|
|
19140
19249
|
clickFileInput() {
|
|
19141
19250
|
if (this.fileInput.nativeElement.disabled) {
|
|
@@ -19184,11 +19293,11 @@ class QdFileCollectorComponent {
|
|
|
19184
19293
|
console.error(`QD-UI | QdFileCollector - ${message}`);
|
|
19185
19294
|
}
|
|
19186
19295
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
19187
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorComponent, isStandalone: false, selector: "qd-file-collector", inputs: { config: "config", testId: ["data-test-id", "testId"] }, providers: [QdFileCollectorService, QdFileCollectorValidationService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n *ngIf=\"canShowAddButton\"\n (click)=\"clickFileInput()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n>\n {{ config?.standaloneAddNewLabel?.i18n || \"i18n.qd.fileCollector.standalone.addNew\" | translate }}\n</button>\n\n<input\n [disabled]=\"config?.readonly || config?.viewonly\"\n type=\"file\"\n (change)=\"handleFiles($event)\"\n #fileInput\n hidden\n multiple=\"multiple\"\n/>\n\n<qd-file-collector-allowed-files-description\n *ngIf=\"!config?.readonly && !config?.viewonly\"\n></qd-file-collector-allowed-files-description>\n\n<ng-container *ngFor=\"let fileUpload of this.fileUploads; let i = index\">\n <qd-file-collector-item\n *ngIf=\"!fileUpload.error && fileUpload.progress === 100\"\n [progress]=\"fileUpload.progress\"\n [newlyUploaded]=\"fileUpload.newlyUploaded\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [readonly]=\"config?.readonly\"\n [viewonly]=\"config?.viewonly\"\n [downloadFilesWithHttpClient]=\"config?.downloadFilesWithHttpClient\"\n [data-test-id]=\"testId + '-item-' + i\"\n ></qd-file-collector-item>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column}:host>.qd-button{align-self:end;margin-bottom:1.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdFileCollectorAllowedFilesDescriptionComponent, selector: "qd-file-collector-allowed-files-description" }, { kind: "component", type: QdFileCollectorItemComponent, selector: "qd-file-collector-item", inputs: ["progress", "newlyUploaded", "collectedFile", "error", "readonly", "viewonly", "downloadFilesWithHttpClient", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
19296
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: QdFileCollectorComponent, isStandalone: false, selector: "qd-file-collector", inputs: { config: "config", testId: ["data-test-id", "testId"] }, providers: [QdFileCollectorService, QdFileCollectorValidationService], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n *ngIf=\"canShowAddButton\"\n (click)=\"clickFileInput()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n>\n {{ config?.standaloneAddNewLabel?.i18n || \"i18n.qd.fileCollector.standalone.addNew\" | translate }}\n</button>\n\n<input\n [disabled]=\"config?.readonly || config?.viewonly\"\n type=\"file\"\n (change)=\"handleFiles($event)\"\n #fileInput\n hidden\n multiple=\"multiple\"\n/>\n\n<qd-file-collector-allowed-files-description\n *ngIf=\"!config?.readonly && !config?.viewonly\"\n [attr.data-test-id]=\"testId + '-allowed-files-description'\"\n></qd-file-collector-allowed-files-description>\n\n<ng-container *ngFor=\"let fileUpload of this.fileUploads; let i = index\">\n <qd-file-collector-item\n *ngIf=\"!fileUpload.error && fileUpload.progress === 100\"\n [progress]=\"fileUpload.progress\"\n [newlyUploaded]=\"fileUpload.newlyUploaded\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [readonly]=\"config?.readonly\"\n [viewonly]=\"config?.viewonly\"\n [downloadFilesWithHttpClient]=\"config?.downloadFilesWithHttpClient\"\n [data-test-id]=\"testId + '-item-' + i\"\n ></qd-file-collector-item>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column}:host>.qd-button{align-self:end;margin-bottom:1.5rem}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QdButtonComponent, selector: "button[qdButton], a[qdButton], button[qd-button]", inputs: ["disabled", "color", "icon", "data-test-id", "additionalInfo"] }, { kind: "directive", type: QdButtonGhostDirective, selector: "button[qdButtonGhost], a[qdButtonGhost]" }, { kind: "component", type: QdFileCollectorAllowedFilesDescriptionComponent, selector: "qd-file-collector-allowed-files-description" }, { kind: "component", type: QdFileCollectorItemComponent, selector: "qd-file-collector-item", inputs: ["progress", "newlyUploaded", "collectedFile", "error", "readonly", "viewonly", "downloadFilesWithHttpClient", "data-test-id"] }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
|
|
19188
19297
|
}
|
|
19189
19298
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: QdFileCollectorComponent, decorators: [{
|
|
19190
19299
|
type: Component,
|
|
19191
|
-
args: [{ selector: 'qd-file-collector', providers: [QdFileCollectorService, QdFileCollectorValidationService], standalone: false, template: "<button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n *ngIf=\"canShowAddButton\"\n (click)=\"clickFileInput()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n>\n {{ config?.standaloneAddNewLabel?.i18n || \"i18n.qd.fileCollector.standalone.addNew\" | translate }}\n</button>\n\n<input\n [disabled]=\"config?.readonly || config?.viewonly\"\n type=\"file\"\n (change)=\"handleFiles($event)\"\n #fileInput\n hidden\n multiple=\"multiple\"\n/>\n\n<qd-file-collector-allowed-files-description\n *ngIf=\"!config?.readonly && !config?.viewonly\"\n></qd-file-collector-allowed-files-description>\n\n<ng-container *ngFor=\"let fileUpload of this.fileUploads; let i = index\">\n <qd-file-collector-item\n *ngIf=\"!fileUpload.error && fileUpload.progress === 100\"\n [progress]=\"fileUpload.progress\"\n [newlyUploaded]=\"fileUpload.newlyUploaded\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [readonly]=\"config?.readonly\"\n [viewonly]=\"config?.viewonly\"\n [downloadFilesWithHttpClient]=\"config?.downloadFilesWithHttpClient\"\n [data-test-id]=\"testId + '-item-' + i\"\n ></qd-file-collector-item>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column}:host>.qd-button{align-self:end;margin-bottom:1.5rem}\n"] }]
|
|
19300
|
+
args: [{ selector: 'qd-file-collector', providers: [QdFileCollectorService, QdFileCollectorValidationService], standalone: false, template: "<button\n qdButton\n qdButtonGhost\n icon=\"plus\"\n *ngIf=\"canShowAddButton\"\n (click)=\"clickFileInput()\"\n [data-test-id]=\"testId + '-button-add-new'\"\n>\n {{ config?.standaloneAddNewLabel?.i18n || \"i18n.qd.fileCollector.standalone.addNew\" | translate }}\n</button>\n\n<input\n [disabled]=\"config?.readonly || config?.viewonly\"\n type=\"file\"\n (change)=\"handleFiles($event)\"\n #fileInput\n hidden\n multiple=\"multiple\"\n/>\n\n<qd-file-collector-allowed-files-description\n *ngIf=\"!config?.readonly && !config?.viewonly\"\n [attr.data-test-id]=\"testId + '-allowed-files-description'\"\n></qd-file-collector-allowed-files-description>\n\n<ng-container *ngFor=\"let fileUpload of this.fileUploads; let i = index\">\n <qd-file-collector-item\n *ngIf=\"!fileUpload.error && fileUpload.progress === 100\"\n [progress]=\"fileUpload.progress\"\n [newlyUploaded]=\"fileUpload.newlyUploaded\"\n [collectedFile]=\"fileUpload.collectedFile\"\n [error]=\"fileUpload.error\"\n [readonly]=\"config?.readonly\"\n [viewonly]=\"config?.viewonly\"\n [downloadFilesWithHttpClient]=\"config?.downloadFilesWithHttpClient\"\n [data-test-id]=\"testId + '-item-' + i\"\n ></qd-file-collector-item>\n</ng-container>\n", styles: [":host{display:flex;flex-direction:column}:host>.qd-button{align-self:end;margin-bottom:1.5rem}\n"] }]
|
|
19192
19301
|
}], propDecorators: { config: [{
|
|
19193
19302
|
type: Input
|
|
19194
19303
|
}], testId: [{
|
|
@@ -26999,8 +27108,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
26999
27108
|
class QdFormGroupManagerService {
|
|
27000
27109
|
_formGroups = new Map();
|
|
27001
27110
|
_formGroupsSnapshot = new Map();
|
|
27111
|
+
_formGroupsChanged$ = new BehaviorSubject(undefined);
|
|
27002
27112
|
setFormGroup(key, formGroup) {
|
|
27003
27113
|
this._formGroups.set(key, formGroup);
|
|
27114
|
+
this._formGroupsChanged$.next();
|
|
27004
27115
|
}
|
|
27005
27116
|
getFormGroup(key) {
|
|
27006
27117
|
return this._formGroups.get(key);
|
|
@@ -27010,6 +27121,7 @@ class QdFormGroupManagerService {
|
|
|
27010
27121
|
}
|
|
27011
27122
|
tryRemoveFormGroup(key) {
|
|
27012
27123
|
this._formGroups.delete(key);
|
|
27124
|
+
this._formGroupsChanged$.next();
|
|
27013
27125
|
}
|
|
27014
27126
|
hasFormGroups() {
|
|
27015
27127
|
return this._formGroups.size > 0;
|
|
@@ -27023,19 +27135,24 @@ class QdFormGroupManagerService {
|
|
|
27023
27135
|
return !this._formGroups.has(key);
|
|
27024
27136
|
}
|
|
27025
27137
|
$areFormGroupsValid() {
|
|
27026
|
-
|
|
27027
|
-
|
|
27028
|
-
|
|
27029
|
-
|
|
27138
|
+
return this._formGroupsChanged$.pipe(observeOn(queueScheduler), switchMap$1(() => {
|
|
27139
|
+
if (!this.hasFormGroups())
|
|
27140
|
+
return of(false);
|
|
27141
|
+
const obs = Array.from(this._formGroups.values()).map(fg => fg.statusChanges.pipe(startWith(fg.status), map(() => this.areFormGroupsValid(fg))));
|
|
27142
|
+
return combineLatest(obs).pipe(map(valids => valids.every(Boolean)));
|
|
27143
|
+
}));
|
|
27030
27144
|
}
|
|
27031
27145
|
$hasValuesChanged() {
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
const
|
|
27036
|
-
|
|
27037
|
-
|
|
27038
|
-
|
|
27146
|
+
return this._formGroupsChanged$.pipe(observeOn(queueScheduler), switchMap$1(() => {
|
|
27147
|
+
if (!this.hasFormGroups())
|
|
27148
|
+
return of(false);
|
|
27149
|
+
const obs = Array.from(this._formGroups.entries()).map(([key, fg]) => fg.valueChanges.pipe(startWith(fg.getRawValue()), map(() => {
|
|
27150
|
+
const currentValues = fg.getRawValue();
|
|
27151
|
+
const snapshot = this._formGroupsSnapshot.get(key);
|
|
27152
|
+
return snapshot ? !isEqual$1(currentValues, snapshot) : true;
|
|
27153
|
+
})));
|
|
27154
|
+
return combineLatest(obs).pipe(map(changes => changes.some(Boolean)));
|
|
27155
|
+
}));
|
|
27039
27156
|
}
|
|
27040
27157
|
takeFormGroupsSnapshot() {
|
|
27041
27158
|
this._formGroups.forEach((fg, key) => this._formGroupsSnapshot.set(key, fg.getRawValue()));
|
|
@@ -27055,6 +27172,43 @@ class QdFormGroupManagerService {
|
|
|
27055
27172
|
}
|
|
27056
27173
|
});
|
|
27057
27174
|
});
|
|
27175
|
+
this.cancelPendingAsyncValidation();
|
|
27176
|
+
}
|
|
27177
|
+
/**
|
|
27178
|
+
* Cancels any in-flight async validators on all registered form groups.
|
|
27179
|
+
*
|
|
27180
|
+
* 1. Collect all PENDING controls and their async validators
|
|
27181
|
+
* 2. Clear all async validators, then update validity (sync-only, no cascade)
|
|
27182
|
+
* 3. Re-attach async validators for future use
|
|
27183
|
+
*/
|
|
27184
|
+
cancelPendingAsyncValidation() {
|
|
27185
|
+
this._formGroups.forEach(fg => {
|
|
27186
|
+
const pendingControls = this.collectPendingControls(fg);
|
|
27187
|
+
if (pendingControls.length === 0)
|
|
27188
|
+
return;
|
|
27189
|
+
for (const { control } of pendingControls) {
|
|
27190
|
+
control.clearAsyncValidators();
|
|
27191
|
+
}
|
|
27192
|
+
for (const { control } of pendingControls) {
|
|
27193
|
+
control.updateValueAndValidity({ onlySelf: true });
|
|
27194
|
+
}
|
|
27195
|
+
for (const { control, asyncValidator } of pendingControls) {
|
|
27196
|
+
control.setAsyncValidators(asyncValidator);
|
|
27197
|
+
}
|
|
27198
|
+
});
|
|
27199
|
+
}
|
|
27200
|
+
collectPendingControls(control) {
|
|
27201
|
+
const result = [];
|
|
27202
|
+
if (control instanceof FormGroup) {
|
|
27203
|
+
Object.values(control.controls).forEach(c => result.push(...this.collectPendingControls(c)));
|
|
27204
|
+
}
|
|
27205
|
+
else if (control instanceof FormArray) {
|
|
27206
|
+
control.controls.forEach(c => result.push(...this.collectPendingControls(c)));
|
|
27207
|
+
}
|
|
27208
|
+
if (control.status === 'PENDING') {
|
|
27209
|
+
result.push({ control, asyncValidator: control.asyncValidator });
|
|
27210
|
+
}
|
|
27211
|
+
return result;
|
|
27058
27212
|
}
|
|
27059
27213
|
resetFormArrayToValues(array, newValues) {
|
|
27060
27214
|
if (!Array.isArray(newValues))
|
|
@@ -27179,6 +27333,7 @@ class QdPageObjectHeaderComponent {
|
|
|
27179
27333
|
_pageObjectDataSubject = new BehaviorSubject({});
|
|
27180
27334
|
_isLoadingSubject = new BehaviorSubject(false);
|
|
27181
27335
|
_customActionsSubject = new BehaviorSubject({ actions: [] });
|
|
27336
|
+
_customActionsSub;
|
|
27182
27337
|
_destroyed$ = new Subject();
|
|
27183
27338
|
_availableContexts = 0;
|
|
27184
27339
|
pageObjectData$ = this._pageObjectDataSubject.asObservable();
|
|
@@ -27309,14 +27464,18 @@ class QdPageObjectHeaderComponent {
|
|
|
27309
27464
|
.$hasValuesChanged()
|
|
27310
27465
|
.pipe(take(1))
|
|
27311
27466
|
.subscribe(hasChanged => {
|
|
27312
|
-
if (hasChanged)
|
|
27467
|
+
if (hasChanged) {
|
|
27313
27468
|
this.openCancelDialog();
|
|
27314
|
-
|
|
27469
|
+
}
|
|
27470
|
+
else {
|
|
27471
|
+
this.formGroupManagerService.cancelPendingAsyncValidation();
|
|
27315
27472
|
this.pageStoreService.toggleViewonly(true);
|
|
27473
|
+
}
|
|
27316
27474
|
});
|
|
27317
27475
|
}
|
|
27318
27476
|
save() {
|
|
27319
27477
|
const handleSuccess = () => {
|
|
27478
|
+
this.formGroupManagerService.cancelPendingAsyncValidation();
|
|
27320
27479
|
this.pageStoreService.toggleViewonly(true);
|
|
27321
27480
|
this.formGroupManagerService.takeFormGroupsSnapshot();
|
|
27322
27481
|
};
|
|
@@ -27345,7 +27504,7 @@ class QdPageObjectHeaderComponent {
|
|
|
27345
27504
|
setupResolverTrigger() {
|
|
27346
27505
|
this.resolverTriggerService
|
|
27347
27506
|
.shouldTriggerResolver(this.pageObjectResolver.config?.triggerOn ?? 'pathParamsChange')
|
|
27348
|
-
.pipe(takeUntil(this._destroyed$), filter(shouldTrigger => shouldTrigger), tap(() => this._isLoadingSubject.next(true)), switchMap(() => this.pageObjectResolver.resolve()), tap(objectData => this._pageObjectDataSubject.next(objectData)), tap(() => this._isLoadingSubject.next(false)))
|
|
27507
|
+
.pipe(takeUntil(this._destroyed$), filter(shouldTrigger => shouldTrigger), tap(() => this._isLoadingSubject.next(true)), switchMap(() => this.pageObjectResolver.resolve()), tap(objectData => this._pageObjectDataSubject.next(objectData)), tap(() => this._isLoadingSubject.next(false)), tap(() => this.formGroupManagerService.takeFormGroupsSnapshot()))
|
|
27349
27508
|
.subscribe();
|
|
27350
27509
|
}
|
|
27351
27510
|
initContexts() {
|
|
@@ -27364,17 +27523,32 @@ class QdPageObjectHeaderComponent {
|
|
|
27364
27523
|
.subscribe();
|
|
27365
27524
|
}
|
|
27366
27525
|
updateCustomActions() {
|
|
27367
|
-
|
|
27368
|
-
|
|
27369
|
-
|
|
27370
|
-
|
|
27371
|
-
|
|
27372
|
-
|
|
27373
|
-
|
|
27374
|
-
|
|
27526
|
+
// 1. Handle non-inspect pages early
|
|
27527
|
+
if (this.config.pageType !== 'inspect') {
|
|
27528
|
+
const actions = this.config.pageTypeConfig?.customActions ?? [];
|
|
27529
|
+
this._customActionsSubject.next({ actions });
|
|
27530
|
+
return;
|
|
27531
|
+
}
|
|
27532
|
+
// 2. Setup Inspect-specific logic
|
|
27533
|
+
const config = this.config.pageTypeConfig;
|
|
27534
|
+
if (config?.operationMode) {
|
|
27535
|
+
this.pageStoreService.toggleViewonly(config.operationMode === 'view');
|
|
27375
27536
|
}
|
|
27376
|
-
|
|
27377
|
-
|
|
27537
|
+
this.subscribeToViewOnlyMode();
|
|
27538
|
+
}
|
|
27539
|
+
subscribeToViewOnlyMode() {
|
|
27540
|
+
this._customActionsSub?.unsubscribe();
|
|
27541
|
+
this._customActionsSub = this.pageStoreService.isViewonly$
|
|
27542
|
+
.pipe(takeUntil(this._destroyed$))
|
|
27543
|
+
.subscribe(isViewonly => {
|
|
27544
|
+
const mode = isViewonly ? 'view' : 'edit';
|
|
27545
|
+
const config = this.config.pageTypeConfig;
|
|
27546
|
+
if (config) {
|
|
27547
|
+
config.operationMode = mode;
|
|
27548
|
+
}
|
|
27549
|
+
const actions = config?.customActions ?? [];
|
|
27550
|
+
this._customActionsSubject.next(this.getCustomActionsByMode(actions, mode));
|
|
27551
|
+
});
|
|
27378
27552
|
}
|
|
27379
27553
|
getCustomActionsByMode(customActions, mode) {
|
|
27380
27554
|
const actions = customActions
|
|
@@ -28373,6 +28547,7 @@ class QdPageSubmitActionService {
|
|
|
28373
28547
|
_submitHandler;
|
|
28374
28548
|
_isVisible = true;
|
|
28375
28549
|
_destroyed$ = new Subject();
|
|
28550
|
+
_cancelTrackFormValidity$ = new Subject();
|
|
28376
28551
|
ngOnDestroy() {
|
|
28377
28552
|
this._destroyed$.next(null);
|
|
28378
28553
|
this._destroyed$.complete();
|
|
@@ -28411,9 +28586,10 @@ class QdPageSubmitActionService {
|
|
|
28411
28586
|
};
|
|
28412
28587
|
}
|
|
28413
28588
|
trackFormValidity() {
|
|
28589
|
+
this._cancelTrackFormValidity$.next();
|
|
28414
28590
|
this.formGroupManagerService
|
|
28415
28591
|
.$areFormGroupsValid()
|
|
28416
|
-
.pipe(takeUntil(this._destroyed$), distinctUntilChanged())
|
|
28592
|
+
.pipe(takeUntil(this._cancelTrackFormValidity$), takeUntil(this._destroyed$), distinctUntilChanged())
|
|
28417
28593
|
.subscribe(isValid => this.updateSubmitButtonState(isValid));
|
|
28418
28594
|
}
|
|
28419
28595
|
updateSubmitButtonState(isValid) {
|
|
@@ -28851,6 +29027,7 @@ class QdPageComponent {
|
|
|
28851
29027
|
projectionGuardMessage = 'QD-UI | QdPage - This content is not supported. Please use QdSectionAdapterDirective for custom content projection.';
|
|
28852
29028
|
_isInitialized = false;
|
|
28853
29029
|
_destroyed$ = new Subject();
|
|
29030
|
+
_cancelSubmitValidation$ = new Subject();
|
|
28854
29031
|
get isControlPanelVisible() {
|
|
28855
29032
|
return this.controlPanel !== undefined && this.controlPanel.config?.isHidden !== true;
|
|
28856
29033
|
}
|
|
@@ -28965,6 +29142,10 @@ class QdPageComponent {
|
|
|
28965
29142
|
]);
|
|
28966
29143
|
}
|
|
28967
29144
|
updateInspectPageOperationMode(pageTypeConfig, mode) {
|
|
29145
|
+
if (mode === 'view') {
|
|
29146
|
+
this.formGroupManagerService.cancelPendingAsyncValidation();
|
|
29147
|
+
setTimeout(() => this.formGroupManagerService.cancelPendingAsyncValidation());
|
|
29148
|
+
}
|
|
28968
29149
|
if (pageTypeConfig?.submit) {
|
|
28969
29150
|
const isVisible = mode === 'view' && !pageTypeConfig.submit.isHidden;
|
|
28970
29151
|
this.submitActionService.setSubmitActionForInspect(pageTypeConfig, isVisible);
|
|
@@ -28992,9 +29173,10 @@ class QdPageComponent {
|
|
|
28992
29173
|
.subscribe();
|
|
28993
29174
|
}
|
|
28994
29175
|
initSubmitValidation() {
|
|
29176
|
+
this._cancelSubmitValidation$.next();
|
|
28995
29177
|
this.formGroupManagerService
|
|
28996
29178
|
.$areFormGroupsValid()
|
|
28997
|
-
.pipe(takeUntil(this._destroyed$), tap(isValid => {
|
|
29179
|
+
.pipe(takeUntil(this._cancelSubmitValidation$), takeUntil(this._destroyed$), tap(isValid => {
|
|
28998
29180
|
const submitDisabledInfoText = this.config.pageType === 'inspect' ? this.config.pageTypeConfig?.submit?.disabledInfo : undefined;
|
|
28999
29181
|
this.footerService.updateActions([
|
|
29000
29182
|
{
|