@smartbit4all/ng-client 7.3.23 → 7.3.25
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.
|
@@ -8,8 +8,8 @@ import { QuillEditorComponent, QuillModule } from 'ngx-quill';
|
|
|
8
8
|
import { DateFnsAdapter } from '@angular/material-date-fns-adapter';
|
|
9
9
|
import { enUS, hu } from 'date-fns/locale';
|
|
10
10
|
import { isPlatformBrowser, NgClass, NgTemplateOutlet, NgStyle, Location, AsyncPipe, KeyValuePipe, DatePipe, NgIf, NgForOf } from '@angular/common';
|
|
11
|
-
import { Subject, lastValueFrom,
|
|
12
|
-
import { catchError, switchMap, takeUntil as takeUntil$1 } from 'rxjs/operators';
|
|
11
|
+
import { Subject, lastValueFrom, defer, finalize, filter, startWith, map, distinctUntilChanged, tap, takeUntil, interval, throwError, from, catchError as catchError$1 } from 'rxjs';
|
|
12
|
+
import { catchError, switchMap, filter as filter$1, takeUntil as takeUntil$1 } from 'rxjs/operators';
|
|
13
13
|
import { deepEqual } from 'fast-equals';
|
|
14
14
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
15
15
|
import { MatDialogRef, MatDialog, MAT_DIALOG_DATA, MatDialogContent, MatDialogTitle, MatDialogClose, MatDialogActions } from '@angular/material/dialog';
|
|
@@ -23,7 +23,7 @@ import { MAT_SNACK_BAR_DATA, MatSnackBarLabel, MatSnackBar } from '@angular/mate
|
|
|
23
23
|
import { Overlay, OverlayPositionBuilder, ScrollDispatcher } from '@angular/cdk/overlay';
|
|
24
24
|
import { TemplatePortal } from '@angular/cdk/portal';
|
|
25
25
|
import * as i1$1 from '@angular/forms';
|
|
26
|
-
import { Validators,
|
|
26
|
+
import { Validators, UntypedFormControl, UntypedFormGroup, NG_VALUE_ACCESSOR, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
27
27
|
import { ENTER, COMMA } from '@angular/cdk/keycodes';
|
|
28
28
|
import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
|
29
29
|
import { MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChip } from '@angular/material/chips';
|
|
@@ -56,6 +56,8 @@ import ZoomPlugin from 'chartjs-plugin-zoom';
|
|
|
56
56
|
import ChartDataLabels from 'chartjs-plugin-datalabels';
|
|
57
57
|
import { MatToolbar } from '@angular/material/toolbar';
|
|
58
58
|
|
|
59
|
+
/** The default count limit of the Global Value Set Store's explicit sets. */
|
|
60
|
+
const DEFAULT_VALUE_SET_STORE_SIZE = 200;
|
|
59
61
|
/**
|
|
60
62
|
* The resolved library configuration. Provided by {@link provideSmartNgClient}; inject it
|
|
61
63
|
* to read a configured value.
|
|
@@ -68,6 +70,7 @@ function resolveSmartNgClientConfig(config) {
|
|
|
68
70
|
treeMenuIcon: 'more_vert',
|
|
69
71
|
dialogDisableClose: true,
|
|
70
72
|
dateLocale: 'hu-HU',
|
|
73
|
+
valueSetStoreSize: DEFAULT_VALUE_SET_STORE_SIZE,
|
|
71
74
|
...config,
|
|
72
75
|
// Merged field by field, so that configuring one string keeps the other two defaults.
|
|
73
76
|
errorDialog: {
|
|
@@ -1609,6 +1612,60 @@ class ViewService {
|
|
|
1609
1612
|
reportProgress: reportProgress
|
|
1610
1613
|
});
|
|
1611
1614
|
}
|
|
1615
|
+
fetchValueSets(viewUuid, valueSetFetchRequest, observe = 'body', reportProgress = false, options) {
|
|
1616
|
+
if (viewUuid === null || viewUuid === undefined) {
|
|
1617
|
+
throw new Error('Required parameter viewUuid was null or undefined when calling fetchValueSets.');
|
|
1618
|
+
}
|
|
1619
|
+
if (valueSetFetchRequest === null || valueSetFetchRequest === undefined) {
|
|
1620
|
+
throw new Error('Required parameter valueSetFetchRequest was null or undefined when calling fetchValueSets.');
|
|
1621
|
+
}
|
|
1622
|
+
let localVarHeaders = this.defaultHeaders;
|
|
1623
|
+
let localVarHttpHeaderAcceptSelected = options && options.httpHeaderAccept;
|
|
1624
|
+
if (localVarHttpHeaderAcceptSelected === undefined) {
|
|
1625
|
+
// to determine the Accept header
|
|
1626
|
+
const httpHeaderAccepts = [
|
|
1627
|
+
'application/json'
|
|
1628
|
+
];
|
|
1629
|
+
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
|
1630
|
+
}
|
|
1631
|
+
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
|
1632
|
+
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
|
1633
|
+
}
|
|
1634
|
+
let localVarHttpContext = options && options.context;
|
|
1635
|
+
if (localVarHttpContext === undefined) {
|
|
1636
|
+
localVarHttpContext = new HttpContext();
|
|
1637
|
+
}
|
|
1638
|
+
// to determine the Content-Type header
|
|
1639
|
+
const consumes = [
|
|
1640
|
+
'application/json'
|
|
1641
|
+
];
|
|
1642
|
+
const httpContentTypeSelected = this.configuration.selectHeaderContentType(consumes);
|
|
1643
|
+
if (httpContentTypeSelected !== undefined) {
|
|
1644
|
+
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
|
|
1645
|
+
}
|
|
1646
|
+
let responseType_ = 'json';
|
|
1647
|
+
if (localVarHttpHeaderAcceptSelected) {
|
|
1648
|
+
if (localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
|
1649
|
+
responseType_ = 'text';
|
|
1650
|
+
}
|
|
1651
|
+
else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) {
|
|
1652
|
+
responseType_ = 'json';
|
|
1653
|
+
}
|
|
1654
|
+
else {
|
|
1655
|
+
responseType_ = 'blob';
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
let localVarPath = `/component/${this.configuration.encodeParam({ name: "viewUuid", value: viewUuid, in: "path", style: "simple", explode: false, dataType: "string", dataFormat: "uuid" })}/valueSets`;
|
|
1659
|
+
return this.httpClient.request('post', `${this.configuration.basePath}${localVarPath}`, {
|
|
1660
|
+
context: localVarHttpContext,
|
|
1661
|
+
body: valueSetFetchRequest,
|
|
1662
|
+
responseType: responseType_,
|
|
1663
|
+
withCredentials: this.configuration.withCredentials,
|
|
1664
|
+
headers: localVarHeaders,
|
|
1665
|
+
observe: observe,
|
|
1666
|
+
reportProgress: reportProgress
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1612
1669
|
getAndroidTheme(name, observe = 'body', reportProgress = false, options) {
|
|
1613
1670
|
if (name === null || name === undefined) {
|
|
1614
1671
|
throw new Error('Required parameter name was null or undefined when calling getAndroidTheme.');
|
|
@@ -3091,6 +3148,30 @@ var UploadWidgetType;
|
|
|
3091
3148
|
UploadWidgetType["IMAGE"] = "IMAGE";
|
|
3092
3149
|
})(UploadWidgetType || (UploadWidgetType = {}));
|
|
3093
3150
|
|
|
3151
|
+
/**
|
|
3152
|
+
* View API
|
|
3153
|
+
* View API
|
|
3154
|
+
*
|
|
3155
|
+
* The version of the OpenAPI document: 1.0.0
|
|
3156
|
+
* Contact: info@it4all.hu
|
|
3157
|
+
*
|
|
3158
|
+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
3159
|
+
* https://openapi-generator.tech
|
|
3160
|
+
* Do not edit the class manually.
|
|
3161
|
+
*/
|
|
3162
|
+
|
|
3163
|
+
/**
|
|
3164
|
+
* View API
|
|
3165
|
+
* View API
|
|
3166
|
+
*
|
|
3167
|
+
* The version of the OpenAPI document: 1.0.0
|
|
3168
|
+
* Contact: info@it4all.hu
|
|
3169
|
+
*
|
|
3170
|
+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
3171
|
+
* https://openapi-generator.tech
|
|
3172
|
+
* Do not edit the class manually.
|
|
3173
|
+
*/
|
|
3174
|
+
|
|
3094
3175
|
/**
|
|
3095
3176
|
* View API
|
|
3096
3177
|
* View API
|
|
@@ -4228,6 +4309,602 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
4228
4309
|
args: [{ selector: '[smartEmbeddedSlot]' }]
|
|
4229
4310
|
}], propDecorators: { containerId: [{ type: i0.Input, args: [{ isSignal: true, alias: "smartEmbeddedSlot", required: true }] }], containerUuid: [{ type: i0.Input, args: [{ isSignal: true, alias: "containerUuid", required: false }] }] } });
|
|
4230
4311
|
|
|
4312
|
+
/**
|
|
4313
|
+
* The key and display property of a valueSet's values: the preferred name if the values carry it,
|
|
4314
|
+
* then the GenericValue name (`uri` / `name`), then the Value name (`objectUri` / `displayValue`).
|
|
4315
|
+
* With no sample value to look at the preferred name is assumed to exist.
|
|
4316
|
+
*/
|
|
4317
|
+
function valueSetKeyProperty(values, preferred) {
|
|
4318
|
+
return firstExisting(values, [preferred ?? 'objectUri', 'uri', 'objectUri']);
|
|
4319
|
+
}
|
|
4320
|
+
function valueSetDisplayProperty(values, preferred) {
|
|
4321
|
+
return firstExisting(values, [preferred ?? 'displayValue', 'name', 'displayValue']);
|
|
4322
|
+
}
|
|
4323
|
+
/** The label of a code in a valueSet, or undefined when the valueSet does not know the code. */
|
|
4324
|
+
function valueSetLabelOf(valueSetData, code) {
|
|
4325
|
+
const values = valueSetData.values ?? [];
|
|
4326
|
+
const keyProperty = valueSetKeyProperty(values, valueSetData.keyProperty);
|
|
4327
|
+
const hit = values.find((value) => String(value[keyProperty]) === String(code));
|
|
4328
|
+
return hit?.[valueSetDisplayProperty(values)];
|
|
4329
|
+
}
|
|
4330
|
+
function firstExisting(values, candidates) {
|
|
4331
|
+
if (!values?.length) {
|
|
4332
|
+
return candidates[0];
|
|
4333
|
+
}
|
|
4334
|
+
return candidates.find((c) => c in values[0]) ?? candidates[candidates.length - 1];
|
|
4335
|
+
}
|
|
4336
|
+
|
|
4337
|
+
/**
|
|
4338
|
+
* The Global Value Set Store: the value sets of the browser tab shared by every open view,
|
|
4339
|
+
* explicit sets by backend module, namespace and name, implicit sets by view uuid and key. It
|
|
4340
|
+
* fetches the versions a view context change names and it lacks, keeps what the open views read
|
|
4341
|
+
* and empties at a change of the session locale.
|
|
4342
|
+
*/
|
|
4343
|
+
class SmartValueSetStore {
|
|
4344
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartValueSetStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4345
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartValueSetStore, providedIn: "root", useFactory: () => new SmartValueSetMemoryStore() }); }
|
|
4346
|
+
}
|
|
4347
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartValueSetStore, decorators: [{
|
|
4348
|
+
type: Injectable,
|
|
4349
|
+
args: [{
|
|
4350
|
+
providedIn: "root",
|
|
4351
|
+
useFactory: () => new SmartValueSetMemoryStore(),
|
|
4352
|
+
}]
|
|
4353
|
+
}] });
|
|
4354
|
+
class SmartValueSetMemoryStore extends SmartValueSetStore {
|
|
4355
|
+
constructor() {
|
|
4356
|
+
super();
|
|
4357
|
+
this.viewService = inject(ViewService);
|
|
4358
|
+
/** The view context service injects the store, so it is looked up at use. */
|
|
4359
|
+
this.injector = inject(Injector);
|
|
4360
|
+
this.sizeLimit = inject(SMART_NG_CLIENT_CONFIG).valueSetStoreSize;
|
|
4361
|
+
this.changeSource = new Subject();
|
|
4362
|
+
this.changes = this.changeSource.asObservable();
|
|
4363
|
+
/** In the order of their last write, the least recently written first. */
|
|
4364
|
+
this.explicitEntries = new Map();
|
|
4365
|
+
/** The entries of each view by key. */
|
|
4366
|
+
this.viewEntries = new Map();
|
|
4367
|
+
/** The closed views the view context still lists; a late model write of one is not taken. */
|
|
4368
|
+
this.closedViewUuids = new Set();
|
|
4369
|
+
/** The selections the widgets of each open view read through, by the name of the set. */
|
|
4370
|
+
this.viewSelections = new Map();
|
|
4371
|
+
/** The keys of the explicit sets the `label` pipe of each open view read by name. */
|
|
4372
|
+
this.readExplicitKeys = new Map();
|
|
4373
|
+
/** The number of subscribers of {@link get} to each explicit set. */
|
|
4374
|
+
this.subscriberCounts = new Map();
|
|
4375
|
+
/** The version of each branch item of the version maps, by its explicit key. */
|
|
4376
|
+
this.branchVersions = new Map();
|
|
4377
|
+
/** The fetches of each entry, by its explicit or implicit key. */
|
|
4378
|
+
this.fetchRecords = new Map();
|
|
4379
|
+
/** Numbers the fetches in the order they start. */
|
|
4380
|
+
this.fetchSequence = 0;
|
|
4381
|
+
/** Stepped by {@link clear}; the answer of a fetch started before is dropped. */
|
|
4382
|
+
this.epoch = 0;
|
|
4383
|
+
/** The number of holds {@link holdFetches} gave out and not yet released. */
|
|
4384
|
+
this.holdCount = 0;
|
|
4385
|
+
/** The sets waiting for the next fetch, by backend module. */
|
|
4386
|
+
this.pendingFetches = new Map();
|
|
4387
|
+
// The sets are resolved in the session locale; the session reports it at every initialize.
|
|
4388
|
+
const session = inject(SmartSessionService);
|
|
4389
|
+
let locale = session.sessionInfoData?.locale;
|
|
4390
|
+
session.localeChanged.subscribe(() => {
|
|
4391
|
+
const previousLocale = locale;
|
|
4392
|
+
locale = session.sessionInfoData?.locale;
|
|
4393
|
+
if (previousLocale !== undefined && previousLocale !== locale) {
|
|
4394
|
+
this.clear();
|
|
4395
|
+
}
|
|
4396
|
+
});
|
|
4397
|
+
}
|
|
4398
|
+
get(module, namespace, name) {
|
|
4399
|
+
const key = createExplicitKey(module, namespace, name);
|
|
4400
|
+
return defer(() => {
|
|
4401
|
+
this.subscriberCounts.set(key, (this.subscriberCounts.get(key) ?? 0) + 1);
|
|
4402
|
+
return this.followChanges(name, () => this.explicitEntries.get(key)?.data);
|
|
4403
|
+
}).pipe(finalize(() => this.releaseSubscriber(key)));
|
|
4404
|
+
}
|
|
4405
|
+
getImplicit(viewUuid, key) {
|
|
4406
|
+
return this.followChanges(key, () => {
|
|
4407
|
+
const entry = this.viewEntries.get(viewUuid)?.get(key);
|
|
4408
|
+
return entry?.implicit ? entry.data : undefined;
|
|
4409
|
+
});
|
|
4410
|
+
}
|
|
4411
|
+
getForSelection(viewUuid, selection) {
|
|
4412
|
+
return defer(() => {
|
|
4413
|
+
this.registerSelection(viewUuid, selection);
|
|
4414
|
+
return this.followChanges(selection.valueSetName, () => this.findForSelection(viewUuid, selection));
|
|
4415
|
+
});
|
|
4416
|
+
}
|
|
4417
|
+
findByName(viewUuid, name) {
|
|
4418
|
+
const module = this.findViewModule(viewUuid);
|
|
4419
|
+
const selection = this.viewSelections.get(viewUuid)?.get(name) ?? {
|
|
4420
|
+
valueSetNamespace: this.findLastWrittenNamespace(module, name),
|
|
4421
|
+
valueSetName: name,
|
|
4422
|
+
};
|
|
4423
|
+
const data = this.findForSelection(viewUuid, selection);
|
|
4424
|
+
if (data && !this.viewEntries.get(viewUuid)?.get(name)?.implicit) {
|
|
4425
|
+
this.registerExplicitRead(viewUuid, createExplicitKey(module, selection.valueSetNamespace, name));
|
|
4426
|
+
}
|
|
4427
|
+
return data;
|
|
4428
|
+
}
|
|
4429
|
+
putImplicit(viewUuid, valueSets) {
|
|
4430
|
+
if (this.closedViewUuids.has(viewUuid)) {
|
|
4431
|
+
return;
|
|
4432
|
+
}
|
|
4433
|
+
let isFetchPending = false;
|
|
4434
|
+
Object.entries(valueSets ?? {}).forEach(([key, valueSet]) => {
|
|
4435
|
+
if (!valueSet) {
|
|
4436
|
+
return;
|
|
4437
|
+
}
|
|
4438
|
+
const held = this.viewEntries.get(viewUuid)?.get(key);
|
|
4439
|
+
const extras = {
|
|
4440
|
+
extraValues: valueSet.extraValues,
|
|
4441
|
+
excludedKeys: valueSet.excludedKeys,
|
|
4442
|
+
};
|
|
4443
|
+
// A version alone keeps the values held on screen until the fetch brings the new ones.
|
|
4444
|
+
const next = !valueSet.valueSetData && valueSet.version && held?.implicit
|
|
4445
|
+
? { ...held, ...extras }
|
|
4446
|
+
: {
|
|
4447
|
+
implicit: !!(valueSet.valueSetData || valueSet.version),
|
|
4448
|
+
version: valueSet.valueSetData ? valueSet.version : undefined,
|
|
4449
|
+
data: valueSet.valueSetData,
|
|
4450
|
+
...extras,
|
|
4451
|
+
};
|
|
4452
|
+
if (!deepEqual(held, next)) {
|
|
4453
|
+
this.writeViewEntry(viewUuid, key, next);
|
|
4454
|
+
}
|
|
4455
|
+
const entryKey = createImplicitKey(viewUuid, key);
|
|
4456
|
+
if (!valueSet.valueSetData &&
|
|
4457
|
+
valueSet.version &&
|
|
4458
|
+
valueSet.version !== next.version &&
|
|
4459
|
+
!this.isFetching(entryKey, valueSet.version)) {
|
|
4460
|
+
this.markFetching(entryKey, valueSet.version);
|
|
4461
|
+
this.queueImplicitItem(viewUuid, key);
|
|
4462
|
+
isFetchPending = true;
|
|
4463
|
+
}
|
|
4464
|
+
});
|
|
4465
|
+
if (isFetchPending) {
|
|
4466
|
+
this.scheduleFlush().catch((err) => console.error("implicit value set fetch failed", err));
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
removeView(viewUuid) {
|
|
4470
|
+
// Only the views the view context still lists are kept, so the set does not grow with the tab.
|
|
4471
|
+
const listedViewUuids = new Set(this.injector
|
|
4472
|
+
.get(SmartViewContextService)
|
|
4473
|
+
.getCurrentViewContext()
|
|
4474
|
+
?.views?.map((view) => view.uuid));
|
|
4475
|
+
this.closedViewUuids.forEach((uuid) => {
|
|
4476
|
+
if (!listedViewUuids.has(uuid)) {
|
|
4477
|
+
this.closedViewUuids.delete(uuid);
|
|
4478
|
+
}
|
|
4479
|
+
});
|
|
4480
|
+
this.closedViewUuids.add(viewUuid);
|
|
4481
|
+
this.viewSelections.delete(viewUuid);
|
|
4482
|
+
this.readExplicitKeys.delete(viewUuid);
|
|
4483
|
+
this.pendingFetches.forEach((pending) => {
|
|
4484
|
+
pending.items = pending.items.filter((item) => item.implicitViewUuid !== viewUuid);
|
|
4485
|
+
});
|
|
4486
|
+
const entries = this.viewEntries.get(viewUuid);
|
|
4487
|
+
if (!entries) {
|
|
4488
|
+
return;
|
|
4489
|
+
}
|
|
4490
|
+
this.viewEntries.delete(viewUuid);
|
|
4491
|
+
entries.forEach((_, key) => {
|
|
4492
|
+
this.fetchRecords.delete(createImplicitKey(viewUuid, key));
|
|
4493
|
+
this.changeSource.next(key);
|
|
4494
|
+
});
|
|
4495
|
+
}
|
|
4496
|
+
holdFetches() {
|
|
4497
|
+
this.holdCount++;
|
|
4498
|
+
return () => {
|
|
4499
|
+
this.holdCount--;
|
|
4500
|
+
if (!this.holdCount) {
|
|
4501
|
+
this.flushFetches();
|
|
4502
|
+
}
|
|
4503
|
+
};
|
|
4504
|
+
}
|
|
4505
|
+
applyVersions(viewContextChange, viewUuid) {
|
|
4506
|
+
const versions = viewContextChange?.valueSetVersions;
|
|
4507
|
+
const requestViewUuid = viewUuid ?? viewContextChange?.changes?.[0]?.uuid;
|
|
4508
|
+
if (!versions?.length || !requestViewUuid) {
|
|
4509
|
+
return Promise.resolve();
|
|
4510
|
+
}
|
|
4511
|
+
const module = this.findViewModule(requestViewUuid);
|
|
4512
|
+
const readKeys = this.collectReadExplicitKeys();
|
|
4513
|
+
let isFetchPending = false;
|
|
4514
|
+
/** The version noted before and the one noted now of each branch item queued for a fetch. */
|
|
4515
|
+
const notedBranchVersions = new Map();
|
|
4516
|
+
versions.forEach((version) => {
|
|
4517
|
+
const key = createExplicitKey(module, version.namespace, version.name, version.branchUri);
|
|
4518
|
+
if (version.branchUri) {
|
|
4519
|
+
const previous = this.branchVersions.get(key);
|
|
4520
|
+
this.branchVersions.set(key, version.version);
|
|
4521
|
+
if (previous === undefined || previous === version.version) {
|
|
4522
|
+
return;
|
|
4523
|
+
}
|
|
4524
|
+
const holders = this.findViewsHoldingImplicitly(module, version.name);
|
|
4525
|
+
if (!holders.length) {
|
|
4526
|
+
return;
|
|
4527
|
+
}
|
|
4528
|
+
holders.forEach((holder) => this.queueImplicitItem(holder, version.name));
|
|
4529
|
+
notedBranchVersions.set(key, [previous, version.version]);
|
|
4530
|
+
isFetchPending = true;
|
|
4531
|
+
return;
|
|
4532
|
+
}
|
|
4533
|
+
const held = this.explicitEntries.get(key)?.version;
|
|
4534
|
+
if (held === version.version ||
|
|
4535
|
+
this.isFetching(key, version.version) ||
|
|
4536
|
+
this.isHeldOnlyImplicitly(module, key, version.name, readKeys)) {
|
|
4537
|
+
return;
|
|
4538
|
+
}
|
|
4539
|
+
this.markFetching(key, version.version);
|
|
4540
|
+
this.queueItem(module, requestViewUuid, {
|
|
4541
|
+
namespace: version.namespace,
|
|
4542
|
+
name: version.name,
|
|
4543
|
+
branchUri: version.branchUri,
|
|
4544
|
+
version: held,
|
|
4545
|
+
});
|
|
4546
|
+
isFetchPending = true;
|
|
4547
|
+
});
|
|
4548
|
+
if (!isFetchPending) {
|
|
4549
|
+
return Promise.resolve();
|
|
4550
|
+
}
|
|
4551
|
+
const flush = this.scheduleFlush();
|
|
4552
|
+
// A branch version whose fetch failed is taken back, so the next map fetches again.
|
|
4553
|
+
flush.catch(() => notedBranchVersions.forEach(([previous, noted], key) => {
|
|
4554
|
+
if (this.branchVersions.get(key) === noted) {
|
|
4555
|
+
this.branchVersions.set(key, previous);
|
|
4556
|
+
}
|
|
4557
|
+
}));
|
|
4558
|
+
return flush;
|
|
4559
|
+
}
|
|
4560
|
+
fetch(module, viewUuid, items) {
|
|
4561
|
+
if (!items.length) {
|
|
4562
|
+
return Promise.resolve();
|
|
4563
|
+
}
|
|
4564
|
+
items.forEach((item) => this.queueItem(module ?? "", viewUuid, item));
|
|
4565
|
+
return this.scheduleFlush();
|
|
4566
|
+
}
|
|
4567
|
+
clear() {
|
|
4568
|
+
const readKeys = this.collectReadExplicitKeys();
|
|
4569
|
+
const entries = [...this.explicitEntries];
|
|
4570
|
+
this.explicitEntries.clear();
|
|
4571
|
+
this.fetchRecords.clear();
|
|
4572
|
+
this.epoch++;
|
|
4573
|
+
// A set fetched again is marked in the version it had, so a change naming it asks nothing.
|
|
4574
|
+
entries.forEach(([key, entry]) => {
|
|
4575
|
+
const { module, namespace, name, branchUri } = parseExplicitKey(key);
|
|
4576
|
+
if (readKeys.has(key)) {
|
|
4577
|
+
this.markFetching(key, entry.version);
|
|
4578
|
+
this.queueItem(module, entry.viewUuid, { namespace, name, branchUri });
|
|
4579
|
+
}
|
|
4580
|
+
this.changeSource.next(name);
|
|
4581
|
+
});
|
|
4582
|
+
this.viewEntries.forEach((entries, viewUuid) => entries.forEach((held, key) => {
|
|
4583
|
+
if (held.implicit) {
|
|
4584
|
+
this.markFetching(createImplicitKey(viewUuid, key), held.version);
|
|
4585
|
+
this.writeViewEntry(viewUuid, key, { ...held, version: undefined, data: undefined });
|
|
4586
|
+
this.queueImplicitItem(viewUuid, key);
|
|
4587
|
+
}
|
|
4588
|
+
}));
|
|
4589
|
+
if (this.pendingFetches.size) {
|
|
4590
|
+
this.scheduleFlush().catch((err) => console.error("value set fetch failed", err));
|
|
4591
|
+
}
|
|
4592
|
+
}
|
|
4593
|
+
/** Queues the item for the fetch of the module, which goes through the first view queued. */
|
|
4594
|
+
queueItem(module, viewUuid, item) {
|
|
4595
|
+
const pending = this.pendingFetches.get(module) ?? { viewUuid, items: [] };
|
|
4596
|
+
pending.items.push(item);
|
|
4597
|
+
this.pendingFetches.set(module, pending);
|
|
4598
|
+
}
|
|
4599
|
+
queueImplicitItem(viewUuid, key) {
|
|
4600
|
+
const module = this.findViewModule(viewUuid);
|
|
4601
|
+
const isQueued = this.pendingFetches
|
|
4602
|
+
.get(module)
|
|
4603
|
+
?.items.some((item) => item.implicitViewUuid === viewUuid && item.name === key);
|
|
4604
|
+
if (!isQueued) {
|
|
4605
|
+
this.queueItem(module, viewUuid, { name: key, implicitViewUuid: viewUuid });
|
|
4606
|
+
}
|
|
4607
|
+
}
|
|
4608
|
+
/** The promise of the fetches waiting, sent now or when the last hold is released. */
|
|
4609
|
+
scheduleFlush() {
|
|
4610
|
+
if (!this.pendingFlush) {
|
|
4611
|
+
let resolve;
|
|
4612
|
+
let reject;
|
|
4613
|
+
const promise = new Promise((res, rej) => {
|
|
4614
|
+
resolve = res;
|
|
4615
|
+
reject = rej;
|
|
4616
|
+
});
|
|
4617
|
+
this.pendingFlush = { promise, resolve, reject };
|
|
4618
|
+
}
|
|
4619
|
+
const promise = this.pendingFlush.promise;
|
|
4620
|
+
if (!this.holdCount) {
|
|
4621
|
+
this.flushFetches();
|
|
4622
|
+
}
|
|
4623
|
+
return promise;
|
|
4624
|
+
}
|
|
4625
|
+
/** Sends the items waiting, one Value Set Fetch per backend module. */
|
|
4626
|
+
flushFetches() {
|
|
4627
|
+
const flush = this.pendingFlush;
|
|
4628
|
+
if (!flush) {
|
|
4629
|
+
return;
|
|
4630
|
+
}
|
|
4631
|
+
this.pendingFlush = undefined;
|
|
4632
|
+
const pendingFetches = [...this.pendingFetches];
|
|
4633
|
+
this.pendingFetches = new Map();
|
|
4634
|
+
Promise.all(pendingFetches.map(([module, pending]) => this.sendFetch(module, pending))).then(() => flush.resolve(), (err) => flush.reject(err));
|
|
4635
|
+
}
|
|
4636
|
+
/**
|
|
4637
|
+
* One Value Set Fetch of a module through its view, each answer written to the set of its item.
|
|
4638
|
+
* An implicit set asks with the version its view holds.
|
|
4639
|
+
*/
|
|
4640
|
+
async sendFetch(module, pending) {
|
|
4641
|
+
const epoch = this.epoch;
|
|
4642
|
+
const sent = pending.items.map((item) => {
|
|
4643
|
+
const entryKey = item.implicitViewUuid
|
|
4644
|
+
? createImplicitKey(item.implicitViewUuid, item.name)
|
|
4645
|
+
: createExplicitKey(module, item.namespace, item.name, item.branchUri);
|
|
4646
|
+
return {
|
|
4647
|
+
item: item.implicitViewUuid
|
|
4648
|
+
? {
|
|
4649
|
+
...item,
|
|
4650
|
+
version: this.viewEntries.get(item.implicitViewUuid)?.get(item.name)?.version,
|
|
4651
|
+
}
|
|
4652
|
+
: item,
|
|
4653
|
+
entryKey,
|
|
4654
|
+
fetchingVersion: this.fetchRecords.get(entryKey)?.fetchingVersion,
|
|
4655
|
+
};
|
|
4656
|
+
});
|
|
4657
|
+
try {
|
|
4658
|
+
if (!sent.length) {
|
|
4659
|
+
return;
|
|
4660
|
+
}
|
|
4661
|
+
const sequence = ++this.fetchSequence;
|
|
4662
|
+
const response = await lastValueFrom(this.viewService.fetchValueSets(pending.viewUuid, { items: sent.map(({ item }) => item) }));
|
|
4663
|
+
if (epoch !== this.epoch) {
|
|
4664
|
+
return;
|
|
4665
|
+
}
|
|
4666
|
+
response?.items?.forEach((result, index) => {
|
|
4667
|
+
const { item, entryKey } = sent[index];
|
|
4668
|
+
if (item.implicitViewUuid) {
|
|
4669
|
+
this.writeImplicitResult(item.implicitViewUuid, item.name, result, sequence);
|
|
4670
|
+
}
|
|
4671
|
+
else {
|
|
4672
|
+
this.writeExplicitResult(entryKey, item.name, result, pending.viewUuid, sequence);
|
|
4673
|
+
}
|
|
4674
|
+
});
|
|
4675
|
+
this.evictExplicitEntries();
|
|
4676
|
+
}
|
|
4677
|
+
finally {
|
|
4678
|
+
// A later change may start a newer fetch of an entry meanwhile; only this one's mark ends.
|
|
4679
|
+
sent.forEach(({ entryKey, fetchingVersion }) => {
|
|
4680
|
+
const record = this.fetchRecords.get(entryKey);
|
|
4681
|
+
const isMarkOfThisFetch = fetchingVersion && record?.fetchingVersion === fetchingVersion;
|
|
4682
|
+
if (epoch === this.epoch && isMarkOfThisFetch) {
|
|
4683
|
+
record.fetchingVersion = undefined;
|
|
4684
|
+
}
|
|
4685
|
+
});
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
writeExplicitResult(key, name, result, viewUuid, sequence) {
|
|
4689
|
+
if (!this.checkAndRecordWrite(key, sequence)) {
|
|
4690
|
+
return;
|
|
4691
|
+
}
|
|
4692
|
+
const held = this.explicitEntries.get(key);
|
|
4693
|
+
if (result.valueSetData) {
|
|
4694
|
+
this.writeExplicitEntry(key, name, {
|
|
4695
|
+
version: result.version,
|
|
4696
|
+
data: result.valueSetData,
|
|
4697
|
+
viewUuid,
|
|
4698
|
+
});
|
|
4699
|
+
}
|
|
4700
|
+
else if (held && (held.version !== result.version || held.viewUuid !== viewUuid)) {
|
|
4701
|
+
this.writeExplicitEntry(key, name, { ...held, version: result.version, viewUuid });
|
|
4702
|
+
}
|
|
4703
|
+
}
|
|
4704
|
+
/** Values are the new version, a version alone is the one held, no version is a set gone. */
|
|
4705
|
+
writeImplicitResult(viewUuid, key, result, sequence) {
|
|
4706
|
+
// The entries of a view closed meanwhile are gone and stay so.
|
|
4707
|
+
const held = this.viewEntries.get(viewUuid)?.get(key);
|
|
4708
|
+
if (!held || !this.checkAndRecordWrite(createImplicitKey(viewUuid, key), sequence)) {
|
|
4709
|
+
return;
|
|
4710
|
+
}
|
|
4711
|
+
if (result.valueSetData || !result.version) {
|
|
4712
|
+
this.writeViewEntry(viewUuid, key, {
|
|
4713
|
+
...held,
|
|
4714
|
+
implicit: true,
|
|
4715
|
+
version: result.version,
|
|
4716
|
+
data: result.valueSetData,
|
|
4717
|
+
});
|
|
4718
|
+
}
|
|
4719
|
+
}
|
|
4720
|
+
/**
|
|
4721
|
+
* Whether nothing reads the explicit set and a view of the module holds it as its implicit set
|
|
4722
|
+
* of the name, read by a selection in the set's namespace.
|
|
4723
|
+
*/
|
|
4724
|
+
isHeldOnlyImplicitly(module, key, name, readKeys) {
|
|
4725
|
+
return (!readKeys.has(key) &&
|
|
4726
|
+
this.findViewsHoldingImplicitly(module, name).some((viewUuid) => {
|
|
4727
|
+
const selection = this.viewSelections.get(viewUuid)?.get(name);
|
|
4728
|
+
return (!!selection && createExplicitKey(module, selection.valueSetNamespace, name) === key);
|
|
4729
|
+
}));
|
|
4730
|
+
}
|
|
4731
|
+
/** The views of the module holding an implicit set under the name. */
|
|
4732
|
+
findViewsHoldingImplicitly(module, name) {
|
|
4733
|
+
return [...this.viewEntries]
|
|
4734
|
+
.filter(([viewUuid, entries]) => entries.get(name)?.implicit && this.findViewModule(viewUuid) === module)
|
|
4735
|
+
.map(([viewUuid]) => viewUuid);
|
|
4736
|
+
}
|
|
4737
|
+
/**
|
|
4738
|
+
* The keys of the explicit sets something reads: a selection of an open view whose view holds
|
|
4739
|
+
* no implicit set of the name, the `label` pipe of an open view, or a subscriber of {@link get}.
|
|
4740
|
+
*/
|
|
4741
|
+
collectReadExplicitKeys() {
|
|
4742
|
+
const keys = new Set(this.subscriberCounts.keys());
|
|
4743
|
+
this.readExplicitKeys.forEach((viewKeys) => viewKeys.forEach((key) => keys.add(key)));
|
|
4744
|
+
this.viewSelections.forEach((selections, viewUuid) => {
|
|
4745
|
+
const module = this.findViewModule(viewUuid);
|
|
4746
|
+
selections.forEach((selection, name) => {
|
|
4747
|
+
if (!this.viewEntries.get(viewUuid)?.get(name)?.implicit) {
|
|
4748
|
+
keys.add(createExplicitKey(module, selection.valueSetNamespace, name));
|
|
4749
|
+
}
|
|
4750
|
+
});
|
|
4751
|
+
});
|
|
4752
|
+
return keys;
|
|
4753
|
+
}
|
|
4754
|
+
releaseSubscriber(key) {
|
|
4755
|
+
const count = this.subscriberCounts.get(key) - 1;
|
|
4756
|
+
if (count) {
|
|
4757
|
+
this.subscriberCounts.set(key, count);
|
|
4758
|
+
}
|
|
4759
|
+
else {
|
|
4760
|
+
this.subscriberCounts.delete(key);
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4763
|
+
registerSelection(viewUuid, selection) {
|
|
4764
|
+
if (this.closedViewUuids.has(viewUuid)) {
|
|
4765
|
+
return;
|
|
4766
|
+
}
|
|
4767
|
+
const selections = this.viewSelections.get(viewUuid) ?? new Map();
|
|
4768
|
+
selections.set(selection.valueSetName, selection);
|
|
4769
|
+
this.viewSelections.set(viewUuid, selections);
|
|
4770
|
+
}
|
|
4771
|
+
registerExplicitRead(viewUuid, key) {
|
|
4772
|
+
if (this.closedViewUuids.has(viewUuid)) {
|
|
4773
|
+
return;
|
|
4774
|
+
}
|
|
4775
|
+
const keys = this.readExplicitKeys.get(viewUuid) ?? new Set();
|
|
4776
|
+
keys.add(key);
|
|
4777
|
+
this.readExplicitKeys.set(viewUuid, keys);
|
|
4778
|
+
}
|
|
4779
|
+
/** The namespace of the explicit set of the name in the module written last. */
|
|
4780
|
+
findLastWrittenNamespace(module, name) {
|
|
4781
|
+
let namespace;
|
|
4782
|
+
this.explicitEntries.forEach((_, key) => {
|
|
4783
|
+
const parsed = parseExplicitKey(key);
|
|
4784
|
+
if (parsed.module === module && parsed.name === name) {
|
|
4785
|
+
namespace = parsed.namespace;
|
|
4786
|
+
}
|
|
4787
|
+
});
|
|
4788
|
+
return namespace;
|
|
4789
|
+
}
|
|
4790
|
+
isFetching(entryKey, version) {
|
|
4791
|
+
return this.fetchRecords.get(entryKey)?.fetchingVersion === version;
|
|
4792
|
+
}
|
|
4793
|
+
markFetching(entryKey, version) {
|
|
4794
|
+
const record = this.fetchRecords.get(entryKey) ?? { writtenSequence: 0 };
|
|
4795
|
+
record.fetchingVersion = version;
|
|
4796
|
+
this.fetchRecords.set(entryKey, record);
|
|
4797
|
+
}
|
|
4798
|
+
/**
|
|
4799
|
+
* Records the fetch as the last writer of the entry, unless a later fetch wrote it already.
|
|
4800
|
+
*
|
|
4801
|
+
* @returns whether the answer of the fetch may write the entry.
|
|
4802
|
+
*/
|
|
4803
|
+
checkAndRecordWrite(entryKey, sequence) {
|
|
4804
|
+
const record = this.fetchRecords.get(entryKey) ?? { writtenSequence: 0 };
|
|
4805
|
+
if (record.writtenSequence > sequence) {
|
|
4806
|
+
return false;
|
|
4807
|
+
}
|
|
4808
|
+
record.writtenSequence = sequence;
|
|
4809
|
+
this.fetchRecords.set(entryKey, record);
|
|
4810
|
+
return true;
|
|
4811
|
+
}
|
|
4812
|
+
/** Drops the least recently written sets nothing reads beyond the count limit. */
|
|
4813
|
+
evictExplicitEntries() {
|
|
4814
|
+
const readKeys = this.collectReadExplicitKeys();
|
|
4815
|
+
let count = this.explicitEntries.size;
|
|
4816
|
+
for (const key of [...this.explicitEntries.keys()]) {
|
|
4817
|
+
if (count <= this.sizeLimit) {
|
|
4818
|
+
return;
|
|
4819
|
+
}
|
|
4820
|
+
if (!readKeys.has(key)) {
|
|
4821
|
+
this.explicitEntries.delete(key);
|
|
4822
|
+
this.fetchRecords.delete(key);
|
|
4823
|
+
count--;
|
|
4824
|
+
}
|
|
4825
|
+
}
|
|
4826
|
+
}
|
|
4827
|
+
/** The values a widget of the view lists for its selection, see {@link getForSelection}. */
|
|
4828
|
+
findForSelection(viewUuid, selection) {
|
|
4829
|
+
const viewEntry = this.viewEntries.get(viewUuid)?.get(selection.valueSetName);
|
|
4830
|
+
// An implicit set of the view wins: the explicit one is not read.
|
|
4831
|
+
const data = viewEntry?.implicit
|
|
4832
|
+
? viewEntry.data
|
|
4833
|
+
: this.explicitEntries.get(createExplicitKey(this.findViewModule(viewUuid), selection.valueSetNamespace, selection.valueSetName))?.data;
|
|
4834
|
+
return data && this.mergeViewExtras(data, viewEntry, selection);
|
|
4835
|
+
}
|
|
4836
|
+
mergeViewExtras(data, viewEntry, selection) {
|
|
4837
|
+
return viewEntry?.extraValues?.length || viewEntry?.excludedKeys?.length
|
|
4838
|
+
? mergeExtraValues(data, viewEntry, selection)
|
|
4839
|
+
: data;
|
|
4840
|
+
}
|
|
4841
|
+
/** Emits the values the read gives now and again whenever the store writes a set of the name. */
|
|
4842
|
+
followChanges(name, read) {
|
|
4843
|
+
return this.changes.pipe(filter((changed) => changed === name), startWith(name), map(read), distinctUntilChanged(deepEqual));
|
|
4844
|
+
}
|
|
4845
|
+
/** The module a view is served by; the empty string stands for the session's own backend. */
|
|
4846
|
+
findViewModule(viewUuid) {
|
|
4847
|
+
return (this.injector
|
|
4848
|
+
.get(SmartViewContextService)
|
|
4849
|
+
.getCurrentViewContext()
|
|
4850
|
+
?.views?.find((view) => view.uuid === viewUuid)?.module ?? "");
|
|
4851
|
+
}
|
|
4852
|
+
/** Writes the explicit entry as the most recently written one. */
|
|
4853
|
+
writeExplicitEntry(key, name, entry) {
|
|
4854
|
+
this.explicitEntries.delete(key);
|
|
4855
|
+
this.explicitEntries.set(key, entry);
|
|
4856
|
+
this.changeSource.next(name);
|
|
4857
|
+
}
|
|
4858
|
+
writeViewEntry(viewUuid, key, entry) {
|
|
4859
|
+
const entries = this.viewEntries.get(viewUuid) ?? new Map();
|
|
4860
|
+
entries.set(key, entry);
|
|
4861
|
+
this.viewEntries.set(viewUuid, entries);
|
|
4862
|
+
this.changeSource.next(key);
|
|
4863
|
+
}
|
|
4864
|
+
}
|
|
4865
|
+
/**
|
|
4866
|
+
* The set without the values whose text at the set's key property is an excluded key, then the
|
|
4867
|
+
* view's extras keyed by their code under the selection's key property, unless the set has the key.
|
|
4868
|
+
*/
|
|
4869
|
+
function mergeExtraValues(data, extras, selection) {
|
|
4870
|
+
const values = data.values ?? [];
|
|
4871
|
+
const keyProperty = valueSetKeyProperty(values, selection.keyProperty ?? data.keyProperty);
|
|
4872
|
+
const displayProperty = valueSetDisplayProperty(values, selection.displayProperty);
|
|
4873
|
+
const excludedKeys = new Set(extras.excludedKeys ?? []);
|
|
4874
|
+
const keptValues = values.filter((value) => {
|
|
4875
|
+
const key = data.keyProperty ? value?.[data.keyProperty] : undefined;
|
|
4876
|
+
return key === undefined || key === null || !excludedKeys.has(String(key));
|
|
4877
|
+
});
|
|
4878
|
+
const keys = new Set(keptValues.map((value) => convertKeyToText(value?.[keyProperty])));
|
|
4879
|
+
const extraValues = (extras.extraValues ?? [])
|
|
4880
|
+
.filter((extra) => extra.code !== undefined && !keys.has(extra.code))
|
|
4881
|
+
.map((extra) => ({
|
|
4882
|
+
...extra,
|
|
4883
|
+
[keyProperty]: extra.code,
|
|
4884
|
+
[displayProperty]: extra.displayValue,
|
|
4885
|
+
}));
|
|
4886
|
+
return { ...data, values: [...keptValues, ...extraValues] };
|
|
4887
|
+
}
|
|
4888
|
+
function convertKeyToText(key) {
|
|
4889
|
+
return key === undefined || key === null ? undefined : String(key);
|
|
4890
|
+
}
|
|
4891
|
+
function createExplicitKey(module, namespace, name, branchUri) {
|
|
4892
|
+
return JSON.stringify([module ?? "", namespace ?? "", name, branchUri ?? ""]);
|
|
4893
|
+
}
|
|
4894
|
+
/** The parts of an explicit key, an empty namespace or branch as undefined. */
|
|
4895
|
+
function parseExplicitKey(key) {
|
|
4896
|
+
const [module, namespace, name, branchUri] = JSON.parse(key);
|
|
4897
|
+
return {
|
|
4898
|
+
module,
|
|
4899
|
+
namespace: namespace || undefined,
|
|
4900
|
+
name,
|
|
4901
|
+
branchUri: branchUri || undefined,
|
|
4902
|
+
};
|
|
4903
|
+
}
|
|
4904
|
+
function createImplicitKey(viewUuid, key) {
|
|
4905
|
+
return JSON.stringify([viewUuid, key]);
|
|
4906
|
+
}
|
|
4907
|
+
|
|
4231
4908
|
class SmartNavigationService {
|
|
4232
4909
|
constructor() { }
|
|
4233
4910
|
subscribeToUrlChange(callback) {
|
|
@@ -7086,31 +7763,6 @@ var ValueChangeMode;
|
|
|
7086
7763
|
ValueChangeMode["BLUR"] = "BLUR";
|
|
7087
7764
|
})(ValueChangeMode || (ValueChangeMode = {}));
|
|
7088
7765
|
|
|
7089
|
-
/**
|
|
7090
|
-
* The key and display property of a valueSet's values: the preferred name if the values carry it,
|
|
7091
|
-
* then the GenericValue name (`uri` / `name`), then the Value name (`objectUri` / `displayValue`).
|
|
7092
|
-
* With no sample value to look at the preferred name is assumed to exist.
|
|
7093
|
-
*/
|
|
7094
|
-
function valueSetKeyProperty(values, preferred) {
|
|
7095
|
-
return firstExisting(values, [preferred ?? 'objectUri', 'uri', 'objectUri']);
|
|
7096
|
-
}
|
|
7097
|
-
function valueSetDisplayProperty(values, preferred) {
|
|
7098
|
-
return firstExisting(values, [preferred ?? 'displayValue', 'name', 'displayValue']);
|
|
7099
|
-
}
|
|
7100
|
-
/** The label of a code in a valueSet, or undefined when the valueSet does not know the code. */
|
|
7101
|
-
function valueSetLabelOf(valueSet, code) {
|
|
7102
|
-
const values = valueSet.valueSetData?.values ?? [];
|
|
7103
|
-
const keyProperty = valueSetKeyProperty(values, valueSet.valueSetData?.keyProperty);
|
|
7104
|
-
const hit = values.find((value) => String(value[keyProperty]) === String(code));
|
|
7105
|
-
return hit?.[valueSetDisplayProperty(values)];
|
|
7106
|
-
}
|
|
7107
|
-
function firstExisting(values, candidates) {
|
|
7108
|
-
if (!values?.length) {
|
|
7109
|
-
return candidates[0];
|
|
7110
|
-
}
|
|
7111
|
-
return candidates.find((c) => c in values[0]) ?? candidates[candidates.length - 1];
|
|
7112
|
-
}
|
|
7113
|
-
|
|
7114
7766
|
const EMPTY_PARAMS = {};
|
|
7115
7767
|
const NAMED_VALIDATOR = new InjectionToken('Named validator factory');
|
|
7116
7768
|
|
|
@@ -7223,6 +7875,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
7223
7875
|
class SmartFormService {
|
|
7224
7876
|
constructor() {
|
|
7225
7877
|
this.validatorProvider = inject(NamedValidatorService, { optional: true });
|
|
7878
|
+
/** Looks up the value set store at use: a form without a view does not need it. */
|
|
7879
|
+
this.injector = inject(Injector);
|
|
7226
7880
|
this.revisionState = signal(0, /* @ts-ignore */
|
|
7227
7881
|
...(ngDevMode ? [{ debugName: "revisionState" }] : /* istanbul ignore next */ []));
|
|
7228
7882
|
/**
|
|
@@ -7247,6 +7901,8 @@ class SmartFormService {
|
|
|
7247
7901
|
* says nothing about what the data holds.
|
|
7248
7902
|
*/
|
|
7249
7903
|
this.exchanged = new Map();
|
|
7904
|
+
/** The values each selection widget's `valueList` was last filled from. */
|
|
7905
|
+
this.filledValueSets = new WeakMap();
|
|
7250
7906
|
this.regexRegexChars = new RegExp(/[\.\-\[\]\/\{\}\(\)\+\^\$\\\|]/g);
|
|
7251
7907
|
this.regexAsteriskInTheMiddle = new RegExp(/([^\*])\*([^\*])/g);
|
|
7252
7908
|
this.regexAsteriskInTheEnd = new RegExp(/([^\*])\*$/g);
|
|
@@ -7405,7 +8061,7 @@ class SmartFormService {
|
|
|
7405
8061
|
// The backend changed this field: its value reaches the control even over an edit.
|
|
7406
8062
|
this.group[key]?.setValue(value ?? '', { emitEvent: false });
|
|
7407
8063
|
}
|
|
7408
|
-
this.
|
|
8064
|
+
this.fillValueListFromValueSet(widget);
|
|
7409
8065
|
}
|
|
7410
8066
|
else {
|
|
7411
8067
|
// In case of CheckBox2
|
|
@@ -7413,62 +8069,113 @@ class SmartFormService {
|
|
|
7413
8069
|
splittedKeys.splice(splittedKeys.length - 1, 1);
|
|
7414
8070
|
widget = this.findSmartFormWidgetByKey(widgets, splittedKeys.join('.'));
|
|
7415
8071
|
if (widget && widget.type === SmartFormWidgetType.CHECK_BOX_2) {
|
|
7416
|
-
this.
|
|
7417
|
-
|
|
7418
|
-
widget.valueList = widget.valueList.map((item) => {
|
|
7419
|
-
let value = this.getValueDeeply(data, `${widget?.key}.${item.key}`);
|
|
7420
|
-
item.value = value;
|
|
7421
|
-
return item;
|
|
7422
|
-
});
|
|
7423
|
-
}
|
|
8072
|
+
this.fillValueListFromValueSet(widget);
|
|
8073
|
+
this.fillCheckBoxItemValues(widget, data);
|
|
7424
8074
|
}
|
|
7425
8075
|
}
|
|
7426
8076
|
}
|
|
7427
8077
|
}
|
|
7428
8078
|
}
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
8079
|
+
/**
|
|
8080
|
+
* Lists the values of a selection widget's value set each time the model writes the field, the
|
|
8081
|
+
* empty item of a SELECT included, also where a mandatory constraint removed it: the set of the
|
|
8082
|
+
* form's own component model, else the values the store last gave the widget.
|
|
8083
|
+
*/
|
|
8084
|
+
fillValueListFromValueSet(widget) {
|
|
8085
|
+
const valueSetData = this.findOwnValueSetData(widget) ?? this.filledValueSets.get(widget);
|
|
8086
|
+
if (valueSetData) {
|
|
8087
|
+
this.fillValueList(widget, valueSetData);
|
|
8088
|
+
}
|
|
8089
|
+
}
|
|
8090
|
+
/**
|
|
8091
|
+
* The set a selection widget's form carries in its own component model under the selection's
|
|
8092
|
+
* name: a form a host builds, or a delivery without the store. It wins over the store's.
|
|
8093
|
+
*/
|
|
8094
|
+
findOwnValueSetData(widget) {
|
|
8095
|
+
if (!isListedFromValueSet(widget)) {
|
|
8096
|
+
return undefined;
|
|
8097
|
+
}
|
|
8098
|
+
const name = widget.selection.valueSetName;
|
|
8099
|
+
return this.smartForm?.componentModel?.valueSets?.[name]?.valueSetData;
|
|
8100
|
+
}
|
|
8101
|
+
/**
|
|
8102
|
+
* The store's values for the selection widget in its view, emitted at once and at every new
|
|
8103
|
+
* version; nothing for a widget that lists no value set.
|
|
8104
|
+
*/
|
|
8105
|
+
observeValueSetData(widget, viewUuid) {
|
|
8106
|
+
if (!isListedFromValueSet(widget)) {
|
|
8107
|
+
return undefined;
|
|
8108
|
+
}
|
|
8109
|
+
return this.injector
|
|
8110
|
+
.get(SmartValueSetStore)
|
|
8111
|
+
.getForSelection(viewUuid, widget.selection);
|
|
8112
|
+
}
|
|
8113
|
+
/**
|
|
8114
|
+
* Lists the values the store gave the widget when they are not the ones listed, unless its form
|
|
8115
|
+
* carries its own; a checkbox group gets the values of its items from the data and a control for
|
|
8116
|
+
* each new item.
|
|
8117
|
+
*
|
|
8118
|
+
* @returns whether the widget lists new values.
|
|
8119
|
+
*/
|
|
8120
|
+
relistValueSet(widget, storeValueSetData, form) {
|
|
8121
|
+
const valueSetData = this.findOwnValueSetData(widget) ?? storeValueSetData;
|
|
8122
|
+
if (!valueSetData || deepEqual(this.filledValueSets.get(widget), valueSetData)) {
|
|
8123
|
+
return false;
|
|
8124
|
+
}
|
|
8125
|
+
this.fillValueList(widget, valueSetData);
|
|
8126
|
+
if (widget.type === SmartFormWidgetType.CHECK_BOX_2) {
|
|
8127
|
+
this.fillCheckBoxItemValues(widget, this.smartForm?.componentModel?.data);
|
|
8128
|
+
// The widget's form, not this service's controls: a host may give the widget its own form.
|
|
8129
|
+
widget.valueList.forEach((item) => {
|
|
8130
|
+
const key = `${widget.key}.${item.key}`;
|
|
8131
|
+
if (form && !form.controls[key]) {
|
|
8132
|
+
form.addControl(key, new UntypedFormControl({ value: item.value ?? '', disabled: !!widget.isDisabled }), { emitEvent: false });
|
|
7470
8133
|
}
|
|
7471
|
-
}
|
|
8134
|
+
});
|
|
8135
|
+
}
|
|
8136
|
+
return true;
|
|
8137
|
+
}
|
|
8138
|
+
/** Gives each item of a checkbox group its value from the data. */
|
|
8139
|
+
fillCheckBoxItemValues(widget, data) {
|
|
8140
|
+
widget.valueList = widget.valueList?.map((item) => {
|
|
8141
|
+
item.value = data ? this.getValueDeeply(data, `${widget.key}.${item.key}`) : undefined;
|
|
8142
|
+
return item;
|
|
8143
|
+
});
|
|
8144
|
+
}
|
|
8145
|
+
/**
|
|
8146
|
+
* Fills the `valueList` of a selection widget from the values of its value set, a SELECT with
|
|
8147
|
+
* the empty item; a constraint that makes the widget mandatory removes it.
|
|
8148
|
+
*/
|
|
8149
|
+
fillValueList(widget, valueSetData) {
|
|
8150
|
+
this.filledValueSets.set(widget, valueSetData);
|
|
8151
|
+
let values = valueSetData.values;
|
|
8152
|
+
let select = widget;
|
|
8153
|
+
let selection = select.selection;
|
|
8154
|
+
let displayProperty = valueSetDisplayProperty(values, selection.displayProperty);
|
|
8155
|
+
if (selection.type === SelectionDefinitionTypeEnum.PROPERTY &&
|
|
8156
|
+
!selection.mapping?.length) {
|
|
8157
|
+
let keyProperty = valueSetKeyProperty(values, selection.keyProperty ?? valueSetData?.keyProperty);
|
|
8158
|
+
select.valueList = values.map((value) => {
|
|
8159
|
+
return {
|
|
8160
|
+
key: value[keyProperty],
|
|
8161
|
+
label: value[displayProperty],
|
|
8162
|
+
type: SmartFormWidgetType.ITEM,
|
|
8163
|
+
value: value[keyProperty],
|
|
8164
|
+
};
|
|
8165
|
+
});
|
|
8166
|
+
this.addEmptyItemToValueList(select, selection.emptyLabel);
|
|
8167
|
+
}
|
|
8168
|
+
else if (selection.type === SelectionDefinitionTypeEnum.OBJECT &&
|
|
8169
|
+
!selection.mapping?.length) {
|
|
8170
|
+
select.valueList = values.map((value, index) => {
|
|
8171
|
+
return {
|
|
8172
|
+
key: `${index}`,
|
|
8173
|
+
label: value[displayProperty],
|
|
8174
|
+
type: SmartFormWidgetType.ITEM,
|
|
8175
|
+
value: value,
|
|
8176
|
+
};
|
|
8177
|
+
});
|
|
8178
|
+
this.addEmptyItemToValueList(select);
|
|
7472
8179
|
}
|
|
7473
8180
|
}
|
|
7474
8181
|
toFormGroup() {
|
|
@@ -7806,6 +8513,15 @@ class SmartFormService {
|
|
|
7806
8513
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartFormService, decorators: [{
|
|
7807
8514
|
type: Injectable
|
|
7808
8515
|
}] });
|
|
8516
|
+
/** Whether the widget lists the values of the value set its selection names. */
|
|
8517
|
+
function isListedFromValueSet(widget) {
|
|
8518
|
+
return ((widget.type === SmartFormWidgetType.SELECT ||
|
|
8519
|
+
widget.type === SmartFormWidgetType.SELECT_MULTIPLE ||
|
|
8520
|
+
widget.type === SmartFormWidgetType.RADIO_BUTTON ||
|
|
8521
|
+
widget.type === SmartFormWidgetType.CHECK_BOX_2 ||
|
|
8522
|
+
widget.type === SmartFormWidgetType.TEXT_FIELD) &&
|
|
8523
|
+
!!widget.selection);
|
|
8524
|
+
}
|
|
7809
8525
|
/**
|
|
7810
8526
|
* Splits a date-time widget's backend value into the `HH:mm` text of its companion
|
|
7811
8527
|
* `<key>-time` control, and normalizes the widget's own value to a `Date` for the picker.
|
|
@@ -8866,11 +9582,11 @@ const PIPES = {
|
|
|
8866
9582
|
time: (v, arg, ctx) => formatDate(v, arg ?? 'H:mm', ctx),
|
|
8867
9583
|
number: (v, arg, ctx) => formatNumber(v, arg ?? '1.0-3', ctx),
|
|
8868
9584
|
label: (v, arg, ctx) => {
|
|
8869
|
-
const
|
|
8870
|
-
if (
|
|
9585
|
+
const valueSetData = isEmpty(v) ? undefined : ctx.findValueSetData?.(arg);
|
|
9586
|
+
if (!valueSetData) {
|
|
8871
9587
|
return v;
|
|
8872
9588
|
}
|
|
8873
|
-
return valueSetLabelOf(
|
|
9589
|
+
return valueSetLabelOf(valueSetData, v) ?? v;
|
|
8874
9590
|
},
|
|
8875
9591
|
default: (v, arg) => (isEmpty(v) ? (arg ?? '') : v),
|
|
8876
9592
|
upper: (v, _arg, ctx) => (isEmpty(v) ? v : String(v).toLocaleUpperCase(locales(ctx))),
|
|
@@ -9387,6 +10103,32 @@ function ownAttribute(element, name, value, wanted, owned) {
|
|
|
9387
10103
|
return owned;
|
|
9388
10104
|
}
|
|
9389
10105
|
|
|
10106
|
+
/**
|
|
10107
|
+
* The lookup the `label` pipe reads a value set through by its name: the set a component model
|
|
10108
|
+
* carries under the name (a form a host builds, or a delivery without the store), else the set
|
|
10109
|
+
* the value set store serves the view under the name.
|
|
10110
|
+
*/
|
|
10111
|
+
function createValueSetLookup(valueSets, store, viewUuid) {
|
|
10112
|
+
return (name) => valueSets?.[name]?.valueSetData ?? (viewUuid ? store.findByName(viewUuid, name) : undefined);
|
|
10113
|
+
}
|
|
10114
|
+
function injectValueSetReads() {
|
|
10115
|
+
const changed = signal(0, /* @ts-ignore */
|
|
10116
|
+
...(ngDevMode ? [{ debugName: "changed" }] : /* istanbul ignore next */ []));
|
|
10117
|
+
let names = new Set();
|
|
10118
|
+
inject(SmartValueSetStore)
|
|
10119
|
+
.changes.pipe(filter((name) => names.has(name)), takeUntilDestroyed())
|
|
10120
|
+
.subscribe(() => changed.update((count) => count + 1));
|
|
10121
|
+
return {
|
|
10122
|
+
changed: changed.asReadonly(),
|
|
10123
|
+
track: (lookup) => {
|
|
10124
|
+
names = new Set();
|
|
10125
|
+
return (name) => {
|
|
10126
|
+
names.add(name);
|
|
10127
|
+
return lookup(name);
|
|
10128
|
+
};
|
|
10129
|
+
},
|
|
10130
|
+
};
|
|
10131
|
+
}
|
|
9390
10132
|
/**
|
|
9391
10133
|
* The class the container carries while the html on screen is about to be replaced. A style sheet
|
|
9392
10134
|
* that gives it an animation or transition plays that before the new html is written; without one
|
|
@@ -9498,7 +10240,7 @@ function injectSmartHtmlRenderer(container) {
|
|
|
9498
10240
|
render: (newTemplate, context) => untracked(() => {
|
|
9499
10241
|
template = newTemplate;
|
|
9500
10242
|
const result = resolveTemplate(template, context.data, {
|
|
9501
|
-
|
|
10243
|
+
findValueSetData: context.findValueSetData,
|
|
9502
10244
|
locale: locale(),
|
|
9503
10245
|
warn,
|
|
9504
10246
|
});
|
|
@@ -9548,24 +10290,28 @@ function injectSmartHtmlRenderer(container) {
|
|
|
9548
10290
|
/**
|
|
9549
10291
|
* The HTML widget: server-sent HTML whose client placeholders are resolved against the model of
|
|
9550
10292
|
* the form it sits on, the widget's `root` applied. It has no control, no label and no value of
|
|
9551
|
-
* its own; it follows the form's revision and
|
|
9552
|
-
* result differs. See HTML-WIDGET.md.
|
|
10293
|
+
* its own; it follows the form's revision and the value sets it reads and re-resolves, which
|
|
10294
|
+
* rewrites the html only when the result differs. See HTML-WIDGET.md.
|
|
9553
10295
|
*/
|
|
9554
10296
|
class SmartHtmlWidgetComponent {
|
|
9555
10297
|
constructor() {
|
|
9556
10298
|
this.service = inject(SmartFormService);
|
|
10299
|
+
this.valueSetStore = inject(SmartValueSetStore);
|
|
10300
|
+
this.valueSetReads = injectValueSetReads();
|
|
10301
|
+
this.smartComponent = injectSmartComponent();
|
|
9557
10302
|
this.renderer = injectSmartHtmlRenderer(inject(ElementRef).nativeElement);
|
|
9558
10303
|
this.widgetInstance = input.required(/* @ts-ignore */
|
|
9559
10304
|
...(ngDevMode ? [{ debugName: "widgetInstance" }] : /* istanbul ignore next */ []));
|
|
9560
10305
|
effect(() => {
|
|
9561
10306
|
this.service.revision();
|
|
10307
|
+
this.valueSetReads.changed();
|
|
9562
10308
|
const properties = this.widgetInstance().htmlProperties;
|
|
9563
10309
|
const model = this.service.smartForm?.componentModel;
|
|
9564
10310
|
this.warnUnloaded(properties);
|
|
9565
10311
|
this.renderer.useCss(properties?.css);
|
|
9566
10312
|
this.renderer.render(properties?.html ?? '', {
|
|
9567
10313
|
data: this.scope(model?.data, properties?.root, properties?.html),
|
|
9568
|
-
|
|
10314
|
+
findValueSetData: this.valueSetReads.track(createValueSetLookup(model?.valueSets, this.valueSetStore, this.smartComponent?.uuid)),
|
|
9569
10315
|
icons: properties?.icons,
|
|
9570
10316
|
});
|
|
9571
10317
|
});
|
|
@@ -10175,6 +10921,7 @@ class SmartformwidgetComponent {
|
|
|
10175
10921
|
}
|
|
10176
10922
|
this.filteredOptions = this.onValueChange.pipe(startWith(""), map((value) => this._filter(value || "")), takeUntil(this._destroy$));
|
|
10177
10923
|
}
|
|
10924
|
+
this.followValueSet();
|
|
10178
10925
|
if (this.widgetInstance.type === SmartFormWidgetType.YOUTUBE_PLAYER) {
|
|
10179
10926
|
let videoId = this.parseYoutubeUrl(this.widgetInstance.link);
|
|
10180
10927
|
if (videoId)
|
|
@@ -10201,6 +10948,24 @@ class SmartformwidgetComponent {
|
|
|
10201
10948
|
});
|
|
10202
10949
|
});
|
|
10203
10950
|
}
|
|
10951
|
+
/**
|
|
10952
|
+
* Lists the value set of a selection widget from the value set store and lists it again at
|
|
10953
|
+
* every new version, with no change of the data. A form without a view follows its own model.
|
|
10954
|
+
*/
|
|
10955
|
+
followValueSet() {
|
|
10956
|
+
const viewUuid = this.smartComponent?.uuid;
|
|
10957
|
+
if (!viewUuid) {
|
|
10958
|
+
return;
|
|
10959
|
+
}
|
|
10960
|
+
this.service
|
|
10961
|
+
.observeValueSetData(this.widgetInstance, viewUuid)
|
|
10962
|
+
?.pipe(takeUntil(this._destroy$))
|
|
10963
|
+
.subscribe((valueSetData) => {
|
|
10964
|
+
if (this.service.relistValueSet(this.widgetInstance, valueSetData, this.form())) {
|
|
10965
|
+
this.changeDetector.markForCheck();
|
|
10966
|
+
}
|
|
10967
|
+
});
|
|
10968
|
+
}
|
|
10204
10969
|
getSophisticatedEventKind() {
|
|
10205
10970
|
return this.widgetInstance.type === SmartFormWidgetType.SELECT ||
|
|
10206
10971
|
this.widgetInstance.type === SmartFormWidgetType.SELECT_MULTIPLE ||
|
|
@@ -11946,6 +12711,7 @@ class SmartViewContextService {
|
|
|
11946
12711
|
this.dialog = inject(SmartViewContextDialogService);
|
|
11947
12712
|
this.apiQueueService = inject(ApiQueueService);
|
|
11948
12713
|
this.themeService = inject(ThemeService);
|
|
12714
|
+
this.valueSetStore = inject(SmartValueSetStore);
|
|
11949
12715
|
this.inject = inject(Injector);
|
|
11950
12716
|
this.smartConfig = inject(SMART_NG_CLIENT_CONFIG);
|
|
11951
12717
|
this.viewContextUuidName = "viewContextUuid";
|
|
@@ -12936,7 +13702,10 @@ class SmartViewContextService {
|
|
|
12936
13702
|
await this.sendViewContextUpdates(updates);
|
|
12937
13703
|
this.viewContextHasBeenSynced.next();
|
|
12938
13704
|
}
|
|
12939
|
-
/**
|
|
13705
|
+
/**
|
|
13706
|
+
* Opens and closes the views as the view context says, returns the states to report. A closed
|
|
13707
|
+
* view's implicit value sets are dropped from the value set store.
|
|
13708
|
+
*/
|
|
12940
13709
|
syncViewStates() {
|
|
12941
13710
|
const updates = [];
|
|
12942
13711
|
const ops = buildViewOps(this.viewContext?.views ?? [], this.reuseEnabled());
|
|
@@ -12968,6 +13737,9 @@ class SmartViewContextService {
|
|
|
12968
13737
|
updates.push(...this.closeView(viewData));
|
|
12969
13738
|
});
|
|
12970
13739
|
}
|
|
13740
|
+
updates
|
|
13741
|
+
.filter((update) => update?.state === ViewState.CLOSED && update.uuid)
|
|
13742
|
+
.forEach((update) => this.valueSetStore.removeView(update.uuid));
|
|
12971
13743
|
return updates;
|
|
12972
13744
|
}
|
|
12973
13745
|
async startDownloadsFiles(downloads) {
|
|
@@ -13050,7 +13822,7 @@ class SmartViewContextService {
|
|
|
13050
13822
|
async message(messageData, messageResult) {
|
|
13051
13823
|
return await this.handlePerformActionResponse(await this.view
|
|
13052
13824
|
.message(messageData.viewUuid ?? "", messageData.uuid, messageResult)
|
|
13053
|
-
.toPromise());
|
|
13825
|
+
.toPromise(), messageData.viewUuid);
|
|
13054
13826
|
// in future use this.apiQueueService.addToQueue
|
|
13055
13827
|
}
|
|
13056
13828
|
getSmartViewContextApiErrorByCode(code) {
|
|
@@ -13183,27 +13955,27 @@ class SmartViewContextService {
|
|
|
13183
13955
|
async _performAction(config) {
|
|
13184
13956
|
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
13185
13957
|
.performAction(config.uuid, config.uiActionRequest)
|
|
13186
|
-
.toPromise()));
|
|
13958
|
+
.toPromise()), config.uuid);
|
|
13187
13959
|
}
|
|
13188
13960
|
async _performWidgetAction(config) {
|
|
13189
13961
|
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
13190
13962
|
.performWidgetAction(config.uuid, config.widgetId, config.nodeId, config.uiActionRequest)
|
|
13191
|
-
.toPromise()));
|
|
13963
|
+
.toPromise()), config.uuid);
|
|
13192
13964
|
}
|
|
13193
13965
|
async _performWidgetMainAction(config) {
|
|
13194
13966
|
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
13195
13967
|
.performWidgetMainAction(config.uuid, config.widgetId, config.uiActionRequest)
|
|
13196
|
-
.toPromise()));
|
|
13968
|
+
.toPromise()), config.uuid);
|
|
13197
13969
|
}
|
|
13198
13970
|
async _performUploadAction(config) {
|
|
13199
13971
|
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
13200
13972
|
.uploadAction(config.uuid, JSON.stringify(config.uiActionRequest), config.param, config.content)
|
|
13201
|
-
.toPromise()));
|
|
13973
|
+
.toPromise()), config.uuid);
|
|
13202
13974
|
}
|
|
13203
13975
|
async _performUploadMultipleAction(config) {
|
|
13204
13976
|
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
13205
13977
|
.uploadMultipleAction(config.uuid, JSON.stringify(config.uiActionRequest), config.param, config.content)
|
|
13206
|
-
.toPromise()));
|
|
13978
|
+
.toPromise()), config.uuid);
|
|
13207
13979
|
}
|
|
13208
13980
|
/**
|
|
13209
13981
|
* Calls run concurrently, so the response of an earlier call can land after that of a later
|
|
@@ -13220,8 +13992,22 @@ class SmartViewContextService {
|
|
|
13220
13992
|
* reports it closed; the applied view context lists such a view OPENED only because an OPENED
|
|
13221
13993
|
* report of the client reached the server after the close. So a view to be closed in the view
|
|
13222
13994
|
* context not applied is closed all the same.
|
|
13995
|
+
*
|
|
13996
|
+
* The Value Set Version Map of the change goes to the value set store, whose fetches are held
|
|
13997
|
+
* until the change is applied, so one request carries the implicit sets the changed models name.
|
|
13998
|
+
* The fetch is not awaited: the widgets follow the store.
|
|
13223
13999
|
*/
|
|
13224
|
-
async handlePerformActionResponse(viewContextChange) {
|
|
14000
|
+
async handlePerformActionResponse(viewContextChange, viewUuid) {
|
|
14001
|
+
// The implicit sets the changed models name go in the Value Set Fetch of the version map.
|
|
14002
|
+
const releaseValueSetFetches = this.valueSetStore.holdFetches();
|
|
14003
|
+
try {
|
|
14004
|
+
return await this.applyPerformActionResponse(viewContextChange, viewUuid);
|
|
14005
|
+
}
|
|
14006
|
+
finally {
|
|
14007
|
+
releaseValueSetFetches();
|
|
14008
|
+
}
|
|
14009
|
+
}
|
|
14010
|
+
async applyPerformActionResponse(viewContextChange, viewUuid) {
|
|
13225
14011
|
await Promise.allSettled(this.runningViewContextUpdates);
|
|
13226
14012
|
const sequence = viewContextChange?.viewContext?.sequence;
|
|
13227
14013
|
const applied = this.viewContext?.sequence;
|
|
@@ -13239,6 +14025,9 @@ class SmartViewContextService {
|
|
|
13239
14025
|
if (viewContextChange?.changes) {
|
|
13240
14026
|
this.handleChanges(viewContextChange.changes);
|
|
13241
14027
|
}
|
|
14028
|
+
this.valueSetStore
|
|
14029
|
+
.applyVersions(viewContextChange, viewUuid)
|
|
14030
|
+
.catch((err) => console.error("value set fetch failed", err));
|
|
13242
14031
|
return viewContextChange?.result;
|
|
13243
14032
|
}
|
|
13244
14033
|
handleChanges(changes) {
|
|
@@ -13256,7 +14045,7 @@ class SmartViewContextService {
|
|
|
13256
14045
|
let change = await this.view.getComponentModel2(uuid).toPromise();
|
|
13257
14046
|
// Not awaited: the sync ends with a viewcontext PUT, which would serialise the mount.
|
|
13258
14047
|
// The failure still has to surface, so log it instead of dropping the promise.
|
|
13259
|
-
this.handlePerformActionResponse(change).catch((err) => console.error("syncView after component load failed", err));
|
|
14048
|
+
this.handlePerformActionResponse(change, uuid).catch((err) => console.error("syncView after component load failed", err));
|
|
13260
14049
|
return change;
|
|
13261
14050
|
}
|
|
13262
14051
|
getCurrentViewContext() {
|
|
@@ -15064,7 +15853,8 @@ function rowActionModels(row, gridIdentifier, serviceToUse) {
|
|
|
15064
15853
|
/**
|
|
15065
15854
|
* A table cell rendered from a column template: server-sent HTML whose client placeholders are
|
|
15066
15855
|
* resolved against the row's data, the template's `root` applied. The toolbar slots and action
|
|
15067
|
-
* triggers in it offer the row's actions, the way a card's row layout does.
|
|
15856
|
+
* triggers in it offer the row's actions, the way a card's row layout does. A new version of a
|
|
15857
|
+
* value set it reads renders it again, which rewrites the html only when the result differs.
|
|
15068
15858
|
*
|
|
15069
15859
|
* The cell provides the action host itself rather than the row: the table creates its cells
|
|
15070
15860
|
* from templates declared in the table, so they inject from there, never from the row element.
|
|
@@ -15074,10 +15864,23 @@ class SmartHtmlCellComponent {
|
|
|
15074
15864
|
constructor() {
|
|
15075
15865
|
this.actionHost = inject(SmartActionHost);
|
|
15076
15866
|
this.smartComponent = injectSmartComponent();
|
|
15867
|
+
this.valueSetStore = inject(SmartValueSetStore);
|
|
15868
|
+
this.valueSetReads = injectValueSetReads();
|
|
15077
15869
|
this.renderer = injectSmartHtmlRenderer(inject(ElementRef).nativeElement);
|
|
15870
|
+
effect(() => {
|
|
15871
|
+
this.valueSetReads.changed();
|
|
15872
|
+
untracked(() => {
|
|
15873
|
+
if (this.row && this.template) {
|
|
15874
|
+
this.renderTemplate();
|
|
15875
|
+
}
|
|
15876
|
+
});
|
|
15877
|
+
});
|
|
15078
15878
|
}
|
|
15079
15879
|
ngOnChanges() {
|
|
15080
15880
|
this.actionHost.actionModels.set(rowActionModels(this.row, this.gridIdentifier));
|
|
15881
|
+
this.renderTemplate();
|
|
15882
|
+
}
|
|
15883
|
+
renderTemplate() {
|
|
15081
15884
|
const { html, root, css, icons } = this.template;
|
|
15082
15885
|
const scope = rootScope(this.row.data, root);
|
|
15083
15886
|
if (scope === undefined && root && this.warnedRoot !== root) {
|
|
@@ -15088,7 +15891,7 @@ class SmartHtmlCellComponent {
|
|
|
15088
15891
|
this.renderer.useCss(css);
|
|
15089
15892
|
this.renderer.render(html ?? '', {
|
|
15090
15893
|
data: scope,
|
|
15091
|
-
|
|
15894
|
+
findValueSetData: this.valueSetReads.track(createValueSetLookup(this.smartComponent?.model?.valueSets, this.valueSetStore, this.smartComponent?.uuid)),
|
|
15092
15895
|
icons,
|
|
15093
15896
|
});
|
|
15094
15897
|
}
|
|
@@ -15098,7 +15901,7 @@ class SmartHtmlCellComponent {
|
|
|
15098
15901
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartHtmlCellComponent, decorators: [{
|
|
15099
15902
|
type: Component,
|
|
15100
15903
|
args: [{ selector: 'smart-html-cell', template: '', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [SmartActionHost], styles: ["smart-html-cell{display:block}smart-html-cell [data-sb4-action]{cursor:pointer}smart-html-cell [data-sb4-action].sb4-action-inert{cursor:inherit}smart-html-cell [data-sb4-action].sb4-action-disabled{cursor:default;opacity:.5}\n"] }]
|
|
15101
|
-
}], propDecorators: { row: [{
|
|
15904
|
+
}], ctorParameters: () => [], propDecorators: { row: [{
|
|
15102
15905
|
type: Input,
|
|
15103
15906
|
args: [{ required: true }]
|
|
15104
15907
|
}], template: [{
|
|
@@ -16629,6 +17432,10 @@ class SmarttreeService {
|
|
|
16629
17432
|
syncTree() {
|
|
16630
17433
|
throw new Error('syncTree method not implemented.');
|
|
16631
17434
|
}
|
|
17435
|
+
/** Whether the tree was downloaded for another view than the one its page shows now. */
|
|
17436
|
+
isDownloadedForAnotherView() {
|
|
17437
|
+
return false;
|
|
17438
|
+
}
|
|
16632
17439
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmarttreeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
16633
17440
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmarttreeService, providedIn: 'root' }); }
|
|
16634
17441
|
}
|
|
@@ -16704,9 +17511,15 @@ class SmartTreeComponent {
|
|
|
16704
17511
|
// The backend knows this widget by its treeId, which is set when the service is created —
|
|
16705
17512
|
// not by smartTreeModel.identifier, which only exists after the first successful
|
|
16706
17513
|
// syncTree, so a tree that has not finished downloading would be unreachable. (#28361)
|
|
17514
|
+
const treeService = this.treeService;
|
|
16707
17515
|
registerSmartWidget(injectSmartComponent(), {
|
|
16708
17516
|
identifier: () => this.treeService()?.treeId,
|
|
16709
17517
|
reload: () => this.treeService().initialize(),
|
|
17518
|
+
// A page opened again keeps this component under a new view uuid, and the server's tree
|
|
17519
|
+
// state of the new view knows none of the node identifiers downloaded for the old one.
|
|
17520
|
+
get reloadDuringInitialSync() {
|
|
17521
|
+
return treeService()?.isDownloadedForAnotherView() ?? false;
|
|
17522
|
+
},
|
|
16710
17523
|
});
|
|
16711
17524
|
}
|
|
16712
17525
|
ngOnInit() {
|
|
@@ -18242,6 +19055,10 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
18242
19055
|
}
|
|
18243
19056
|
async initialize() {
|
|
18244
19057
|
if (this.viewContext.hasViewContextUuid()) {
|
|
19058
|
+
if (this.isDownloadedForAnotherView()) {
|
|
19059
|
+
// The selection is a node of the other view's tree, unknown to this view's tree state.
|
|
19060
|
+
this.selectedNode = undefined;
|
|
19061
|
+
}
|
|
18245
19062
|
await this.downloadTree().then((rootNodes) => {
|
|
18246
19063
|
if (!deepEqual(this.treeFromBackend, rootNodes)) {
|
|
18247
19064
|
this.treeFromBackend = rootNodes;
|
|
@@ -18252,19 +19069,23 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
18252
19069
|
}
|
|
18253
19070
|
async downloadTree() {
|
|
18254
19071
|
let uuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
18255
|
-
const rootNodes = await this.viewContext.handlePerformActionResponse(await this.service.getRootNodes2(uuid, this.treeId).toPromise());
|
|
18256
|
-
const uiActions = await this.viewContext.handlePerformActionResponse(await this.service.getMainActions2(uuid, this.treeId).toPromise());
|
|
19072
|
+
const rootNodes = await this.viewContext.handlePerformActionResponse(await this.service.getRootNodes2(uuid, this.treeId).toPromise(), uuid);
|
|
19073
|
+
const uiActions = await this.viewContext.handlePerformActionResponse(await this.service.getMainActions2(uuid, this.treeId).toPromise(), uuid);
|
|
18257
19074
|
if (uiActions) {
|
|
18258
19075
|
this.constructUiActionModels(uiActions);
|
|
18259
19076
|
}
|
|
18260
|
-
if (
|
|
19077
|
+
if (rootNodes) {
|
|
19078
|
+
// Recorded only for a received tree, so that a download without one is repeated.
|
|
19079
|
+
this.downloadedViewUuid = uuid;
|
|
19080
|
+
}
|
|
19081
|
+
else {
|
|
18261
19082
|
console.error('RootNodes are undefined!');
|
|
18262
19083
|
}
|
|
18263
19084
|
return rootNodes ?? [];
|
|
18264
19085
|
}
|
|
18265
19086
|
async downloadChildren(parentNode) {
|
|
18266
19087
|
let uuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
18267
|
-
const children = await this.viewContext.handlePerformActionResponse(await this.service.getChildrenNodes2(uuid, this.treeId, parentNode.identifier).toPromise());
|
|
19088
|
+
const children = await this.viewContext.handlePerformActionResponse(await this.service.getChildrenNodes2(uuid, this.treeId, parentNode.identifier).toPromise(), uuid);
|
|
18268
19089
|
if (!children) {
|
|
18269
19090
|
throw new Error(`Node with identifier ${parentNode.identifier} does not have children.`);
|
|
18270
19091
|
}
|
|
@@ -18273,11 +19094,11 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
18273
19094
|
async onTreeNodeOpen(treeNode) {
|
|
18274
19095
|
let viewUuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
18275
19096
|
if (treeNode?.expanded) {
|
|
18276
|
-
let tempTreeNode = await this.viewContext.handlePerformActionResponse(await this.service.collapseNode2(viewUuid, this.treeId, treeNode.identifier).toPromise());
|
|
19097
|
+
let tempTreeNode = await this.viewContext.handlePerformActionResponse(await this.service.collapseNode2(viewUuid, this.treeId, treeNode.identifier).toPromise(), viewUuid);
|
|
18277
19098
|
treeNode = tempTreeNode;
|
|
18278
19099
|
}
|
|
18279
19100
|
else if (!treeNode?.expanded) {
|
|
18280
|
-
let tempTreeNode = await this.viewContext.handlePerformActionResponse(await this.service.expandNode2(viewUuid, this.treeId, treeNode?.identifier).toPromise());
|
|
19101
|
+
let tempTreeNode = await this.viewContext.handlePerformActionResponse(await this.service.expandNode2(viewUuid, this.treeId, treeNode?.identifier).toPromise(), viewUuid);
|
|
18281
19102
|
treeNode = tempTreeNode;
|
|
18282
19103
|
}
|
|
18283
19104
|
let node = this.deepSearchTreeNode(treeNode?.identifier, this.treeFromBackend);
|
|
@@ -18290,7 +19111,7 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
18290
19111
|
}
|
|
18291
19112
|
async selectFolder(folderUri, treeNode) {
|
|
18292
19113
|
let viewUuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
18293
|
-
let updatedTreeNode = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync({}, (request) => this.service.selectNode2(viewUuid, this.treeId, treeNode.identifier, request).toPromise()));
|
|
19114
|
+
let updatedTreeNode = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync({}, (request) => this.service.selectNode2(viewUuid, this.treeId, treeNode.identifier, request).toPromise()), viewUuid);
|
|
18294
19115
|
if (this.selectedNode) {
|
|
18295
19116
|
this.selectedNode.selected = false;
|
|
18296
19117
|
}
|
|
@@ -18306,6 +19127,10 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
18306
19127
|
this.syncTree();
|
|
18307
19128
|
//this.viewContext.getAndSyncViewContext(this.viewContext.getViewContextUuid());
|
|
18308
19129
|
}
|
|
19130
|
+
isDownloadedForAnotherView() {
|
|
19131
|
+
return (this.downloadedViewUuid !== undefined &&
|
|
19132
|
+
this.downloadedViewUuid !== this.viewContext.getUuidOfPage(this.pageName));
|
|
19133
|
+
}
|
|
18309
19134
|
async updateTreeOnTheFly() {
|
|
18310
19135
|
await this.initialize();
|
|
18311
19136
|
}
|
|
@@ -18500,11 +19325,11 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
18500
19325
|
let nodeId = uiActionRequest.params['nodeUuid'];
|
|
18501
19326
|
delete uiActionRequest.params['nodeUuid'];
|
|
18502
19327
|
let viewUuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
18503
|
-
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync(uiActionRequest, (request) => this.service.performAction2(viewUuid, this.treeId, nodeId, request).toPromise()));
|
|
19328
|
+
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync(uiActionRequest, (request) => this.service.performAction2(viewUuid, this.treeId, nodeId, request).toPromise()), viewUuid);
|
|
18504
19329
|
}
|
|
18505
19330
|
async performMainUiActionRequest(uiActionRequest) {
|
|
18506
19331
|
let viewUuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
18507
|
-
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync(uiActionRequest, (request) => this.service.performMainAction2(viewUuid, this.treeId, request).toPromise()));
|
|
19332
|
+
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync(uiActionRequest, (request) => this.service.performMainAction2(viewUuid, this.treeId, request).toPromise()), viewUuid);
|
|
18508
19333
|
}
|
|
18509
19334
|
handleSpecificDemandsAsynchronously(uiAction, uiActionRequest) {
|
|
18510
19335
|
throw new Error('Method not implemented.');
|
|
@@ -18692,6 +19517,9 @@ class SmartComponentApiClient {
|
|
|
18692
19517
|
set model(model) {
|
|
18693
19518
|
this.modelState.set(model);
|
|
18694
19519
|
this.actionsState.set(model?.actions);
|
|
19520
|
+
if (this.uuid) {
|
|
19521
|
+
this.valueSetStore.putImplicit(this.uuid, model?.valueSets);
|
|
19522
|
+
}
|
|
18695
19523
|
this.initComponentByModel();
|
|
18696
19524
|
}
|
|
18697
19525
|
get data() {
|
|
@@ -18792,6 +19620,7 @@ class SmartComponentApiClient {
|
|
|
18792
19620
|
}
|
|
18793
19621
|
this.viewContext = inject.get(SmartViewContextService);
|
|
18794
19622
|
this.bootstrap = inject.get(SmartBackendBootstrapService);
|
|
19623
|
+
this.valueSetStore = inject.get(SmartValueSetStore);
|
|
18795
19624
|
if (this._componentName) {
|
|
18796
19625
|
let pageNameForComponent = this.viewContext.getPageNameOfComponent(this._componentName);
|
|
18797
19626
|
if (!this.pageName) {
|
|
@@ -19273,6 +20102,7 @@ class SmartComponentApiClient {
|
|
|
19273
20102
|
handleValueSetChange(changes, changeKey) {
|
|
19274
20103
|
let valueSetKey = changeKey.split('.')[1];
|
|
19275
20104
|
this.model.valueSets[valueSetKey] = changes[changeKey];
|
|
20105
|
+
this.valueSetStore.putImplicit(this.uuid, { [valueSetKey]: changes[changeKey] });
|
|
19276
20106
|
}
|
|
19277
20107
|
handleActionChange(changes, changeKey) {
|
|
19278
20108
|
this.model.actions = changes[changeKey];
|
|
@@ -21672,13 +22502,13 @@ class SmartGridComponent {
|
|
|
21672
22502
|
this.isBlocked = true;
|
|
21673
22503
|
const row = this.service.gridModel.page.rows?.find((gridRow) => gridRow.id === rowId);
|
|
21674
22504
|
const viewContextChange = await this.service.select(this.smartGrid, row);
|
|
21675
|
-
this.smartGrid.viewContextService.handlePerformActionResponse(viewContextChange);
|
|
22505
|
+
this.smartGrid.viewContextService.handlePerformActionResponse(viewContextChange, this.smartGrid.gridModel.viewUuid);
|
|
21676
22506
|
this.refresh();
|
|
21677
22507
|
}
|
|
21678
22508
|
async onSelectAll(selected) {
|
|
21679
22509
|
this.isBlocked = true;
|
|
21680
22510
|
const viewContextChange = await this.service.selectAll(this.smartGrid, selected);
|
|
21681
|
-
this.smartGrid.viewContextService.handlePerformActionResponse(viewContextChange);
|
|
22511
|
+
this.smartGrid.viewContextService.handlePerformActionResponse(viewContextChange, this.smartGrid.gridModel.viewUuid);
|
|
21682
22512
|
this.refresh();
|
|
21683
22513
|
}
|
|
21684
22514
|
async onSelectRows(selectedIds, unselectedIds) {
|
|
@@ -21686,7 +22516,7 @@ class SmartGridComponent {
|
|
|
21686
22516
|
let selected = selectedIds.filter((item) => item !== undefined);
|
|
21687
22517
|
let unselected = unselectedIds.filter((item) => item !== undefined);
|
|
21688
22518
|
const viewContextChange = await this.service.selectRows(this.smartGrid, selected, unselected);
|
|
21689
|
-
this.smartGrid.viewContextService.handlePerformActionResponse(viewContextChange);
|
|
22519
|
+
this.smartGrid.viewContextService.handlePerformActionResponse(viewContextChange, this.smartGrid.gridModel.viewUuid);
|
|
21690
22520
|
this.refresh();
|
|
21691
22521
|
}
|
|
21692
22522
|
editColumns() {
|
|
@@ -23231,7 +24061,7 @@ class SmartMapComponent {
|
|
|
23231
24061
|
return null;
|
|
23232
24062
|
}
|
|
23233
24063
|
else {
|
|
23234
|
-
return this.viewContextService.handlePerformActionResponse(change);
|
|
24064
|
+
return this.viewContextService.handlePerformActionResponse(change, this.uuid);
|
|
23235
24065
|
}
|
|
23236
24066
|
}, (err) => {
|
|
23237
24067
|
console.warn('Could not submit selection change! ', err);
|
|
@@ -25784,10 +26614,8 @@ class SmartComponentLayoutComponent {
|
|
|
25784
26614
|
this.smartForm = {
|
|
25785
26615
|
direction: this.getFormLayout(),
|
|
25786
26616
|
// A row gets an envelope rather than being written into: its `data` stays the row's own
|
|
25787
|
-
// object
|
|
25788
|
-
componentModel: gridRow
|
|
25789
|
-
? { ...gridRow, valueSets: gridRow.valueSets ?? this.smartComponent?.model?.valueSets }
|
|
25790
|
-
: this.smartComponent?.model,
|
|
26617
|
+
// object. Its widgets read the value sets of the page's view from the value set store.
|
|
26618
|
+
componentModel: gridRow ? { ...gridRow } : this.smartComponent?.model,
|
|
25791
26619
|
widgets,
|
|
25792
26620
|
};
|
|
25793
26621
|
}
|
|
@@ -26781,6 +27609,8 @@ var ACLEntry;
|
|
|
26781
27609
|
* Do not edit the class manually.
|
|
26782
27610
|
*/
|
|
26783
27611
|
|
|
27612
|
+
/** The key of the view's value set that lists the operations of the matrix. */
|
|
27613
|
+
const OPERATIONS = 'OPERATIONS';
|
|
26784
27614
|
class AclEditingViewComponent extends SmartComponent {
|
|
26785
27615
|
get smartForm() {
|
|
26786
27616
|
return this.smartFormState();
|
|
@@ -26802,13 +27632,16 @@ class AclEditingViewComponent extends SmartComponent {
|
|
|
26802
27632
|
*/
|
|
26803
27633
|
this.aclActionModels = computed(() => this.actionModels().map((model) => model.uiAction.code === 'SAVE' ? { ...model, exception: true } : model), /* @ts-ignore */
|
|
26804
27634
|
...(ngDevMode ? [{ debugName: "aclActionModels" }] : /* istanbul ignore next */ []));
|
|
26805
|
-
|
|
26806
|
-
|
|
27635
|
+
// The operations come from the value set store, which may get them after the data.
|
|
27636
|
+
this.dataChanged
|
|
27637
|
+
.pipe(switchMap(() => this.valueSetStore.getImplicit(this.uuid, OPERATIONS)), filter$1((operations) => !!operations), takeUntil$1(this._destroy$))
|
|
27638
|
+
.subscribe((operations) => {
|
|
27639
|
+
this.constructForm(operations);
|
|
26807
27640
|
this.initActions();
|
|
26808
27641
|
});
|
|
26809
27642
|
}
|
|
26810
|
-
constructForm() {
|
|
26811
|
-
let tempOpartions =
|
|
27643
|
+
constructForm(operations) {
|
|
27644
|
+
let tempOpartions = operations.values.map((value) => value.toString());
|
|
26812
27645
|
let widgets = this.formService.render({
|
|
26813
27646
|
layoutDefinitions: this.model.layouts['ACL_MATRIX'].widgets,
|
|
26814
27647
|
});
|
|
@@ -27129,5 +27962,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
27129
27962
|
* Generated bundle index. Do not edit.
|
|
27130
27963
|
*/
|
|
27131
27964
|
|
|
27132
|
-
export { ACLEntry, APIS$5 as APIS, AclEditingViewComponent, ApiModule$4 as ApiModule, ApiQueueService, BASE_PATH$7 as BASE_PATH, COLLECTION_FORMATS$7 as COLLECTION_FORMATS, CUSTOM_DIAGRAM_OPTIONS, CloseResult, ComponentFactoryService, ComponentType, ComponentWidgetType, Configuration$7 as Configuration, DEFAULT_ROW_LAYOUT, DIALOG_DISABLE_CLOSE, DataChangeKind, DefaultChartOptionsProvider, DefaultUiActionCode_CLOSE, DrawTime, EMPTY_PARAMS, ExpandableSectionButtonIconPosition, ExpandableSectionButtonType, ExpandableSectionComponent, FilterExpressionBoolOperator$1 as FilterExpressionBoolOperator, FilterExpressionBuilderGroupBuilderGroupKindEnum, FilterExpressionBuilderUiModelTypeEnum, FilterExpressionDataType, FilterExpressionFieldWidgetType, FilterExpressionOperation, FilterExpressionOrderByOrderEnum, GenericPageComponent, GeoMapDataLoadingMode, GeoMapDataSourceType, GeoMapItemKind, GeoMapOperationMode, GeoMapSelectionMode, GeoMapTextType, GridColumnContentType, GridDataAccessConfigKindEnum, GridDefaultRowActionTrigger, GridRowStateDisplay, GridSelectionMode, GridSelectionType, GridUiActionType, GridViewDescriptorKindEnum, HighlightPipe, IS_ASYNC_PARAM_NAME, IconPosition, ImageResourceKindEnum, InvalidSmartlinkComponent, LayoutDirection, LinkTargetEnum, MAP_ENGINE, MapEngine, MenuOpenDirection, MenuTriggerType, MessageOptionType, MessageTextType, MessageType, NAMED_VALIDATOR, NamedValidatorOperationEnum, NamedValidatorService, NoPermissionPageComponent, PageExportFieldScope, PageExportSelectionKind, PageExportValueType, PageExportValuesSource, REUSE_ROUTER_SLOT_COMPONENT, ROOT_CONTAINER_UUID, ROUTER_SLOT_ID, RecordingUploaderPropertiesOpenDirectionEnum, SMART_DATE_FORMATS, SMART_DEFAULT_VIEW_COMPONENTS, SMART_NG_CLIENT_CONFIG, SMART_ROW_LAYOUT_COMPONENT, SearchPageComponent, SelectionDefinitionTypeEnum, SelectionDefinitionValueSetValueTypeEnum, ServerRequestType, SessionAPIS, SessionErrorBehaviour, SessionService, SmartActionHost, SmartActionType, SmartBackendBootstrapService, SmartComponent, SmartComponentApiClient, SmartComponentDetachedDirective, SmartComponentHost, SmartComponentLayoutComponent, SmartDateFnsAdapter, SmartDatePipe, SmartDateTimePipe, SmartDefaultErrorUiService, SmartDiagramComponent, SmartDialog, SmartEmbeddedSlotDirective, SmartExpandableSectionService, SmartFileEditorComponent, SmartFilterComponent, SmartFilterEditorContentComponent, SmartFilterEditorService, SmartFilterExpressionFieldComponent, SmartFilterPosition, SmartFilterType, SmartFilterWidgetComponent, SmartFormInputMode, SmartFormTextFieldButtonIconPosition, SmartFormWidgetDirection, SmartFormWidgetType, SmartFormWidgetWidth, SmartGridButtonType, SmartGridComponent, SmartGridDataLayout, SmartGridService, SmartGridType, SmartIconComponent, SmartIconService, SmartKeybindingService, SmartLayoutDef, SmartLinkChannelVariableInPath, SmartLinkMigrationStatusStatusEnum, SmartLinkUuidVariableInPath, SmartMapComponent, SmartMultiFileEditorComponent, SmartNavbarComponent, SmartNavbarService, SmartNavigationService, SmartNgClientFeatureKind, SmartService, SmartSessionService, SmartSessionTimerComponent, SmartTable, SmartTableButtonType, SmartTableHeaderPropertyType, SmartTableInterfaceTypeEnum, SmartTableOptionButtonDirection, SmartTableOrder, SmartTableType, SmartTimePipe, SmartTooltipDirective, SmartTreeComponent, SmartTreeNodeButtonType, SmartUserSettinsIconPosition, SmartValidatorName, SmartViewContextService, SmartViewRedirect, SmartVoiceRecorderComponent, SmartWidgetHintPosition, SmartWidgetHintPositionEnum, SmartdialogService, SmartfileuploaderComponent, SmartformComponent, SmartformLayoutDefinitionService, SmarttreeGenericService, SmarttreeService, SubjectSelectorComponent, ThemeService, ToggleLabelPosition, ToolbarAlignment, ToolbarAppearance, ToolbarDirection, TreeArrowPosition, TreeGridControl, USE_ADVANCED_FILTER, UiActionButtonComponent, UiActionButtonType, UiActionConfirmDialogService, UiActionDescriptorService, UiActionDialogButtonComponent, UiActionDialogType, UiActionFeedbackType, UiActionInputDialogService, UiActionInputType, UiActionService, UiActionToolbarComponent, UiActionTooltipTooltipPositionEnum, UiBadgeComponent, UiBadgeDirective, UploadWidgetType, ValidationResultPageComponent, ValueChangeMode, ViewContextRebuiltError, ViewEventHandlerViewEventTypeEnum, ViewService, ViewState, ViewType, barChart, bubbleChart, createBasicOptions, doughnutChart, formatChord, hasGroupEditActions, horizontalBarChart, horizontalStackedBarChart, injectSmartComponent, isMacPlatform, matches, multiAxisLineChart, parseChord, pieChart, polarAreaChart, provideSmartNgClient, radarChart, registerSmartWidget, resolveDateLocale, resolveSlot, resolveSmartNgClientConfig, resolveViewHandler, scatterChart, stackedBarChart, transformDataToBarLikeDataSet, transformDataToBasicDataSets, transformDataToBubble, transformDataToScatter, withSmartDiagram, withSmartMap };
|
|
27965
|
+
export { ACLEntry, APIS$5 as APIS, AclEditingViewComponent, ApiModule$4 as ApiModule, ApiQueueService, BASE_PATH$7 as BASE_PATH, COLLECTION_FORMATS$7 as COLLECTION_FORMATS, CUSTOM_DIAGRAM_OPTIONS, CloseResult, ComponentFactoryService, ComponentType, ComponentWidgetType, Configuration$7 as Configuration, DEFAULT_ROW_LAYOUT, DIALOG_DISABLE_CLOSE, DataChangeKind, DefaultChartOptionsProvider, DefaultUiActionCode_CLOSE, DrawTime, EMPTY_PARAMS, ExpandableSectionButtonIconPosition, ExpandableSectionButtonType, ExpandableSectionComponent, FilterExpressionBoolOperator$1 as FilterExpressionBoolOperator, FilterExpressionBuilderGroupBuilderGroupKindEnum, FilterExpressionBuilderUiModelTypeEnum, FilterExpressionDataType, FilterExpressionFieldWidgetType, FilterExpressionOperation, FilterExpressionOrderByOrderEnum, GenericPageComponent, GeoMapDataLoadingMode, GeoMapDataSourceType, GeoMapItemKind, GeoMapOperationMode, GeoMapSelectionMode, GeoMapTextType, GridColumnContentType, GridDataAccessConfigKindEnum, GridDefaultRowActionTrigger, GridRowStateDisplay, GridSelectionMode, GridSelectionType, GridUiActionType, GridViewDescriptorKindEnum, HighlightPipe, IS_ASYNC_PARAM_NAME, IconPosition, ImageResourceKindEnum, InvalidSmartlinkComponent, LayoutDirection, LinkTargetEnum, MAP_ENGINE, MapEngine, MenuOpenDirection, MenuTriggerType, MessageOptionType, MessageTextType, MessageType, NAMED_VALIDATOR, NamedValidatorOperationEnum, NamedValidatorService, NoPermissionPageComponent, PageExportFieldScope, PageExportSelectionKind, PageExportValueType, PageExportValuesSource, REUSE_ROUTER_SLOT_COMPONENT, ROOT_CONTAINER_UUID, ROUTER_SLOT_ID, RecordingUploaderPropertiesOpenDirectionEnum, SMART_DATE_FORMATS, SMART_DEFAULT_VIEW_COMPONENTS, SMART_NG_CLIENT_CONFIG, SMART_ROW_LAYOUT_COMPONENT, SearchPageComponent, SelectionDefinitionTypeEnum, SelectionDefinitionValueSetValueTypeEnum, ServerRequestType, SessionAPIS, SessionErrorBehaviour, SessionService, SmartActionHost, SmartActionType, SmartBackendBootstrapService, SmartComponent, SmartComponentApiClient, SmartComponentDetachedDirective, SmartComponentHost, SmartComponentLayoutComponent, SmartDateFnsAdapter, SmartDatePipe, SmartDateTimePipe, SmartDefaultErrorUiService, SmartDiagramComponent, SmartDialog, SmartEmbeddedSlotDirective, SmartExpandableSectionService, SmartFileEditorComponent, SmartFilterComponent, SmartFilterEditorContentComponent, SmartFilterEditorService, SmartFilterExpressionFieldComponent, SmartFilterPosition, SmartFilterType, SmartFilterWidgetComponent, SmartFormInputMode, SmartFormTextFieldButtonIconPosition, SmartFormWidgetDirection, SmartFormWidgetType, SmartFormWidgetWidth, SmartGridButtonType, SmartGridComponent, SmartGridDataLayout, SmartGridService, SmartGridType, SmartIconComponent, SmartIconService, SmartKeybindingService, SmartLayoutDef, SmartLinkChannelVariableInPath, SmartLinkMigrationStatusStatusEnum, SmartLinkUuidVariableInPath, SmartMapComponent, SmartMultiFileEditorComponent, SmartNavbarComponent, SmartNavbarService, SmartNavigationService, SmartNgClientFeatureKind, SmartService, SmartSessionService, SmartSessionTimerComponent, SmartTable, SmartTableButtonType, SmartTableHeaderPropertyType, SmartTableInterfaceTypeEnum, SmartTableOptionButtonDirection, SmartTableOrder, SmartTableType, SmartTimePipe, SmartTooltipDirective, SmartTreeComponent, SmartTreeNodeButtonType, SmartUserSettinsIconPosition, SmartValidatorName, SmartValueSetStore, SmartViewContextService, SmartViewRedirect, SmartVoiceRecorderComponent, SmartWidgetHintPosition, SmartWidgetHintPositionEnum, SmartdialogService, SmartfileuploaderComponent, SmartformComponent, SmartformLayoutDefinitionService, SmarttreeGenericService, SmarttreeService, SubjectSelectorComponent, ThemeService, ToggleLabelPosition, ToolbarAlignment, ToolbarAppearance, ToolbarDirection, TreeArrowPosition, TreeGridControl, USE_ADVANCED_FILTER, UiActionButtonComponent, UiActionButtonType, UiActionConfirmDialogService, UiActionDescriptorService, UiActionDialogButtonComponent, UiActionDialogType, UiActionFeedbackType, UiActionInputDialogService, UiActionInputType, UiActionService, UiActionToolbarComponent, UiActionTooltipTooltipPositionEnum, UiBadgeComponent, UiBadgeDirective, UploadWidgetType, ValidationResultPageComponent, ValueChangeMode, ViewContextRebuiltError, ViewEventHandlerViewEventTypeEnum, ViewService, ViewState, ViewType, barChart, bubbleChart, createBasicOptions, doughnutChart, formatChord, hasGroupEditActions, horizontalBarChart, horizontalStackedBarChart, injectSmartComponent, isMacPlatform, matches, multiAxisLineChart, parseChord, pieChart, polarAreaChart, provideSmartNgClient, radarChart, registerSmartWidget, resolveDateLocale, resolveSlot, resolveSmartNgClientConfig, resolveViewHandler, scatterChart, stackedBarChart, transformDataToBarLikeDataSet, transformDataToBasicDataSets, transformDataToBubble, transformDataToScatter, withSmartDiagram, withSmartMap };
|
|
27133
27966
|
//# sourceMappingURL=smartbit4all-ng-client.mjs.map
|