@smartbit4all/ng-client 7.0.9 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIGRATION-7.0.md +164 -1
- package/fesm2022/smartbit4all-ng-client.mjs +560 -203
- package/fesm2022/smartbit4all-ng-client.mjs.map +1 -1
- package/package.json +1 -1
- package/smartbit4all-ng-client-7.1.0.tgz +0 -0
- package/types/smartbit4all-ng-client.d.ts +136 -20
- package/smartbit4all-ng-client-7.0.9.tgz +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, reflectComponentType, Injectable, inject, DOCUMENT, PLATFORM_ID, Optional, Inject, RendererStyleFlags2, input, computed, Component, HostListener, HostBinding, Directive, ViewContainerRef, ElementRef, Renderer2, ChangeDetectorRef, Input, output, signal, Injector, ViewChild, ViewChildren, effect, afterNextRender, NgZone, forwardRef, Pipe, ChangeDetectionStrategy, ViewEncapsulation, EnvironmentInjector, EventEmitter, Output, ApplicationRef, viewChild, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
|
|
2
|
+
import { InjectionToken, reflectComponentType, Injectable, inject, DOCUMENT, PLATFORM_ID, Optional, Inject, RendererStyleFlags2, input, computed, Component, HostListener, HostBinding, Directive, ViewContainerRef, ElementRef, Renderer2, ChangeDetectorRef, Input, output, signal, Injector, ViewChild, ViewChildren, effect, afterNextRender, NgZone, forwardRef, Pipe, ChangeDetectionStrategy, ViewEncapsulation, SkipSelf, NgModule, EnvironmentInjector, EventEmitter, Output, ApplicationRef, viewChild, makeEnvironmentProviders, importProvidersFrom } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common/http';
|
|
4
4
|
import { HttpHeaders, HttpContext, HttpErrorResponse, HttpParams, provideHttpClient, withInterceptors, withInterceptorsFromDi } from '@angular/common/http';
|
|
5
5
|
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
|
|
@@ -10,6 +10,7 @@ import { enUS, hu } from 'date-fns/locale';
|
|
|
10
10
|
import { isPlatformBrowser, NgClass, NgTemplateOutlet, NgStyle, AsyncPipe, KeyValuePipe, DatePipe, Location, NgIf, NgForOf } from '@angular/common';
|
|
11
11
|
import { Subject, lastValueFrom, tap, takeUntil, throwError, from, interval, startWith, map, distinctUntilChanged, catchError as catchError$1 } from 'rxjs';
|
|
12
12
|
import { catchError, switchMap, takeUntil as takeUntil$1 } from 'rxjs/operators';
|
|
13
|
+
import { deepEqual } from 'fast-equals';
|
|
13
14
|
import { MatButton, MatIconButton, MatMiniFabButton } from '@angular/material/button';
|
|
14
15
|
import { MatTooltip } from '@angular/material/tooltip';
|
|
15
16
|
import { MatIconRegistry, MatIcon } from '@angular/material/icon';
|
|
@@ -22,7 +23,6 @@ import { Validators, UntypedFormGroup, UntypedFormControl, NG_VALUE_ACCESSOR, Fo
|
|
|
22
23
|
import { ENTER, COMMA } from '@angular/cdk/keycodes';
|
|
23
24
|
import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
|
24
25
|
import { MatChipGrid, MatChipRow, MatChipRemove, MatChipInput, MatChip } from '@angular/material/chips';
|
|
25
|
-
import { deepEqual } from 'fast-equals';
|
|
26
26
|
import { set } from 'date-fns';
|
|
27
27
|
import { Overlay, OverlayPositionBuilder, ScrollDispatcher } from '@angular/cdk/overlay';
|
|
28
28
|
import { TemplatePortal } from '@angular/cdk/portal';
|
|
@@ -43,7 +43,6 @@ import { MatMenuTrigger, MatContextMenuTrigger, MatMenu, MatMenuItem } from '@an
|
|
|
43
43
|
import { SelectionModel } from '@angular/cdk/collections';
|
|
44
44
|
import { MatDivider } from '@angular/material/divider';
|
|
45
45
|
import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
|
46
|
-
import { trigger, state, style, transition, animate } from '@angular/animations';
|
|
47
46
|
import { MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, MatCellDef, MatCell, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow } from '@angular/material/table';
|
|
48
47
|
import { NestedTreeControl, FlatTreeControl } from '@angular/cdk/tree';
|
|
49
48
|
import { MatTreeNestedDataSource, MatTree, MatTreeNodeDef, MatNestedTreeNode, MatTreeNodeToggle, MatTreeNodeOutlet, MatTreeFlattener, MatTreeFlatDataSource, MatTreeNode, MatTreeNodePadding } from '@angular/material/tree';
|
|
@@ -2725,6 +2724,18 @@ var MessageType;
|
|
|
2725
2724
|
* Do not edit the class manually.
|
|
2726
2725
|
*/
|
|
2727
2726
|
|
|
2727
|
+
/**
|
|
2728
|
+
* View API
|
|
2729
|
+
* View API
|
|
2730
|
+
*
|
|
2731
|
+
* The version of the OpenAPI document: 1.0.0
|
|
2732
|
+
* Contact: info@it4all.hu
|
|
2733
|
+
*
|
|
2734
|
+
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
2735
|
+
* https://openapi-generator.tech
|
|
2736
|
+
* Do not edit the class manually.
|
|
2737
|
+
*/
|
|
2738
|
+
|
|
2728
2739
|
/**
|
|
2729
2740
|
* View API
|
|
2730
2741
|
* View API
|
|
@@ -2916,18 +2927,6 @@ var UiActionInputType;
|
|
|
2916
2927
|
* Do not edit the class manually.
|
|
2917
2928
|
*/
|
|
2918
2929
|
|
|
2919
|
-
/**
|
|
2920
|
-
* View API
|
|
2921
|
-
* View API
|
|
2922
|
-
*
|
|
2923
|
-
* The version of the OpenAPI document: 1.0.0
|
|
2924
|
-
* Contact: info@it4all.hu
|
|
2925
|
-
*
|
|
2926
|
-
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
2927
|
-
* https://openapi-generator.tech
|
|
2928
|
-
* Do not edit the class manually.
|
|
2929
|
-
*/
|
|
2930
|
-
|
|
2931
2930
|
/**
|
|
2932
2931
|
* View API
|
|
2933
2932
|
* View API
|
|
@@ -3935,6 +3934,15 @@ class SmartViewContextService {
|
|
|
3935
3934
|
this.openSmartLink = new Subject();
|
|
3936
3935
|
this.isOpeningSmartLink = false;
|
|
3937
3936
|
this.dialogRefs = [];
|
|
3937
|
+
this.modelSyncParticipants = new Map();
|
|
3938
|
+
/**
|
|
3939
|
+
* Each view's data as last synced with the backend, a copy. A view whose data is deep-equal
|
|
3940
|
+
* to its copy is left out of the next call; a view without a copy is always sent.
|
|
3941
|
+
*/
|
|
3942
|
+
this.syncedModels = new Map();
|
|
3943
|
+
/** The seq of the envelope (or push) each copy came from, so a late completion cannot roll it back. */
|
|
3944
|
+
this.syncedSeq = new Map();
|
|
3945
|
+
this.modelSyncSeq = 0;
|
|
3938
3946
|
this.embeddedContainers = new Map();
|
|
3939
3947
|
this.embeddedViewRefs = [];
|
|
3940
3948
|
this.pendingEmbeddedViews = [];
|
|
@@ -4035,33 +4043,138 @@ class SmartViewContextService {
|
|
|
4035
4043
|
}
|
|
4036
4044
|
this.embeddedViewRefs = this.embeddedViewRefs.filter((ref) => !orphaned.includes(ref));
|
|
4037
4045
|
}
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
Object.assign(result, this.getCompositeModel(child.uuid));
|
|
4044
|
-
}
|
|
4045
|
-
return result;
|
|
4046
|
-
}
|
|
4047
|
-
submitEmbeddedForms(containerUuid, validate) {
|
|
4046
|
+
/**
|
|
4047
|
+
* Validates the forms of the views embedded under the container, transitively, and collects
|
|
4048
|
+
* their invalid fields into one list for the container's snackbar.
|
|
4049
|
+
*/
|
|
4050
|
+
validateEmbeddedForms(containerUuid) {
|
|
4048
4051
|
const allInvalidKeys = [];
|
|
4049
4052
|
const allInvalidNames = [];
|
|
4050
4053
|
const children = this.embeddedViewRefs.filter((ref) => ref.containerUuid === containerUuid);
|
|
4051
4054
|
for (const child of children) {
|
|
4052
4055
|
const instance = child.componentRef.instance;
|
|
4053
|
-
instance.submitForm(
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
}
|
|
4059
|
-
const nested = this.submitEmbeddedForms(child.uuid, validate);
|
|
4056
|
+
instance.submitForm(true);
|
|
4057
|
+
const invalid = instance.getInvalidFields();
|
|
4058
|
+
allInvalidKeys.push(...invalid.invalidFieldKeys);
|
|
4059
|
+
allInvalidNames.push(...invalid.invalidFieldNames);
|
|
4060
|
+
const nested = this.validateEmbeddedForms(child.uuid);
|
|
4060
4061
|
allInvalidKeys.push(...nested.invalidFieldKeys);
|
|
4061
4062
|
allInvalidNames.push(...nested.invalidFieldNames);
|
|
4062
4063
|
}
|
|
4063
4064
|
return { invalidFieldKeys: allInvalidKeys, invalidFieldNames: allInvalidNames };
|
|
4064
4065
|
}
|
|
4066
|
+
// #region model sync
|
|
4067
|
+
joinModelSync(uuid, participant) {
|
|
4068
|
+
this.modelSyncParticipants.set(uuid, participant);
|
|
4069
|
+
}
|
|
4070
|
+
/**
|
|
4071
|
+
* Only the participant that is registered under the uuid leaves: a component destroyed after
|
|
4072
|
+
* its successor joined under the same uuid must not take the successor with it.
|
|
4073
|
+
*/
|
|
4074
|
+
leaveModelSync(uuid, participant) {
|
|
4075
|
+
if (this.modelSyncParticipants.get(uuid) !== participant) {
|
|
4076
|
+
return;
|
|
4077
|
+
}
|
|
4078
|
+
this.modelSyncParticipants.delete(uuid);
|
|
4079
|
+
this.syncedModels.delete(uuid);
|
|
4080
|
+
this.syncedSeq.delete(uuid);
|
|
4081
|
+
}
|
|
4082
|
+
/**
|
|
4083
|
+
* Records what the backend's model just told the view as in sync. Without keys the view's
|
|
4084
|
+
* whole data is the backend's (initial load, a whole-model push) and becomes the copy. With
|
|
4085
|
+
* keys only those paths of the data were pushed: they are written into the copy, and whatever
|
|
4086
|
+
* else the view holds keeps its standing — an edit written into the data outside the form
|
|
4087
|
+
* while a call was in flight stays unsynced. A view without a copy has nothing to update.
|
|
4088
|
+
*/
|
|
4089
|
+
markModelSynced(uuid, keys) {
|
|
4090
|
+
const participant = this.modelSyncParticipants.get(uuid);
|
|
4091
|
+
if (!participant) {
|
|
4092
|
+
return;
|
|
4093
|
+
}
|
|
4094
|
+
if (!keys) {
|
|
4095
|
+
this.syncedModels.set(uuid, this.cloneModel(uuid, participant.getModel()));
|
|
4096
|
+
}
|
|
4097
|
+
else {
|
|
4098
|
+
const copy = this.syncedModels.get(uuid);
|
|
4099
|
+
const model = participant.getModel();
|
|
4100
|
+
if (copy === undefined || copy === null || model === undefined || model === null) {
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
4103
|
+
for (const key of keys) {
|
|
4104
|
+
setDeep(copy, key, this.cloneModel(uuid, getDeep(model, key)));
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
this.syncedSeq.set(uuid, this.modelSyncSeq);
|
|
4108
|
+
}
|
|
4109
|
+
cloneModel(uuid, model) {
|
|
4110
|
+
try {
|
|
4111
|
+
return structuredClone(model);
|
|
4112
|
+
}
|
|
4113
|
+
catch (err) {
|
|
4114
|
+
const path = uncloneablePath(model);
|
|
4115
|
+
throw new Error(`Model sync: the data of view ${uuid} cannot be cloned` +
|
|
4116
|
+
(path ? ` (at ${path})` : '') +
|
|
4117
|
+
`: ${err.message}`);
|
|
4118
|
+
}
|
|
4119
|
+
}
|
|
4120
|
+
/**
|
|
4121
|
+
* The envelope of the next backend call: the data of every open view that differs from its
|
|
4122
|
+
* last synced copy. Forms are flushed into their data first, so an unsaved field value is
|
|
4123
|
+
* part of what is compared and sent. The envelope is always present, that is what tells the
|
|
4124
|
+
* backend it talks to a client that syncs; a view absent from it means "unchanged".
|
|
4125
|
+
*
|
|
4126
|
+
* The copies taken here become the synced copies when the call succeeds
|
|
4127
|
+
* ({@link completeModelSync}), not the data at response time: what the user types while the
|
|
4128
|
+
* call is in flight must count as unsynced.
|
|
4129
|
+
*/
|
|
4130
|
+
beginModelSync() {
|
|
4131
|
+
const models = {};
|
|
4132
|
+
const snapshots = new Map();
|
|
4133
|
+
for (const [uuid, participant] of this.modelSyncParticipants) {
|
|
4134
|
+
participant.submitForm(false);
|
|
4135
|
+
const model = participant.getModel();
|
|
4136
|
+
if (model === undefined || model === null) {
|
|
4137
|
+
continue;
|
|
4138
|
+
}
|
|
4139
|
+
if (this.syncedModels.has(uuid) && deepEqual(model, this.syncedModels.get(uuid))) {
|
|
4140
|
+
continue;
|
|
4141
|
+
}
|
|
4142
|
+
const snapshot = this.cloneModel(uuid, model);
|
|
4143
|
+
models[uuid] = snapshot;
|
|
4144
|
+
snapshots.set(uuid, snapshot);
|
|
4145
|
+
}
|
|
4146
|
+
return { modelSync: { models }, snapshots, seq: ++this.modelSyncSeq };
|
|
4147
|
+
}
|
|
4148
|
+
/**
|
|
4149
|
+
* Calls run concurrently, so an envelope built earlier may complete later: its copies are
|
|
4150
|
+
* older than what a later envelope or push already settled, and are not written back.
|
|
4151
|
+
*/
|
|
4152
|
+
completeModelSync(pending) {
|
|
4153
|
+
for (const [uuid, snapshot] of pending.snapshots) {
|
|
4154
|
+
if (!this.modelSyncParticipants.has(uuid)) {
|
|
4155
|
+
continue;
|
|
4156
|
+
}
|
|
4157
|
+
if ((this.syncedSeq.get(uuid) ?? -1) > pending.seq) {
|
|
4158
|
+
continue;
|
|
4159
|
+
}
|
|
4160
|
+
this.syncedModels.set(uuid, snapshot);
|
|
4161
|
+
this.syncedSeq.set(uuid, pending.seq);
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
/**
|
|
4165
|
+
* Runs a backend call on a model sync carrier: a request that can bring the models (a
|
|
4166
|
+
* `UiActionRequest`, a `GridSelectionChange`). The envelope goes onto the carrier, the call
|
|
4167
|
+
* runs with it, and a successful call settles the copies the envelope was built from. What
|
|
4168
|
+
* happens to the response is the caller's business.
|
|
4169
|
+
*/
|
|
4170
|
+
async withModelSync(carrier, call) {
|
|
4171
|
+
const pending = this.beginModelSync();
|
|
4172
|
+
carrier.modelSync = pending.modelSync;
|
|
4173
|
+
const viewContextChange = await call(carrier);
|
|
4174
|
+
this.completeModelSync(pending);
|
|
4175
|
+
return viewContextChange;
|
|
4176
|
+
}
|
|
4177
|
+
// #endregion
|
|
4065
4178
|
unregisterEmbeddedSlot(containerUuid, containerId) {
|
|
4066
4179
|
const innerMap = this.embeddedContainers.get(containerUuid);
|
|
4067
4180
|
if (innerMap) {
|
|
@@ -4355,7 +4468,11 @@ class SmartViewContextService {
|
|
|
4355
4468
|
.afterClosed()
|
|
4356
4469
|
.pipe(takeUntil(this._destroy$))
|
|
4357
4470
|
.subscribe(() => {
|
|
4358
|
-
|
|
4471
|
+
// A close the backend ordered (closeView) has already left dialogRefs; only the
|
|
4472
|
+
// user's own close is an action the backend has yet to hear about.
|
|
4473
|
+
if (this.dialogRefs.some((ref) => ref.uuid === view.uuid)) {
|
|
4474
|
+
this.performAction(view.uuid, { code: DefaultUiActionCode_CLOSE, params: {} });
|
|
4475
|
+
}
|
|
4359
4476
|
});
|
|
4360
4477
|
}
|
|
4361
4478
|
}
|
|
@@ -4424,9 +4541,9 @@ class SmartViewContextService {
|
|
|
4424
4541
|
if (view.type === ViewType.DIALOG) {
|
|
4425
4542
|
let dialogRef = this.dialogRefs.find((dialogRef) => dialogRef.uuid === view.uuid);
|
|
4426
4543
|
if (dialogRef) {
|
|
4427
|
-
dialogRef.dialogRef.close();
|
|
4428
4544
|
let index = this.dialogRefs.indexOf(dialogRef);
|
|
4429
4545
|
this.dialogRefs.splice(index, 1);
|
|
4546
|
+
dialogRef.dialogRef.close();
|
|
4430
4547
|
}
|
|
4431
4548
|
else {
|
|
4432
4549
|
// console.log('DialogRef is not found by uuid.');
|
|
@@ -4801,47 +4918,28 @@ class SmartViewContextService {
|
|
|
4801
4918
|
content,
|
|
4802
4919
|
});
|
|
4803
4920
|
}
|
|
4804
|
-
async dataChanged(uuid, dataChange) {
|
|
4805
|
-
return await this._dataChanged({ uuid, dataChange });
|
|
4806
|
-
// const isCompleted = new Subject<void>();
|
|
4807
|
-
// this.apiQueueService.addToQueue(
|
|
4808
|
-
// {
|
|
4809
|
-
// callback: this._dataChanged.bind(this),
|
|
4810
|
-
// config: {
|
|
4811
|
-
// uuid,
|
|
4812
|
-
// dataChange,
|
|
4813
|
-
// },
|
|
4814
|
-
// isCompleted,
|
|
4815
|
-
// },
|
|
4816
|
-
// true
|
|
4817
|
-
// );
|
|
4818
|
-
// return await isCompleted.toPromise();
|
|
4819
|
-
}
|
|
4820
4921
|
async _performAction(config) {
|
|
4821
|
-
return await this.handlePerformActionResponse(await this.view.performAction(config.uuid, config.uiActionRequest).toPromise());
|
|
4922
|
+
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view.performAction(config.uuid, config.uiActionRequest).toPromise()));
|
|
4822
4923
|
}
|
|
4823
4924
|
async _performWidgetAction(config) {
|
|
4824
|
-
return await this.handlePerformActionResponse(await this.view
|
|
4925
|
+
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
4825
4926
|
.performWidgetAction(config.uuid, config.widgetId, config.nodeId, config.uiActionRequest)
|
|
4826
|
-
.toPromise());
|
|
4927
|
+
.toPromise()));
|
|
4827
4928
|
}
|
|
4828
4929
|
async _performWidgetMainAction(config) {
|
|
4829
|
-
return await this.handlePerformActionResponse(await this.view
|
|
4930
|
+
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
4830
4931
|
.performWidgetMainAction(config.uuid, config.widgetId, config.uiActionRequest)
|
|
4831
|
-
.toPromise());
|
|
4932
|
+
.toPromise()));
|
|
4832
4933
|
}
|
|
4833
4934
|
async _performUploadAction(config) {
|
|
4834
|
-
return await this.handlePerformActionResponse(await this.view
|
|
4935
|
+
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
4835
4936
|
.uploadAction(config.uuid, JSON.stringify(config.uiActionRequest), config.param, config.content)
|
|
4836
|
-
.toPromise());
|
|
4937
|
+
.toPromise()));
|
|
4837
4938
|
}
|
|
4838
4939
|
async _performUploadMultipleAction(config) {
|
|
4839
|
-
return await this.handlePerformActionResponse(await this.view
|
|
4940
|
+
return await this.handlePerformActionResponse(await this.withModelSync(config.uiActionRequest, () => this.view
|
|
4840
4941
|
.uploadMultipleAction(config.uuid, JSON.stringify(config.uiActionRequest), config.param, config.content)
|
|
4841
|
-
.toPromise());
|
|
4842
|
-
}
|
|
4843
|
-
async _dataChanged(config) {
|
|
4844
|
-
return await this.handlePerformActionResponse(await this.view.dataChanged(config.uuid, config.dataChange).toPromise());
|
|
4942
|
+
.toPromise()));
|
|
4845
4943
|
}
|
|
4846
4944
|
async handlePerformActionResponse(viewContextChange) {
|
|
4847
4945
|
this.viewContext = viewContextChange?.viewContext;
|
|
@@ -4881,6 +4979,47 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
4881
4979
|
providedIn: 'root',
|
|
4882
4980
|
}]
|
|
4883
4981
|
}], ctorParameters: () => [] });
|
|
4982
|
+
/** Reads the value at a dotted path; a missing segment yields undefined. */
|
|
4983
|
+
function getDeep(model, key) {
|
|
4984
|
+
let value = model;
|
|
4985
|
+
for (const segment of key.split('.')) {
|
|
4986
|
+
if (value === undefined || value === null) {
|
|
4987
|
+
return undefined;
|
|
4988
|
+
}
|
|
4989
|
+
value = value[segment];
|
|
4990
|
+
}
|
|
4991
|
+
return value;
|
|
4992
|
+
}
|
|
4993
|
+
/** Writes the value at a dotted path, creating the objects on the way. */
|
|
4994
|
+
function setDeep(model, key, value) {
|
|
4995
|
+
const segments = key.split('.');
|
|
4996
|
+
let target = model;
|
|
4997
|
+
for (const segment of segments.slice(0, -1)) {
|
|
4998
|
+
if (target[segment] === undefined || target[segment] === null) {
|
|
4999
|
+
target[segment] = {};
|
|
5000
|
+
}
|
|
5001
|
+
target = target[segment];
|
|
5002
|
+
}
|
|
5003
|
+
target[segments[segments.length - 1]] = value;
|
|
5004
|
+
}
|
|
5005
|
+
/** The first path in the value that structuredClone refuses (a function, a DOM node), if any. */
|
|
5006
|
+
function uncloneablePath(value, path = '') {
|
|
5007
|
+
if (typeof value === 'function' || typeof value === 'symbol') {
|
|
5008
|
+
return path || '<root>';
|
|
5009
|
+
}
|
|
5010
|
+
if (typeof Node !== 'undefined' && value instanceof Node) {
|
|
5011
|
+
return path || '<root>';
|
|
5012
|
+
}
|
|
5013
|
+
if (value !== null && typeof value === 'object' && !(value instanceof Date)) {
|
|
5014
|
+
for (const [k, v] of Object.entries(value)) {
|
|
5015
|
+
const found = uncloneablePath(v, path ? `${path}.${k}` : k);
|
|
5016
|
+
if (found) {
|
|
5017
|
+
return found;
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
5020
|
+
}
|
|
5021
|
+
return undefined;
|
|
5022
|
+
}
|
|
4884
5023
|
const IS_ASYNC_PARAM_NAME = 'isAsync';
|
|
4885
5024
|
class ApiQueueService {
|
|
4886
5025
|
constructor() {
|
|
@@ -5133,6 +5272,10 @@ const UI_ACTION_CONFIRM_DIALOG_SERVICE = new InjectionToken('UI_ACTION_CONFIRM_D
|
|
|
5133
5272
|
const UI_ACTION_INPUT_DIALOG_SERVICE = new InjectionToken('UI_ACTION_INPUT_DIALOG_SERVICE');
|
|
5134
5273
|
const UI_ACTION_FILE_UPLOAD_DIALOG_SERVICE = new InjectionToken('UI_ACTION_FILE_UPLOAD_DIALOG_SERVICE');
|
|
5135
5274
|
|
|
5275
|
+
/** A view's own client, as opposed to an executor standing in for another API. */
|
|
5276
|
+
function isViewClient(executor) {
|
|
5277
|
+
return typeof executor.uuid === 'string';
|
|
5278
|
+
}
|
|
5136
5279
|
class UiActionService {
|
|
5137
5280
|
constructor() {
|
|
5138
5281
|
this.confirmDialogService = inject(UI_ACTION_CONFIRM_DIALOG_SERVICE);
|
|
@@ -5168,14 +5311,14 @@ class UiActionService {
|
|
|
5168
5311
|
identifier: uiAction.identifier,
|
|
5169
5312
|
params: uiAction.params ?? {},
|
|
5170
5313
|
};
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5314
|
+
// submit: validate before sending, the embedded views' forms included. The model itself
|
|
5315
|
+
// travels by model sync whatever the flags say; the deprecated `model` flag only keeps
|
|
5316
|
+
// flushing the form of an executor that is not a view.
|
|
5317
|
+
if (uiAction.submit) {
|
|
5318
|
+
executor.submitForm(true);
|
|
5175
5319
|
let invalidFields = executor.getInvalidFields();
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
const embeddedInvalid = this.viewContext.submitEmbeddedForms(containerUuid, validate);
|
|
5320
|
+
if (isViewClient(executor)) {
|
|
5321
|
+
const embeddedInvalid = this.viewContext.validateEmbeddedForms(executor.uuid);
|
|
5179
5322
|
invalidFields = {
|
|
5180
5323
|
invalidFieldKeys: [...invalidFields.invalidFieldKeys, ...embeddedInvalid.invalidFieldKeys],
|
|
5181
5324
|
invalidFieldNames: [
|
|
@@ -5184,11 +5327,14 @@ class UiActionService {
|
|
|
5184
5327
|
],
|
|
5185
5328
|
};
|
|
5186
5329
|
}
|
|
5187
|
-
if (
|
|
5330
|
+
if (invalidFields.invalidFieldKeys.length) {
|
|
5188
5331
|
this.showInvalidFieldsSnackbar(invalidFields);
|
|
5189
5332
|
return;
|
|
5190
5333
|
}
|
|
5191
5334
|
}
|
|
5335
|
+
else if (uiAction.model && !isViewClient(executor)) {
|
|
5336
|
+
executor.submitForm(false);
|
|
5337
|
+
}
|
|
5192
5338
|
if (uiAction.confirm) {
|
|
5193
5339
|
this.confirmDialogService.action = uiAction;
|
|
5194
5340
|
this.confirmDialogService.openDialog();
|
|
@@ -5293,26 +5439,10 @@ class UiActionService {
|
|
|
5293
5439
|
return uiActionRequest;
|
|
5294
5440
|
}
|
|
5295
5441
|
async performAction(uiAction, uiActionRequest, uiActionModel, executor, options) {
|
|
5296
|
-
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
};
|
|
5301
|
-
}
|
|
5302
|
-
else if (uiAction.submit || uiAction.model) {
|
|
5303
|
-
if (options?.widgetId && options?.nodeId) {
|
|
5304
|
-
uiActionRequest.params['clientPageModel'] = { data: executor.getModel() };
|
|
5305
|
-
}
|
|
5306
|
-
else {
|
|
5307
|
-
uiActionRequest.params['model'] = executor.getModel();
|
|
5308
|
-
}
|
|
5309
|
-
}
|
|
5310
|
-
if (uiAction.composite) {
|
|
5311
|
-
const containerUuid = executor.uuid;
|
|
5312
|
-
if (containerUuid) {
|
|
5313
|
-
uiActionRequest.params['compositeModel'] =
|
|
5314
|
-
this.viewContext.getCompositeModel(containerUuid);
|
|
5315
|
-
}
|
|
5442
|
+
// A view's model goes by model sync (SmartViewContextService). An executor that is not a
|
|
5443
|
+
// view (tree, filter editor) has no view to sync, so its model still rides on the request.
|
|
5444
|
+
if (!isViewClient(executor) && (uiAction.submit || uiAction.model)) {
|
|
5445
|
+
uiActionRequest.params['model'] = executor.getModel();
|
|
5316
5446
|
}
|
|
5317
5447
|
try {
|
|
5318
5448
|
await executor.performUiActionRequest(uiActionRequest, options?.widgetId, options?.nodeId);
|
|
@@ -6418,6 +6548,14 @@ class SmartFormService {
|
|
|
6418
6548
|
this.revision = this.revisionState.asReadonly();
|
|
6419
6549
|
this.emptyKey = 'e#m%p@t*y';
|
|
6420
6550
|
this.group = {};
|
|
6551
|
+
/**
|
|
6552
|
+
* The model value each control last agreed with, by control key: what the control was built
|
|
6553
|
+
* or refreshed from, or what it last wrote into the data. A control whose value still equals
|
|
6554
|
+
* it holds no edit of the user's, and a data value that no longer equals it was changed by
|
|
6555
|
+
* the backend. The form's own dirty flag is not this: it lives until the form is rebuilt and
|
|
6556
|
+
* says nothing about what the data holds.
|
|
6557
|
+
*/
|
|
6558
|
+
this.exchanged = new Map();
|
|
6421
6559
|
this.regexRegexChars = new RegExp(/[\.\-\[\]\/\{\}\(\)\+\^\$\\\|]/g);
|
|
6422
6560
|
this.regexAsteriskInTheMiddle = new RegExp(/([^\*])\*([^\*])/g);
|
|
6423
6561
|
this.regexAsteriskInTheEnd = new RegExp(/([^\*])\*$/g);
|
|
@@ -6432,6 +6570,10 @@ class SmartFormService {
|
|
|
6432
6570
|
widgetsChanged() {
|
|
6433
6571
|
this.revisionState.update((revision) => revision + 1);
|
|
6434
6572
|
}
|
|
6573
|
+
/** Forgets the agreed values; the form is being rebuilt from the model. */
|
|
6574
|
+
resetExchangedValues() {
|
|
6575
|
+
this.exchanged.clear();
|
|
6576
|
+
}
|
|
6435
6577
|
getSmartFormWidgetByKey(key) {
|
|
6436
6578
|
return this.findSmartFormWidgetByKey(this.smartForm?.widgets, key);
|
|
6437
6579
|
}
|
|
@@ -6556,6 +6698,12 @@ class SmartFormService {
|
|
|
6556
6698
|
widget = this.findSmartFormWidgetByKey(widgets, key);
|
|
6557
6699
|
if (widget) {
|
|
6558
6700
|
let value = this.getValueDeeply(data, key);
|
|
6701
|
+
// A data value the control already agreed with was not pushed: the control keeps
|
|
6702
|
+
// what it shows, which may be the user's edit.
|
|
6703
|
+
if (this.exchanged.has(key) && deepEqual(value, this.exchanged.get(key))) {
|
|
6704
|
+
continue;
|
|
6705
|
+
}
|
|
6706
|
+
this.exchanged.set(key, structuredClone(value));
|
|
6559
6707
|
if (widget.type === SmartFormWidgetType.CHECK_BOX && typeof value !== 'boolean') {
|
|
6560
6708
|
value = value === 'true';
|
|
6561
6709
|
}
|
|
@@ -6575,6 +6723,8 @@ class SmartFormService {
|
|
|
6575
6723
|
if (widget.showLabel === undefined && smartForm.showLabel) {
|
|
6576
6724
|
widget.showLabel = true;
|
|
6577
6725
|
}
|
|
6726
|
+
// The backend changed this field: its value reaches the control even over an edit.
|
|
6727
|
+
this.group[key]?.setValue(value ?? '', { emitEvent: false });
|
|
6578
6728
|
}
|
|
6579
6729
|
this.copyFromValueSetToValuesList(widget, smartForm.componentModel.valueSets);
|
|
6580
6730
|
}
|
|
@@ -6734,7 +6884,7 @@ class SmartFormService {
|
|
|
6734
6884
|
formControl = new UntypedFormControl();
|
|
6735
6885
|
this.group[key] = formControl;
|
|
6736
6886
|
}
|
|
6737
|
-
formControl.setValue(value
|
|
6887
|
+
formControl.setValue(value ?? '', { emitEvent: false });
|
|
6738
6888
|
formControl.clearValidators();
|
|
6739
6889
|
validators?.map((validator) => {
|
|
6740
6890
|
formControl.addValidators(validator.validator);
|
|
@@ -6800,15 +6950,29 @@ class SmartFormService {
|
|
|
6800
6950
|
}
|
|
6801
6951
|
});
|
|
6802
6952
|
}
|
|
6953
|
+
/**
|
|
6954
|
+
* Copies the user's edits from the controls into the data: only a control whose value differs
|
|
6955
|
+
* from what it last agreed with writes, typed as the data holds the field. Nothing is
|
|
6956
|
+
* submitted; a control the user never touched leaves its field as the backend sent it.
|
|
6957
|
+
*/
|
|
6803
6958
|
toSmartForm(group) {
|
|
6804
6959
|
if (this.smartForm) {
|
|
6805
6960
|
this.copyValueFromFormToWidgetBeans(this.smartForm.widgets, group);
|
|
6806
6961
|
const data = this.smartForm.componentModel?.data;
|
|
6807
6962
|
if (data) {
|
|
6808
6963
|
for (const key of this.getPropertyNamesDeeply(data)) {
|
|
6809
|
-
if (group.controls[key]) {
|
|
6810
|
-
|
|
6964
|
+
if (!group.controls[key]) {
|
|
6965
|
+
continue;
|
|
6966
|
+
}
|
|
6967
|
+
const agreed = this.exchanged.has(key)
|
|
6968
|
+
? this.exchanged.get(key)
|
|
6969
|
+
: this.getValueDeeply(data, key);
|
|
6970
|
+
const value = coerceToTypeOf(agreed, group.controls[key].value);
|
|
6971
|
+
if (this.exchanged.has(key) && deepEqual(value, agreed)) {
|
|
6972
|
+
continue;
|
|
6811
6973
|
}
|
|
6974
|
+
this.setValueDeeply(data, key, value);
|
|
6975
|
+
this.exchanged.set(key, structuredClone(this.getValueDeeply(data, key)));
|
|
6812
6976
|
}
|
|
6813
6977
|
}
|
|
6814
6978
|
}
|
|
@@ -6820,12 +6984,14 @@ class SmartFormService {
|
|
|
6820
6984
|
}
|
|
6821
6985
|
let originalModel = this.smartForm.componentModel.data;
|
|
6822
6986
|
let copyOfModel = { ...originalModel };
|
|
6987
|
+
const exchangedBefore = new Map(this.exchanged);
|
|
6823
6988
|
// copyOfModel should be the current model
|
|
6824
6989
|
this.smartForm.componentModel.data = copyOfModel;
|
|
6825
6990
|
// copy value from FormGroup into model
|
|
6826
6991
|
this.toSmartForm(group);
|
|
6827
6992
|
let newModel = this.smartForm.componentModel.data;
|
|
6828
6993
|
this.smartForm.componentModel.data = originalModel;
|
|
6994
|
+
this.exchanged = exchangedBefore;
|
|
6829
6995
|
return newModel;
|
|
6830
6996
|
}
|
|
6831
6997
|
applyComponentConstraints(widgets, constraints) {
|
|
@@ -7002,6 +7168,32 @@ function extractTime(widgetInstance) {
|
|
|
7002
7168
|
}
|
|
7003
7169
|
return time;
|
|
7004
7170
|
}
|
|
7171
|
+
/**
|
|
7172
|
+
* A control's value in the type its field has in the data. The controls of a boolean or a
|
|
7173
|
+
* number shown as text hold strings; the data keeps the field's type across a round trip.
|
|
7174
|
+
*/
|
|
7175
|
+
function coerceToTypeOf(reference, value) {
|
|
7176
|
+
if (typeof reference === 'boolean') {
|
|
7177
|
+
if (value === 'true') {
|
|
7178
|
+
return true;
|
|
7179
|
+
}
|
|
7180
|
+
if (value === 'false') {
|
|
7181
|
+
return false;
|
|
7182
|
+
}
|
|
7183
|
+
if (value === '') {
|
|
7184
|
+
return null;
|
|
7185
|
+
}
|
|
7186
|
+
}
|
|
7187
|
+
else if (typeof reference === 'number') {
|
|
7188
|
+
if (value === '') {
|
|
7189
|
+
return null;
|
|
7190
|
+
}
|
|
7191
|
+
if (typeof value === 'string' && value.trim() !== '' && !isNaN(Number(value))) {
|
|
7192
|
+
return Number(value);
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
return value;
|
|
7196
|
+
}
|
|
7005
7197
|
|
|
7006
7198
|
/*
|
|
7007
7199
|
* Public API Surface of component-factory-service
|
|
@@ -10761,6 +10953,7 @@ class SmartformComponent {
|
|
|
10761
10953
|
if (!this.originalWidgets || this.originalWidgets.length === 0) {
|
|
10762
10954
|
this.originalWidgets = this.smartForm.widgets;
|
|
10763
10955
|
}
|
|
10956
|
+
this.service.resetExchangedValues();
|
|
10764
10957
|
this.service.setValuesFromModel(this.originalWidgets);
|
|
10765
10958
|
this.service.applyConstraints(this.originalWidgets);
|
|
10766
10959
|
this.smartForm.widgets = this.service.filterWidgetsByVisibility(this.originalWidgets);
|
|
@@ -11243,6 +11436,8 @@ class SmartGridToolbarActionsUtil {
|
|
|
11243
11436
|
}
|
|
11244
11437
|
}
|
|
11245
11438
|
|
|
11439
|
+
/** Id of the detail row's collapse animation, so a second leave call can find the running one. */
|
|
11440
|
+
const DETAIL_COLLAPSE = 'smart-table-detail-collapse';
|
|
11246
11441
|
class Table {
|
|
11247
11442
|
constructor() {
|
|
11248
11443
|
this.cfService = inject(ComponentFactoryService);
|
|
@@ -11252,6 +11447,8 @@ class Table {
|
|
|
11252
11447
|
this.smartTableButtonType = SmartTableButtonType;
|
|
11253
11448
|
this.highlightedRows = [];
|
|
11254
11449
|
this.sortEvent = new Subject();
|
|
11450
|
+
/** The `when` predicate of the detail row definition. */
|
|
11451
|
+
this.isExpandedRow = (_index, row) => row === this.expandedElement;
|
|
11255
11452
|
// Cells to UiAction models, used for toolbars in cells
|
|
11256
11453
|
this.cellToActionMap = {};
|
|
11257
11454
|
this.onSelectionChanged = new Subject();
|
|
@@ -11260,15 +11457,45 @@ class Table {
|
|
|
11260
11457
|
// ---- Toolbar ----
|
|
11261
11458
|
this.defaultActionToolbarId = SmartGridToolbarActionsUtil.defaultActionToolbarId;
|
|
11262
11459
|
this.rowMenuActionModelArrayCache = new Map();
|
|
11460
|
+
// ------------- TREE_GRID -------------
|
|
11461
|
+
this.expandedRowIds = new Set();
|
|
11462
|
+
this.visibleRows = [];
|
|
11463
|
+
this.rowsById = new Map();
|
|
11464
|
+
this.isTreeGrid = false;
|
|
11465
|
+
this.treeInitialized = false;
|
|
11263
11466
|
}
|
|
11264
11467
|
/** The address of the toolbar in this grid's header; `undefined` while it has no id. */
|
|
11265
11468
|
get headerToolbarId() {
|
|
11266
11469
|
return headerToolbarAddress(this.smartTable?.getGridId());
|
|
11267
11470
|
}
|
|
11471
|
+
/**
|
|
11472
|
+
* `animate.leave` of the detail row: collapses the detail the way it expanded, then lets
|
|
11473
|
+
* the row go. A class on the detail itself would not do — the row is what leaves, and
|
|
11474
|
+
* Angular does not look for leave animations behind the `mat-row` component boundary.
|
|
11475
|
+
* Angular calls this once for detaching and once for destroying the row; both wait for
|
|
11476
|
+
* the one animation.
|
|
11477
|
+
*/
|
|
11478
|
+
onDetailRowLeave(event) {
|
|
11479
|
+
const detail = event.target.querySelector('.smart-table-detail');
|
|
11480
|
+
if (!detail) {
|
|
11481
|
+
event.animationComplete();
|
|
11482
|
+
return;
|
|
11483
|
+
}
|
|
11484
|
+
const collapse = detail.getAnimations().find((animation) => animation.id === DETAIL_COLLAPSE) ??
|
|
11485
|
+
detail.animate([{ gridTemplateRows: '1fr' }, { gridTemplateRows: '0fr' }], {
|
|
11486
|
+
id: DETAIL_COLLAPSE,
|
|
11487
|
+
duration: 225,
|
|
11488
|
+
easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
|
|
11489
|
+
fill: 'forwards',
|
|
11490
|
+
});
|
|
11491
|
+
const done = () => event.animationComplete();
|
|
11492
|
+
collapse.finished.then(done, done);
|
|
11493
|
+
}
|
|
11268
11494
|
ngOnInit() {
|
|
11269
11495
|
if (this.smartTable.sortable)
|
|
11270
11496
|
this.sortEvent = new Subject();
|
|
11271
11497
|
this.createCellToActionMap();
|
|
11498
|
+
this.calcTree();
|
|
11272
11499
|
}
|
|
11273
11500
|
ngOnDestroy() {
|
|
11274
11501
|
this._destroy$.next();
|
|
@@ -11298,6 +11525,7 @@ class Table {
|
|
|
11298
11525
|
this.smartTable = smartTable;
|
|
11299
11526
|
// Pushed in by the grid rather than read from it, so nothing else marks this view. The
|
|
11300
11527
|
// pull the rest of the library moved to (ADR-0005) is the 7.1 grid/table merge.
|
|
11528
|
+
this.calcTree();
|
|
11301
11529
|
this.changeDetector.markForCheck();
|
|
11302
11530
|
this.renderRows();
|
|
11303
11531
|
}
|
|
@@ -11621,24 +11849,27 @@ class Table {
|
|
|
11621
11849
|
if (event) {
|
|
11622
11850
|
event?.stopPropagation();
|
|
11623
11851
|
}
|
|
11624
|
-
let oldIndex = this.smartTable.tableRows.findIndex((element) => element === this.expandedElement);
|
|
11625
|
-
if (oldIndex !== -1) {
|
|
11626
|
-
let ref = this.vcRef.filter((element, index) => index === oldIndex);
|
|
11627
|
-
ref[0].clear();
|
|
11628
|
-
}
|
|
11629
11852
|
this.expandedElement = this.expandedElement === element ? null : element;
|
|
11630
|
-
|
|
11853
|
+
// The row definitions are re-evaluated on render only: this drops the old detail row
|
|
11854
|
+
// (and the component in it) and creates the new one, then the query picks it up.
|
|
11855
|
+
this.myTableChild.renderRows();
|
|
11856
|
+
this.changeDetector.detectChanges();
|
|
11857
|
+
if (!this.expandedElement) {
|
|
11858
|
+
return;
|
|
11859
|
+
}
|
|
11860
|
+
const container = this.vcRef.first;
|
|
11631
11861
|
let rowDataResponse;
|
|
11632
|
-
if (
|
|
11633
|
-
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11862
|
+
if (this.smartTable.asyncOnExpand) {
|
|
11863
|
+
this.componentRef = this.cfService.createComponent(container, LoadingComponent, new Map());
|
|
11864
|
+
rowDataResponse = await this.smartTable.rowExpander?.expandAsync(this.smartTable.tableRows.indexOf(element));
|
|
11865
|
+
// Another toggle while loading has already replaced this row's detail row.
|
|
11866
|
+
if (this.expandedElement !== element) {
|
|
11867
|
+
return;
|
|
11638
11868
|
}
|
|
11639
|
-
|
|
11640
|
-
this.element = undefined;
|
|
11869
|
+
container.clear();
|
|
11641
11870
|
}
|
|
11871
|
+
this.componentRef = this.cfService.createComponent(container, this.smartTable.expandedComponent, new Map([['rowData', rowDataResponse]]));
|
|
11872
|
+
this.element = undefined;
|
|
11642
11873
|
}
|
|
11643
11874
|
setSelection(element) {
|
|
11644
11875
|
if (this.smartTable.maxNumOfSelectableRows &&
|
|
@@ -11785,6 +12016,143 @@ class Table {
|
|
|
11785
12016
|
shouldShowMenuButton(row) {
|
|
11786
12017
|
return SmartGridToolbarActionsUtil.showMenu(row, this.smartTable.tableHeaders);
|
|
11787
12018
|
}
|
|
12019
|
+
initializeExpandedRows(rows) {
|
|
12020
|
+
if (this.treeInitialized) {
|
|
12021
|
+
return;
|
|
12022
|
+
}
|
|
12023
|
+
rows.forEach(row => {
|
|
12024
|
+
if (row.id && row.children?.length) {
|
|
12025
|
+
this.expandedRowIds.add(row.id);
|
|
12026
|
+
}
|
|
12027
|
+
});
|
|
12028
|
+
this.treeInitialized = true;
|
|
12029
|
+
}
|
|
12030
|
+
calcTree() {
|
|
12031
|
+
const rows = this.smartTable.tableRows ?? [];
|
|
12032
|
+
this.isTreeGrid = rows.some(row => !!row?.children?.length || !!row?.parent);
|
|
12033
|
+
if (!this.isTreeGrid) {
|
|
12034
|
+
this.visibleRows = rows;
|
|
12035
|
+
return;
|
|
12036
|
+
}
|
|
12037
|
+
// Open all rows on first tree initialization.
|
|
12038
|
+
this.initializeExpandedRows(rows);
|
|
12039
|
+
this.rowsById.clear();
|
|
12040
|
+
rows.forEach(row => {
|
|
12041
|
+
if (row.id) {
|
|
12042
|
+
this.rowsById.set(row.id, row);
|
|
12043
|
+
}
|
|
12044
|
+
});
|
|
12045
|
+
const roots = rows.filter(row => !row.parent);
|
|
12046
|
+
const result = [];
|
|
12047
|
+
const walk = (row) => {
|
|
12048
|
+
result.push(row);
|
|
12049
|
+
if (row.id &&
|
|
12050
|
+
row.children?.length &&
|
|
12051
|
+
this.expandedRowIds.has(row.id)) {
|
|
12052
|
+
row.children
|
|
12053
|
+
.map(childId => this.rowsById.get(childId))
|
|
12054
|
+
.filter((child) => !!child)
|
|
12055
|
+
.forEach(child => walk(child));
|
|
12056
|
+
}
|
|
12057
|
+
};
|
|
12058
|
+
roots.forEach(root => walk(root));
|
|
12059
|
+
this.visibleRows = result;
|
|
12060
|
+
}
|
|
12061
|
+
hasChildren(row) {
|
|
12062
|
+
return !!row?.children?.length;
|
|
12063
|
+
}
|
|
12064
|
+
isRowExpanded(row) {
|
|
12065
|
+
return !!row?.id && this.expandedRowIds.has(row.id);
|
|
12066
|
+
}
|
|
12067
|
+
toggleRowExpansion(row, event) {
|
|
12068
|
+
event?.stopPropagation();
|
|
12069
|
+
if (!row?.id) {
|
|
12070
|
+
return;
|
|
12071
|
+
}
|
|
12072
|
+
if (this.expandedRowIds.has(row.id)) {
|
|
12073
|
+
this.expandedRowIds.delete(row.id);
|
|
12074
|
+
}
|
|
12075
|
+
else {
|
|
12076
|
+
this.expandedRowIds.add(row.id);
|
|
12077
|
+
}
|
|
12078
|
+
this.calcTree();
|
|
12079
|
+
}
|
|
12080
|
+
canExpand() {
|
|
12081
|
+
return this.visibleRows.some(row => this.hasChildren(row) && !this.isRowExpanded(row));
|
|
12082
|
+
}
|
|
12083
|
+
canCollapse() {
|
|
12084
|
+
return this.expandedRowIds.size > 0;
|
|
12085
|
+
}
|
|
12086
|
+
expandOneLevel() {
|
|
12087
|
+
let changed = false;
|
|
12088
|
+
for (const row of this.visibleRows) {
|
|
12089
|
+
if (row.id && this.hasChildren(row) && !this.expandedRowIds.has(row.id)) {
|
|
12090
|
+
this.expandedRowIds.add(row.id);
|
|
12091
|
+
changed = true;
|
|
12092
|
+
}
|
|
12093
|
+
}
|
|
12094
|
+
if (changed) {
|
|
12095
|
+
this.calcTree();
|
|
12096
|
+
}
|
|
12097
|
+
}
|
|
12098
|
+
collapseOneLevel() {
|
|
12099
|
+
let maxLevel = -1;
|
|
12100
|
+
for (const row of this.visibleRows) {
|
|
12101
|
+
if (row.id && this.expandedRowIds.has(row.id)) {
|
|
12102
|
+
maxLevel = Math.max(maxLevel, row.level ?? 0);
|
|
12103
|
+
}
|
|
12104
|
+
}
|
|
12105
|
+
if (maxLevel < 0) {
|
|
12106
|
+
return;
|
|
12107
|
+
}
|
|
12108
|
+
let changed = false;
|
|
12109
|
+
for (const row of this.visibleRows) {
|
|
12110
|
+
if (row.id && this.expandedRowIds.has(row.id) && (row.level ?? 0) === maxLevel) {
|
|
12111
|
+
this.expandedRowIds.delete(row.id);
|
|
12112
|
+
changed = true;
|
|
12113
|
+
}
|
|
12114
|
+
}
|
|
12115
|
+
if (changed) {
|
|
12116
|
+
this.calcTree();
|
|
12117
|
+
}
|
|
12118
|
+
}
|
|
12119
|
+
expandAll() {
|
|
12120
|
+
let changed = false;
|
|
12121
|
+
(this.smartTable.tableRows ?? []).forEach(row => {
|
|
12122
|
+
if (row.id && this.hasChildren(row) && !this.expandedRowIds.has(row.id)) {
|
|
12123
|
+
this.expandedRowIds.add(row.id);
|
|
12124
|
+
changed = true;
|
|
12125
|
+
}
|
|
12126
|
+
});
|
|
12127
|
+
if (changed) {
|
|
12128
|
+
this.calcTree();
|
|
12129
|
+
}
|
|
12130
|
+
}
|
|
12131
|
+
collapseAll() {
|
|
12132
|
+
if (this.expandedRowIds.size === 0) {
|
|
12133
|
+
return;
|
|
12134
|
+
}
|
|
12135
|
+
this.expandedRowIds.clear();
|
|
12136
|
+
this.calcTree();
|
|
12137
|
+
}
|
|
12138
|
+
get expandTreeGridLevel() {
|
|
12139
|
+
return {
|
|
12140
|
+
title: '',
|
|
12141
|
+
color: 'primary',
|
|
12142
|
+
type: UiActionButtonType.MINI_FAB,
|
|
12143
|
+
icon: 'add',
|
|
12144
|
+
iconPosition: IconPosition.PRE,
|
|
12145
|
+
};
|
|
12146
|
+
}
|
|
12147
|
+
get closeTreeGridLevel() {
|
|
12148
|
+
return {
|
|
12149
|
+
title: '',
|
|
12150
|
+
color: 'primary',
|
|
12151
|
+
type: UiActionButtonType.MINI_FAB,
|
|
12152
|
+
icon: 'remove',
|
|
12153
|
+
iconPosition: IconPosition.PRE,
|
|
12154
|
+
};
|
|
12155
|
+
}
|
|
11788
12156
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: Table, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
11789
12157
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.0.8", type: Table, isStandalone: true, selector: "ng-component", inputs: { smartTable: "smartTable" }, viewQueries: [{ propertyName: "myTableChild", first: true, predicate: ["myTable"], descendants: true }, { propertyName: "vcRef", predicate: ["expandedArea"], descendants: true, read: ViewContainerRef }, { propertyName: "defaultActionMenuComponents", predicate: DefaultActionsPopupComponent, descendants: true }, { propertyName: "triggers", predicate: MatMenuTrigger, descendants: true }], ngImport: i0, template: '', isInline: true }); }
|
|
11790
12158
|
}
|
|
@@ -11845,23 +12213,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
11845
12213
|
|
|
11846
12214
|
class MaterialTableComponent extends Table {
|
|
11847
12215
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MaterialTableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
11848
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MaterialTableComponent, isStandalone: true, selector: "lib-material-table", usesInheritance: true, ngImport: i0, template: "<table\n #myTable\n mat-table\n [dataSource]=\"smartTable.tableRows\"\n class=\"full-width\"\n multiTemplateDataRows\n >\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n <ng-container\n matColumnDef=\"{{ header }}\"\n >\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th\n mat-header-cell\n *matHeaderCellDef\n [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\"\n >\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th\n mat-header-cell\n *matHeaderCellDef\n [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\"\n >\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div\n ></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox\n (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\"\n [aria-label]=\"checkboxLabel()\"\n >\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div\n >\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button\n (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\"\n mat-button\n class=\"sortableHeaderButton\"\n >\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon\n class=\"sortableHeaderButtonIcon\"\n title=\"sort\"\n [icon]=\"getSortIcon(header)!\"\n ></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon\n class=\"sortableHeaderButtonIcon\"\n title=\"sort\"\n [icon]=\"getSortNumIcon(header)\"\n ></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \"\n [disabled]=\"isDisabled(element)\"\n [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \"\n [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \"\n >\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div\n >\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div\n >\n <smart-icon\n [smartTooltip]=\"getToolTip(element, i)\"\n [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\"\n >\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div\n class=\"smart-table-buttons-col\"\n >\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button\n (click)=\"customButtonClicked($event, button, element)\"\n mat-icon-button\n color=\"{{ button.color }}\"\n >\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button\n (click)=\"customButtonClicked($event, button, element)\"\n mat-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button\n (click)=\"customButtonClicked($event, button, element)\"\n mat-raised-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getMenuActions(element)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon\n [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\"\n >\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div\n >\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button\n mat-icon-button\n aria-label=\"expand row\"\n (click)=\"onToggle(element, $event)\"\n >\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div\n >\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img\n [src]=\"getValue(element, header)\"\n alt=\"\"\n class=\"smarttableImg\"\n />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n <div\n [innerHtml]=\"getValue(element, header)\"\n ></div>\n }\n </div>\n }\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div\n class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\"\n >\n <ng-template #expandedArea></ng-template>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr\n mat-row\n class=\"example-element-row\"\n [class.example-expanded-row]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\"\n [ngStyle]=\"getRowStyles(element)\"\n (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\"\n [attr.data-testid]=\"element?.id ?? null\"\n ></tr>\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup\n #defaultActionMenu\n [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"\n ></lib-default-actions-popup>\n }\n </ng-container>\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"example-detail-row\"></tr>\n</table>\n", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.example-detail-row{height:0}tr.example-element-row:not(.example-expanded-row):hover{background:#f5f5f5}tr.example-element-row:not(.example-expanded-row):active{background:#efefef}.example-element-row td{border-bottom-width:0}.example-element-detail{overflow:hidden;display:flex;flex-direction:column}.example-element-diagram{min-width:80px;border:2px solid black;padding:8px;font-weight:lighter;margin:8px 0;height:104px}.example-element-symbol{font-weight:700;font-size:40px;line-height:normal}.example-element-description{padding:16px}.example-element-description-attribution{opacity:.5}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}\n"], dependencies: [{ kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: DefaultActionsPopupComponent, selector: "lib-default-actions-popup", inputs: ["buttons", "row", "colIdx"] }, { kind: "pipe", type: SmartDateTimePipe, name: "smartDateTime" }, { kind: "pipe", type: SmartDatePipe, name: "smartDate" }, { kind: "pipe", type: SmartTimePipe, name: "smartTime" }], animations: [
|
|
11849
|
-
trigger('detailExpand', [
|
|
11850
|
-
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
11851
|
-
state('expanded', style({ height: '*' })),
|
|
11852
|
-
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
11853
|
-
]),
|
|
11854
|
-
] }); }
|
|
12216
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: MaterialTableComponent, isStandalone: true, selector: "lib-material-table", usesInheritance: true, ngImport: i0, template: "<table #myTable mat-table [dataSource]=\"isTreeGrid ? visibleRows : smartTable.tableRows\" class=\"full-width\"\n multiTemplateDataRows>\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n\n <ng-container matColumnDef=\"{{ header }}\">\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n\n <!-- ==================== TREE ACTIONS ==================== -->\n @if ( isTreeGrid) {\n <div class=\"tree-grid-actions\">\n\n <ui-action-button (actionClick)=\"expandOneLevel()\" [descriptor]=\"expandTreeGridLevel\">\n </ui-action-button>\n\n\n <ui-action-button (actionClick)=\"collapseOneLevel()\" [descriptor]=\"closeTreeGridLevel\">\n </ui-action-button>\n </div>\n }\n <!-- ==================== TREE ACTIONS ==================== -->\n\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div>\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\" mat-button\n class=\"sortableHeaderButton\">\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortIcon(header)!\"></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortNumIcon(header)\"></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n <div class=\"mat-cell-content\">\n\n\n <!-- ==================== TREE TOGGLE ==================== -->\n @if (isTreeGrid && i === 0) {\n <div class=\"tree-grid-first-column\" [style.padding-left.px]=\"(element.level ?? 0) * 24\">\n @if (hasChildren(element)) {\n <button mat-icon-button type=\"button\" (click)=\"toggleRowExpansion(element, $event)\">\n <smart-icon [icon]=\"\n isRowExpanded(element)\n ? 'keyboard_arrow_down'\n : 'keyboard_arrow_right'\n \"></smart-icon>\n </button>\n } @else {\n <span class=\"tree-grid-spacer\"></span>\n }\n\n </div>\n }\n <!-- ==================== TREE TOGGLE ==================== -->\n\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \" [disabled]=\"isDisabled(element)\" [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \" [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \">\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div>\n <smart-icon [smartTooltip]=\"getToolTip(element, i)\" [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\">\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div class=\"smart-table-buttons-col\">\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-icon-button color=\"{{ button.color }}\">\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-button color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-raised-button\n color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getMenuActions(element)\" [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\" [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\">\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div>\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button mat-icon-button aria-label=\"expand row\" (click)=\"onToggle(element, $event)\">\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div>\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img [src]=\"getValue(element, header)\" alt=\"\" class=\"smarttableImg\" />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n <div [innerHtml]=\"getValue(element, header)\"></div>\n }\n </div>\n }\n\n </div>\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (smartTable.expandable) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div class=\"smart-table-detail\" animate.enter=\"smart-table-detail-enter\">\n <div class=\"smart-table-detail-content\">\n <ng-template #expandedArea></ng-template>\n </div>\n </div>\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr mat-row class=\"smart-table-row\" [class.smart-table-row-expanded]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\" [ngStyle]=\"getRowStyles(element)\" (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\" [attr.data-testid]=\"element?.id ?? null\"></tr>\n\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup #defaultActionMenu [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"></lib-default-actions-popup>\n }\n </ng-container>\n <!-- Only the expanded row has a detail row; no host style can give a collapsed one a height. -->\n @if (smartTable.expandable) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpandedRow\" class=\"smart-table-detail-row\"\n (animate.leave)=\"onDetailRowLeave($event)\"></tr>\n }\n</table>", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.smart-table-row:not(.smart-table-row-expanded):hover{background:#f5f5f5}tr.smart-table-row:not(.smart-table-row-expanded):active{background:#efefef}tr.smart-table-row-expanded td{border-bottom-width:0}tr.smart-table-detail-row{height:0}.smart-table-detail{display:grid;grid-template-rows:1fr}.smart-table-detail-enter{animation:smart-table-detail-expand 225ms cubic-bezier(.4,0,.2,1)}.smart-table-detail-content{min-height:0;overflow:hidden}@keyframes smart-table-detail-expand{0%{grid-template-rows:0fr}to{grid-template-rows:1fr}}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}.tree-grid-actions,.mat-cell-content{display:flex;flex-direction:row;align-items:center}.mat-column-my_menu,.tree-grid-column{width:0}.tree-grid-cell{display:flex;align-items:center;min-height:48px}.tree-grid-expand-button{flex:0 0 auto}.tree-grid-spacer{display:inline-block;width:40px;flex:0 0 40px}.tree-grid-label{min-width:0}\n"], dependencies: [{ kind: "component", type: MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: SmartIconComponent, selector: "smart-icon", inputs: ["icon", "color", "imageResource"] }, { kind: "directive", type: MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: SmartTooltipDirective, selector: "[smartTooltip]", inputs: ["smartTooltip"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "directive", type: MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "component", type: MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "directive", type: MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "component", type: MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: DefaultActionsPopupComponent, selector: "lib-default-actions-popup", inputs: ["buttons", "row", "colIdx"] }, { kind: "pipe", type: SmartDateTimePipe, name: "smartDateTime" }, { kind: "pipe", type: SmartDatePipe, name: "smartDate" }, { kind: "pipe", type: SmartTimePipe, name: "smartTime" }] }); }
|
|
11855
12217
|
}
|
|
11856
12218
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: MaterialTableComponent, decorators: [{
|
|
11857
12219
|
type: Component,
|
|
11858
|
-
args: [{ selector: 'lib-material-table', animations: [
|
|
11859
|
-
trigger('detailExpand', [
|
|
11860
|
-
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
11861
|
-
state('expanded', style({ height: '*' })),
|
|
11862
|
-
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
11863
|
-
]),
|
|
11864
|
-
], imports: [MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, NgClass, NgStyle, UiActionToolbarComponent, MatCheckbox, MatButton, SmartIconComponent, MatCellDef, MatCell, SmartTooltipDirective, MatIconButton, MatMenuTrigger, MatMenu, MatMenuItem, MatDivider, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, DefaultActionsPopupComponent, SmartDateTimePipe, SmartDatePipe, SmartTimePipe], template: "<table\n #myTable\n mat-table\n [dataSource]=\"smartTable.tableRows\"\n class=\"full-width\"\n multiTemplateDataRows\n >\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n <ng-container\n matColumnDef=\"{{ header }}\"\n >\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th\n mat-header-cell\n *matHeaderCellDef\n [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\"\n >\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th\n mat-header-cell\n *matHeaderCellDef\n [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\"\n >\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div\n ></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox\n (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\"\n [aria-label]=\"checkboxLabel()\"\n >\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div\n >\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button\n (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\"\n mat-button\n class=\"sortableHeaderButton\"\n >\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon\n class=\"sortableHeaderButtonIcon\"\n title=\"sort\"\n [icon]=\"getSortIcon(header)!\"\n ></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon\n class=\"sortableHeaderButtonIcon\"\n title=\"sort\"\n [icon]=\"getSortNumIcon(header)\"\n ></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox\n (click)=\"$event.stopPropagation()\"\n (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \"\n [disabled]=\"isDisabled(element)\"\n [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \"\n [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \"\n >\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div\n >\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div\n >\n <smart-icon\n [smartTooltip]=\"getToolTip(element, i)\"\n [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\"\n >\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div\n class=\"smart-table-buttons-col\"\n >\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button\n (click)=\"customButtonClicked($event, button, element)\"\n mat-icon-button\n color=\"{{ button.color }}\"\n >\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button\n (click)=\"customButtonClicked($event, button, element)\"\n mat-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button\n (click)=\"customButtonClicked($event, button, element)\"\n mat-raised-button\n color=\"{{ button.color }}\"\n >\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getMenuActions(element)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon\n [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\"\n >\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div\n >\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button\n mat-icon-button\n aria-label=\"expand row\"\n (click)=\"onToggle(element, $event)\"\n >\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div\n >\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img\n [src]=\"getValue(element, header)\"\n alt=\"\"\n class=\"smarttableImg\"\n />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar\n [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"\n ></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n <div\n [innerHtml]=\"getValue(element, header)\"\n ></div>\n }\n </div>\n }\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div\n class=\"example-element-detail\"\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\"\n >\n <ng-template #expandedArea></ng-template>\n </div>\n </td>\n </ng-container>\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr\n mat-row\n class=\"example-element-row\"\n [class.example-expanded-row]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\"\n [ngStyle]=\"getRowStyles(element)\"\n (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\"\n [attr.data-testid]=\"element?.id ?? null\"\n ></tr>\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup\n #defaultActionMenu\n [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"\n ></lib-default-actions-popup>\n }\n </ng-container>\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']\" class=\"example-detail-row\"></tr>\n</table>\n", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.example-detail-row{height:0}tr.example-element-row:not(.example-expanded-row):hover{background:#f5f5f5}tr.example-element-row:not(.example-expanded-row):active{background:#efefef}.example-element-row td{border-bottom-width:0}.example-element-detail{overflow:hidden;display:flex;flex-direction:column}.example-element-diagram{min-width:80px;border:2px solid black;padding:8px;font-weight:lighter;margin:8px 0;height:104px}.example-element-symbol{font-weight:700;font-size:40px;line-height:normal}.example-element-description{padding:16px}.example-element-description-attribution{opacity:.5}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}\n"] }]
|
|
12220
|
+
args: [{ selector: 'lib-material-table', imports: [MatTable, MatColumnDef, MatHeaderCellDef, MatHeaderCell, NgClass, NgStyle, UiActionToolbarComponent, UiActionButtonComponent, MatCheckbox, MatButton, SmartIconComponent, MatCellDef, MatCell, SmartTooltipDirective, MatIconButton, MatMenuTrigger, MatMenu, MatMenuItem, MatDivider, MatHeaderRowDef, MatHeaderRow, MatRowDef, MatRow, DefaultActionsPopupComponent, SmartDateTimePipe, SmartDatePipe, SmartTimePipe], template: "<table #myTable mat-table [dataSource]=\"isTreeGrid ? visibleRows : smartTable.tableRows\" class=\"full-width\"\n multiTemplateDataRows>\n <!-- Column Descriptor -->\n @if (smartTable.title) {\n <caption class=\"captionTitle\">\n {{ smartTable.title }}\n </caption>\n }\n\n @for (header of smartTable.tableHeaders; track header; let i = $index) {\n\n <ng-container matColumnDef=\"{{ header }}\">\n <!-- my_menu is the implicit action column present on all tables: -->\n @if ('my_menu' === header) {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n\n <!-- ==================== TREE ACTIONS ==================== -->\n @if ( isTreeGrid) {\n <div class=\"tree-grid-actions\">\n\n <ui-action-button (actionClick)=\"expandOneLevel()\" [descriptor]=\"expandTreeGridLevel\">\n </ui-action-button>\n\n\n <ui-action-button (actionClick)=\"collapseOneLevel()\" [descriptor]=\"closeTreeGridLevel\">\n </ui-action-button>\n </div>\n }\n <!-- ==================== TREE ACTIONS ==================== -->\n\n <smart-ui-action-toolbar [id]=\"headerToolbarId\"></smart-ui-action-toolbar>\n </th>\n } @else {\n <th mat-header-cell *matHeaderCellDef [ngClass]=\"getColumnClasses(smartTable.customSmartTableHeaders![i])\"\n [ngStyle]=\"getColumnStyles(smartTable.customSmartTableHeaders![i])\"\n [attr.data-testid]=\"smartTable.customSmartTableHeaders![i].propertyName\">\n @if (\n header === 'icon' || header === 'img' || header === 'options' || header === 'button'\n ) {\n <div></div>\n }\n @if (header === 'select') {\n <div>\n @if (smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\n [checked]=\"smartTable.selection!.hasValue() && isAllSelected()\"\n [indeterminate]=\"smartTable.selection!.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\n </mat-checkbox>\n }\n @if (!smartTable.customSmartTableHeaders![i].showCheckboxInHeader) {\n <div>\n {{ smartTable.customTableHeaders[i] }}\n </div>\n }\n </div>\n }\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'options' &&\n header !== 'button' &&\n header !== 'select' &&\n header !== 'expand' &&\n header !== 'actions'\n ) {\n <div>\n @if (smartTable.sortable) {\n @if (smartTable.sortable && isSortable(smartTable.customSmartTableHeaders![i])) {\n <button (click)=\"sortButtonClicked($event, smartTable.customSmartTableHeaders![i])\" mat-button\n class=\"sortableHeaderButton\">\n {{ smartTable.customTableHeaders[i] }}\n @if (getSortIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortIcon(header)!\"></smart-icon>\n }\n @if (hasSortNumIcon(header)) {\n <smart-icon class=\"sortableHeaderButtonIcon\" title=\"sort\" [icon]=\"getSortNumIcon(header)\"></smart-icon>\n }\n </button>\n }\n } @else {\n {{ smartTable.customTableHeaders[i] }}\n }\n </div>\n }\n </th>\n }\n\n <td mat-cell *matCellDef=\"let element\" [ngClass]=\"isDisabled(element) ? 'disabledRow' : ''\">\n <div class=\"mat-cell-content\">\n\n\n <!-- ==================== TREE TOGGLE ==================== -->\n @if (isTreeGrid && i === 0) {\n <div class=\"tree-grid-first-column\" [style.padding-left.px]=\"(element.level ?? 0) * 24\">\n @if (hasChildren(element)) {\n <button mat-icon-button type=\"button\" (click)=\"toggleRowExpansion(element, $event)\">\n <smart-icon [icon]=\"\n isRowExpanded(element)\n ? 'keyboard_arrow_down'\n : 'keyboard_arrow_right'\n \"></smart-icon>\n </button>\n } @else {\n <span class=\"tree-grid-spacer\"></span>\n }\n\n </div>\n }\n <!-- ==================== TREE TOGGLE ==================== -->\n\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'select' &&\n !isDisabled(element)\n ) {\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"\n $event\n ? setSelection(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n : null\n \" [disabled]=\"isDisabled(element)\" [checked]=\"\n smartTable.selection!.isSelected(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \" [aria-label]=\"\n checkboxLabel(\n smartTable.selectionProperty\n ? smartTable.getValueDeeply(element, smartTable.selectionProperty)\n : element\n )\n \">\n </mat-checkbox>\n }\n @if (\n smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].properties\n ) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATETIME) {\n <div>\n {{\n getValue(element, header)\n | smartDateTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().DATE) {\n <div>\n {{\n getValue(element, header)\n | smartDate: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().TIME) {\n <div>\n {{\n getValue(element, header)\n | smartTime: $safeNavigationMigration(smartTable.customSmartTableHeaders[i].properties?.dateFormat)\n }}\n </div>\n }\n @if (smartTable.customSmartTableHeaders[i].properties?.type === type().CHECKBOX) {\n <div>\n <mat-checkbox [disabled]=\"true\" [checked]=\"getValue(element, header)\"></mat-checkbox>\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders[i].properties?.type === type().ICON &&\n smartTable.customSmartTableHeaders[i].properties?.icons?.length\n ) {\n <div>\n <smart-icon [smartTooltip]=\"getToolTip(element, i)\" [icon]=\"getIcon(getValue(element, header), i)!\"\n [color]=\"getColor(getValue(element, header), i)\">\n </smart-icon>\n </div>\n }\n </div>\n }\n <div class=\"smart-table-icon-container\">\n @for (ir of getImageResourceIcons(element, header); track ir) {\n <div>\n <smart-icon [imageResource]=\"ir\"> </smart-icon>\n </div>\n }\n </div>\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].buttons) {\n <div class=\"smart-table-buttons-col\">\n @for (button of smartTable.customSmartTableHeaders[i].buttons; track button) {\n <div>\n @if (showButton(button, element)) {\n <div>\n @switch (button.type) {\n @case (smartTableButtonType.ICON) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-icon-button color=\"{{ button.color }}\">\n <smart-icon title=\"{{ button.label }}\" [icon]=\"button.icon!\"></smart-icon>\n </button>\n }\n @case (smartTableButtonType.NORMAL) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-button color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n @case (smartTableButtonType.RAISED) {\n <button (click)=\"customButtonClicked($event, button, element)\" mat-raised-button\n color=\"{{ button.color }}\">\n @if (button.icon) {\n <smart-icon [icon]=\"button.icon\"></smart-icon>\n }\n {{ button.label ?? (button.translator ? button.translator(element).title : '') }}\n </button>\n }\n <!------ MENU ------>\n @case (smartTableButtonType.MENU) {\n <div class=\"menu-button\">\n <!------ DEFAULT_ACTION_COLUMN ID TOOLBAR ------>\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, defaultActionToolbarId)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n <!------ GENERIC HAMBURGER ------>\n <!------ TOOLBAR ------>\n @if (shouldShowMenuButton(element)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getMenuActions(element)\" [widgetId]=\"smartTable.getGridId()\"\n [nodeId]=\"element.id\" [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n </div>\n }\n <!------ MENU ------>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n @if (smartTable.customSmartTableHeaders && smartTable.customSmartTableHeaders[i].icon) {\n <div>\n @if (smartTable.customSmartTableHeaders[i].icon?.icon) {\n <smart-icon [ngClass]=\"smartTable.customSmartTableHeaders[i].icon?.cssClass ?? ''\"\n [color]=\"$safeNavigationMigration(smartTable.customSmartTableHeaders[i].icon?.color)\"\n [icon]=\"smartTable.customSmartTableHeaders[i].icon!.icon\">\n </smart-icon>\n }\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].translator !== undefined\n ) {\n <div>\n {{ smartTable.customSmartTableHeaders[i].translator!(getValue(element, header)) }}\n </div>\n }\n @if (\n smartTable.customSmartTableHeaders &&\n smartTable.customSmartTableHeaders[i].propertyName === 'expand'\n ) {\n <button mat-icon-button aria-label=\"expand row\" (click)=\"onToggle(element, $event)\">\n @if (expandedElement !== element) {\n <smart-icon [icon]=\"'keyboard_arrow_down'\"></smart-icon>\n }\n @if (expandedElement === element) {\n <smart-icon [icon]=\"'keyboard_arrow_up'\"></smart-icon>\n }\n </button>\n }\n @if (\n !smartTable.customSmartTableHeaders ||\n (smartTable.customSmartTableHeaders &&\n !smartTable.customSmartTableHeaders[i].properties &&\n !smartTable.customSmartTableHeaders[i].icon &&\n !smartTable.customSmartTableHeaders[i].buttons &&\n !smartTable.customSmartTableHeaders[i].translator &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'select') &&\n !(smartTable.customSmartTableHeaders[i].propertyName === 'expand'))\n ) {\n <div>\n @if (header === 'icon') {\n <smart-icon [icon]=\"getValue(element, header)!\"> </smart-icon>\n }\n @if (header === 'img') {\n <img [src]=\"getValue(element, header)\" alt=\"\" class=\"smarttableImg\" />\n }\n <!------ TOOLBAR ------>\n @if (showCellToolbar(element, header)) {\n <smart-ui-action-toolbar [uiActionModels]=\"getRowColumnAction(element, header)\"\n [widgetId]=\"smartTable.getGridId()\" [nodeId]=\"element.id\"\n [actionParams]=\"{ model: element }\"></smart-ui-action-toolbar>\n }\n <!------ TOOLBAR ------>\n @if (\n header !== 'icon' &&\n header !== 'img' &&\n header !== 'option' &&\n header !== 'button' &&\n !isImageResource(element, header)\n ) {\n <div [innerHtml]=\"getValue(element, header)\"></div>\n }\n </div>\n }\n\n </div>\n </td>\n </ng-container>\n }\n\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\n @if (smartTable.expandable) {\n <ng-container matColumnDef=\"expandedDetail\">\n <td mat-cell *matCellDef=\"let element\" [attr.colspan]=\"smartTable.tableHeaders.length\">\n <div class=\"smart-table-detail\" animate.enter=\"smart-table-detail-enter\">\n <div class=\"smart-table-detail-content\">\n <ng-template #expandedArea></ng-template>\n </div>\n </div>\n </td>\n </ng-container>\n }\n\n <tr mat-header-row *matHeaderRowDef=\"smartTable.tableHeaders; sticky: true\"></tr>\n <ng-container *matRowDef=\"let element; columns: smartTable.tableHeaders\">\n <tr mat-row class=\"smart-table-row\" [class.smart-table-row-expanded]=\"expandedElement === element\"\n [ngClass]=\"getRowClasses(element)\" [ngStyle]=\"getRowStyles(element)\" (click)=\"handleOnRowClick(element)\"\n (dblclick)=\"handleOnRowDoubleClick($event, element)\" [attr.data-testid]=\"element?.id ?? null\"></tr>\n\n @if (smartTable.defaultActionCodes && smartTable.defaultActionCodes.length > 0) {\n <lib-default-actions-popup #defaultActionMenu [buttons]=\"getDefaultActionsForRow(element)!\"\n [row]=\"element\"></lib-default-actions-popup>\n }\n </ng-container>\n <!-- Only the expanded row has a detail row; no host style can give a collapsed one a height. -->\n @if (smartTable.expandable) {\n <tr mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpandedRow\" class=\"smart-table-detail-row\"\n (animate.leave)=\"onDetailRowLeave($event)\"></tr>\n }\n</table>", styles: [".full-width{width:100%}.smarttableImg{width:25px}.smartTableRowHover:hover{cursor:pointer}tr.smart-table-row:not(.smart-table-row-expanded):hover{background:#f5f5f5}tr.smart-table-row:not(.smart-table-row-expanded):active{background:#efefef}tr.smart-table-row-expanded td{border-bottom-width:0}tr.smart-table-detail-row{height:0}.smart-table-detail{display:grid;grid-template-rows:1fr}.smart-table-detail-enter{animation:smart-table-detail-expand 225ms cubic-bezier(.4,0,.2,1)}.smart-table-detail-content{min-height:0;overflow:hidden}@keyframes smart-table-detail-expand{0%{grid-template-rows:0fr}to{grid-template-rows:1fr}}.disabledRow{color:var(--disabled)}.disabledRow:hover{cursor:default}.smart-table-buttons-col{display:flex;flex-direction:row;justify-content:flex-end}.sortableHeaderButton{margin:0!important;padding:0!important;text-align:left!important}.selected{background-color:var(--primary-light-color)}.smart-table-icon-container{display:flex;flex-direction:row;justify-content:space-between;white-space:initial}.reversed{flex-direction:row-reverse;gap:1rem}:host ::ng-deep .mat-mdc-menu-item{line-height:normal!important}.mat-mdc-menu-item[disabled]{cursor:default!important}.menu-button{display:flex;flex-direction:row;justify-content:flex-end;text-align:-webkit-right;align-items:center}.captionTitle{font-size:1.5rem;align-content:center;padding:.5rem .75rem;text-align:start;border-top:1px solid rgba(0,0,0,.12);border-bottom:1px solid rgba(0,0,0,.12);background:#f5f5f5}.tree-grid-actions,.mat-cell-content{display:flex;flex-direction:row;align-items:center}.mat-column-my_menu,.tree-grid-column{width:0}.tree-grid-cell{display:flex;align-items:center;min-height:48px}.tree-grid-expand-button{flex:0 0 auto}.tree-grid-spacer{display:inline-block;width:40px;flex:0 0 40px}.tree-grid-label{min-width:0}\n"] }]
|
|
11865
12221
|
}] });
|
|
11866
12222
|
|
|
11867
12223
|
class MobileTableComponent extends Table {
|
|
@@ -15589,11 +15945,11 @@ class SmarttreeGenericService extends SmarttreeService {
|
|
|
15589
15945
|
let nodeId = uiActionRequest.params['nodeUuid'];
|
|
15590
15946
|
delete uiActionRequest.params['nodeUuid'];
|
|
15591
15947
|
let viewUuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
15592
|
-
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.service.performAction2(viewUuid, this.treeId, nodeId,
|
|
15948
|
+
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync(uiActionRequest, (request) => this.service.performAction2(viewUuid, this.treeId, nodeId, request).toPromise()));
|
|
15593
15949
|
}
|
|
15594
15950
|
async performMainUiActionRequest(uiActionRequest) {
|
|
15595
15951
|
let viewUuid = this.viewContext.getUuidOfPage(this.pageName);
|
|
15596
|
-
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.service.performMainAction2(viewUuid, this.treeId,
|
|
15952
|
+
this.treeFromBackend = await this.viewContext.handlePerformActionResponse(await this.viewContext.withModelSync(uiActionRequest, (request) => this.service.performMainAction2(viewUuid, this.treeId, request).toPromise()));
|
|
15597
15953
|
}
|
|
15598
15954
|
handleSpecificDemandsAsynchronously(uiAction, uiActionRequest) {
|
|
15599
15955
|
throw new Error('Method not implemented.');
|
|
@@ -15635,11 +15991,13 @@ class SmartComponentApiClient {
|
|
|
15635
15991
|
}
|
|
15636
15992
|
if (this.uuid) {
|
|
15637
15993
|
this.viewContext.unfollow(this.uuid);
|
|
15994
|
+
this.viewContext.leaveModelSync(this.uuid, this);
|
|
15638
15995
|
}
|
|
15639
15996
|
this.uuidState.set(uuid);
|
|
15640
15997
|
// Widgets read `widgetUuid` themselves; nothing is pushed into them from here. (ADR-0005)
|
|
15641
15998
|
if (uuid) {
|
|
15642
15999
|
this.viewContext.follow(this.uuid, this.detectChange);
|
|
16000
|
+
this.viewContext.joinModelSync(this.uuid, this);
|
|
15643
16001
|
this.onUuidResolved(uuid);
|
|
15644
16002
|
}
|
|
15645
16003
|
}
|
|
@@ -15729,7 +16087,6 @@ class SmartComponentApiClient {
|
|
|
15729
16087
|
*/
|
|
15730
16088
|
this.commands = new Subject();
|
|
15731
16089
|
this.dataChanged = new Subject();
|
|
15732
|
-
this.sendModelOnWidgetAction = false;
|
|
15733
16090
|
this.inmediateDataChangeKeys = [];
|
|
15734
16091
|
this.blurDataChangeKeys = [];
|
|
15735
16092
|
// check and calculate pageName
|
|
@@ -15766,6 +16123,7 @@ class SmartComponentApiClient {
|
|
|
15766
16123
|
}
|
|
15767
16124
|
_ngOnDestroy() {
|
|
15768
16125
|
this.viewContext.unfollow(this.uuid);
|
|
16126
|
+
this.viewContext.leaveModelSync(this.uuid, this);
|
|
15769
16127
|
this._destroy$.next();
|
|
15770
16128
|
this._destroy$.complete();
|
|
15771
16129
|
}
|
|
@@ -15851,6 +16209,7 @@ class SmartComponentApiClient {
|
|
|
15851
16209
|
// grids are already loaded in setUuid()
|
|
15852
16210
|
this.handleChangeWidgets(this.model.widgets, true);
|
|
15853
16211
|
}
|
|
16212
|
+
this.viewContext.markModelSynced(uuid);
|
|
15854
16213
|
}
|
|
15855
16214
|
async executeUiAction(uiAction, options) {
|
|
15856
16215
|
const uiActionModel = {
|
|
@@ -15877,7 +16236,7 @@ class SmartComponentApiClient {
|
|
|
15877
16236
|
}
|
|
15878
16237
|
let blurIdx = this.blurDataChangeKeys.indexOf(key);
|
|
15879
16238
|
if (blurIdx >= 0) {
|
|
15880
|
-
this.
|
|
16239
|
+
this.blurDataChangeKeys.splice(blurIdx, 1);
|
|
15881
16240
|
}
|
|
15882
16241
|
}
|
|
15883
16242
|
/**
|
|
@@ -15889,7 +16248,6 @@ class SmartComponentApiClient {
|
|
|
15889
16248
|
if (changeKeys.includes(event.key)) {
|
|
15890
16249
|
this.executeUiAction({
|
|
15891
16250
|
code: event.key,
|
|
15892
|
-
model: true,
|
|
15893
16251
|
params: {
|
|
15894
16252
|
item: event.value,
|
|
15895
16253
|
},
|
|
@@ -15935,7 +16293,6 @@ class SmartComponentApiClient {
|
|
|
15935
16293
|
delete uiActionRequest.params['_files'];
|
|
15936
16294
|
delete uiActionRequest.params['_uploadDescriptor'];
|
|
15937
16295
|
delete uiActionRequest.params['isMultiple'];
|
|
15938
|
-
// await this.sendModelToServer();
|
|
15939
16296
|
if (!isMultiple) {
|
|
15940
16297
|
await this.viewContext.performUploadAction(this.uuid, uiActionRequest, param, files[0]);
|
|
15941
16298
|
}
|
|
@@ -15975,38 +16332,15 @@ class SmartComponentApiClient {
|
|
|
15975
16332
|
}
|
|
15976
16333
|
}
|
|
15977
16334
|
else if (widgetId && nodeId) {
|
|
15978
|
-
// await this.sendModelToServer();
|
|
15979
|
-
this.addModelToWidgetAction(uiActionRequest);
|
|
15980
16335
|
await this.viewContext.performWidgetAction(this.uuid, widgetId, nodeId, uiActionRequest);
|
|
15981
16336
|
}
|
|
15982
16337
|
else if (widgetId) {
|
|
15983
|
-
// await this.sendModelToServer();
|
|
15984
|
-
this.addModelToWidgetAction(uiActionRequest);
|
|
15985
16338
|
await this.viewContext.performWidgetMainAction(this.uuid, widgetId, uiActionRequest);
|
|
15986
16339
|
}
|
|
15987
16340
|
else {
|
|
15988
16341
|
await this.viewContext.performAction(this.uuid, uiActionRequest);
|
|
15989
16342
|
}
|
|
15990
16343
|
}
|
|
15991
|
-
addModelToWidgetAction(uiActionRequest) {
|
|
15992
|
-
this.addModelToWidgetParams(uiActionRequest.params);
|
|
15993
|
-
}
|
|
15994
|
-
addModelToWidgetParams(params) {
|
|
15995
|
-
if (this.sendModelOnWidgetAction) {
|
|
15996
|
-
this.submitForm(false);
|
|
15997
|
-
// mimic ComponentModel
|
|
15998
|
-
params['clientPageModel'] = { data: this.getModel() };
|
|
15999
|
-
}
|
|
16000
|
-
}
|
|
16001
|
-
// private async sendModelToServer() {
|
|
16002
|
-
// this.submitForms(false);
|
|
16003
|
-
// let dataChange = {
|
|
16004
|
-
// kind: DataChangeKind.Widget,
|
|
16005
|
-
// source: '',
|
|
16006
|
-
// values: [['', this.getModel()]],
|
|
16007
|
-
// };
|
|
16008
|
-
// await this.viewContext.dataChanged(this.uuid!, dataChange);
|
|
16009
|
-
// }
|
|
16010
16344
|
handleSpecificDemandsAsynchronously(uiAction, uiActionRequest) {
|
|
16011
16345
|
throw new Error('handleSpecificDemandsAsynchronously method not implemented.');
|
|
16012
16346
|
}
|
|
@@ -16056,27 +16390,10 @@ class SmartComponentApiClient {
|
|
|
16056
16390
|
return matData?.uuid;
|
|
16057
16391
|
}
|
|
16058
16392
|
// #region handle changes
|
|
16059
|
-
handleValueChanges(valueChange) {
|
|
16060
|
-
let dataChange;
|
|
16061
|
-
if (valueChange.key.includes('.')) {
|
|
16062
|
-
const source = valueChange.key.split('.')[0];
|
|
16063
|
-
const valueKey = valueChange.key.split('.')[1];
|
|
16064
|
-
dataChange = {
|
|
16065
|
-
kind: valueChange.kind === 'basic' ? DataChangeKind.WIDGET : DataChangeKind.SELECTION,
|
|
16066
|
-
source,
|
|
16067
|
-
values: [[valueKey, valueChange.value]],
|
|
16068
|
-
};
|
|
16069
|
-
}
|
|
16070
|
-
else {
|
|
16071
|
-
dataChange = {
|
|
16072
|
-
kind: valueChange.kind === 'basic' ? DataChangeKind.WIDGET : DataChangeKind.SELECTION,
|
|
16073
|
-
source: valueChange.key,
|
|
16074
|
-
values: [[valueChange.key, valueChange.value]],
|
|
16075
|
-
};
|
|
16076
|
-
}
|
|
16077
|
-
this.viewContext.dataChanged(this.uuid, dataChange);
|
|
16078
|
-
}
|
|
16079
16393
|
handleChanges(change) {
|
|
16394
|
+
// What of the data the push wrote: the paths under `data`, or everything on a whole-model
|
|
16395
|
+
// replacement. Tells the view context how much of the data to take as the backend's.
|
|
16396
|
+
let pushedKeys = [];
|
|
16080
16397
|
try {
|
|
16081
16398
|
if (!this.componentModelLoaded) {
|
|
16082
16399
|
// initial load
|
|
@@ -16091,6 +16408,7 @@ class SmartComponentApiClient {
|
|
|
16091
16408
|
Object.keys(changes).map((changeKey) => {
|
|
16092
16409
|
if (changeKey.startsWith('data.')) {
|
|
16093
16410
|
this.handleDataChange(changes, changeKey);
|
|
16411
|
+
pushedKeys?.push(changeKey.substring('data.'.length));
|
|
16094
16412
|
}
|
|
16095
16413
|
else if (changeKey.startsWith('layouts.') && this.model?.layouts) {
|
|
16096
16414
|
this.handleLayoutChange(changes, changeKey);
|
|
@@ -16110,6 +16428,7 @@ class SmartComponentApiClient {
|
|
|
16110
16428
|
else if (changeKey === '') {
|
|
16111
16429
|
this.model = changes[''];
|
|
16112
16430
|
dataChangeHasBeenNexted = true;
|
|
16431
|
+
pushedKeys = undefined;
|
|
16113
16432
|
}
|
|
16114
16433
|
});
|
|
16115
16434
|
if (!dataChangeHasBeenNexted) {
|
|
@@ -16120,9 +16439,14 @@ class SmartComponentApiClient {
|
|
|
16120
16439
|
catch (error) {
|
|
16121
16440
|
console.error(error);
|
|
16122
16441
|
this.model = change.value;
|
|
16442
|
+
pushedKeys = undefined;
|
|
16123
16443
|
}
|
|
16124
16444
|
if (!change.changedWidgets && !change.changes && change.value) {
|
|
16125
16445
|
this.model = change.value;
|
|
16446
|
+
pushedKeys = undefined;
|
|
16447
|
+
}
|
|
16448
|
+
if (pushedKeys === undefined || pushedKeys.length) {
|
|
16449
|
+
this.viewContext.markModelSynced(this.uuid, pushedKeys);
|
|
16126
16450
|
}
|
|
16127
16451
|
}
|
|
16128
16452
|
/**
|
|
@@ -16276,6 +16600,7 @@ var SmartLayoutDef;
|
|
|
16276
16600
|
SmartLayoutDef["EXPANDABLE"] = "EXPANDABLE";
|
|
16277
16601
|
SmartLayoutDef["CARD"] = "CARD";
|
|
16278
16602
|
SmartLayoutDef["TREE"] = "TREE";
|
|
16603
|
+
SmartLayoutDef["TREE_GRID"] = "TREE_GRID";
|
|
16279
16604
|
})(SmartLayoutDef || (SmartLayoutDef = {}));
|
|
16280
16605
|
var SmartGridButtonType;
|
|
16281
16606
|
(function (SmartGridButtonType) {
|
|
@@ -16979,18 +17304,6 @@ var GridDataAccessConfigKindEnum;
|
|
|
16979
17304
|
})(GridDataAccessConfigKindEnum || (GridDataAccessConfigKindEnum = {}));
|
|
16980
17305
|
;
|
|
16981
17306
|
|
|
16982
|
-
/**
|
|
16983
|
-
* Grid api
|
|
16984
|
-
* The grid api is resposible for the grid components that shows a list of item.
|
|
16985
|
-
*
|
|
16986
|
-
* The version of the OpenAPI document: 1.0.0
|
|
16987
|
-
* Contact: info@it4all.hu
|
|
16988
|
-
*
|
|
16989
|
-
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
|
16990
|
-
* https://openapi-generator.tech
|
|
16991
|
-
* Do not edit the class manually.
|
|
16992
|
-
*/
|
|
16993
|
-
|
|
16994
17307
|
/**
|
|
16995
17308
|
* Grid api
|
|
16996
17309
|
* The grid api is resposible for the grid components that shows a list of item.
|
|
@@ -17031,9 +17344,46 @@ var GridViewDescriptorKindEnum;
|
|
|
17031
17344
|
GridViewDescriptorKindEnum["TABLE"] = "TABLE";
|
|
17032
17345
|
GridViewDescriptorKindEnum["CARDS"] = "CARDS";
|
|
17033
17346
|
GridViewDescriptorKindEnum["TREE"] = "TREE";
|
|
17347
|
+
GridViewDescriptorKindEnum["TREE_GRID"] = "TREE_GRID";
|
|
17034
17348
|
})(GridViewDescriptorKindEnum || (GridViewDescriptorKindEnum = {}));
|
|
17035
17349
|
;
|
|
17036
17350
|
|
|
17351
|
+
class ApiModule {
|
|
17352
|
+
static forRoot(configurationFactory) {
|
|
17353
|
+
return {
|
|
17354
|
+
ngModule: ApiModule,
|
|
17355
|
+
providers: [{ provide: Configuration$2, useFactory: configurationFactory }]
|
|
17356
|
+
};
|
|
17357
|
+
}
|
|
17358
|
+
constructor(parentModule, http) {
|
|
17359
|
+
if (parentModule) {
|
|
17360
|
+
throw new Error('ApiModule is already loaded. Import in your base AppModule only.');
|
|
17361
|
+
}
|
|
17362
|
+
if (!http) {
|
|
17363
|
+
throw new Error('You need to import the HttpClientModule in your AppModule! \n' +
|
|
17364
|
+
'See also https://github.com/angular/angular/issues/20575');
|
|
17365
|
+
}
|
|
17366
|
+
}
|
|
17367
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ApiModule, deps: [{ token: ApiModule, optional: true, skipSelf: true }, { token: i1.HttpClient, optional: true }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
17368
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "22.0.8", ngImport: i0, type: ApiModule }); }
|
|
17369
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ApiModule }); }
|
|
17370
|
+
}
|
|
17371
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: ApiModule, decorators: [{
|
|
17372
|
+
type: NgModule,
|
|
17373
|
+
args: [{
|
|
17374
|
+
imports: [],
|
|
17375
|
+
declarations: [],
|
|
17376
|
+
exports: [],
|
|
17377
|
+
providers: []
|
|
17378
|
+
}]
|
|
17379
|
+
}], ctorParameters: () => [{ type: ApiModule, decorators: [{
|
|
17380
|
+
type: Optional
|
|
17381
|
+
}, {
|
|
17382
|
+
type: SkipSelf
|
|
17383
|
+
}] }, { type: i1.HttpClient, decorators: [{
|
|
17384
|
+
type: Optional
|
|
17385
|
+
}] }] });
|
|
17386
|
+
|
|
17037
17387
|
class TableLayoutDefinerComponent {
|
|
17038
17388
|
constructor() {
|
|
17039
17389
|
this.data = inject(MAT_DIALOG_DATA);
|
|
@@ -17219,6 +17569,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
17219
17569
|
args: ['forms']
|
|
17220
17570
|
}] } });
|
|
17221
17571
|
|
|
17572
|
+
/** The model sync carrier of a selection call; the view context puts the envelope on it. */
|
|
17573
|
+
function selection(selected, unselected) {
|
|
17574
|
+
return { selected, unselected, params: {} };
|
|
17575
|
+
}
|
|
17222
17576
|
class SmartGridService {
|
|
17223
17577
|
constructor() {
|
|
17224
17578
|
this.api = inject(GridService);
|
|
@@ -17256,27 +17610,19 @@ class SmartGridService {
|
|
|
17256
17610
|
}
|
|
17257
17611
|
async select(smartGrid, gridRow) {
|
|
17258
17612
|
gridRow.selected = !gridRow.selected;
|
|
17259
|
-
|
|
17260
|
-
return await this.api
|
|
17613
|
+
return await smartGrid.viewContextService.withModelSync(selection([], []), (gridSelectionChange) => this.api
|
|
17261
17614
|
.select(smartGrid.gridModel.viewUuid, smartGrid.gridIdentifier, gridRow.id, gridRow.selected, gridSelectionChange)
|
|
17262
|
-
.toPromise();
|
|
17615
|
+
.toPromise());
|
|
17263
17616
|
}
|
|
17264
17617
|
async selectRows(smartGrid, selected, unselected) {
|
|
17265
|
-
|
|
17266
|
-
return await this.api
|
|
17618
|
+
return await smartGrid.viewContextService.withModelSync(selection(selected, unselected), (gridSelectionChange) => this.api
|
|
17267
17619
|
.selectRows(smartGrid.gridModel.viewUuid, smartGrid.gridIdentifier, gridSelectionChange)
|
|
17268
|
-
.toPromise();
|
|
17620
|
+
.toPromise());
|
|
17269
17621
|
}
|
|
17270
17622
|
async selectAll(smartGrid, selected) {
|
|
17271
|
-
|
|
17272
|
-
return await this.api
|
|
17623
|
+
return await smartGrid.viewContextService.withModelSync(selection([], []), (gridSelectionChange) => this.api
|
|
17273
17624
|
.selectAll(smartGrid.gridModel.viewUuid, smartGrid.gridIdentifier, selected, gridSelectionChange)
|
|
17274
|
-
.toPromise();
|
|
17275
|
-
}
|
|
17276
|
-
buildGridSelectionChange(smartGrid, selected, unselected) {
|
|
17277
|
-
const gridSelectionChange = { selected, unselected, params: {} };
|
|
17278
|
-
smartGrid.serviceToUse?.addModelToWidgetParams?.(gridSelectionChange.params);
|
|
17279
|
-
return gridSelectionChange;
|
|
17625
|
+
.toPromise());
|
|
17280
17626
|
}
|
|
17281
17627
|
async update(uuid, identifier, updateData) {
|
|
17282
17628
|
if (!updateData.pageSize) {
|
|
@@ -17821,6 +18167,9 @@ class SmartGridComponent {
|
|
|
17821
18167
|
if (kind === GridViewDescriptorKindEnum.TABLE) {
|
|
17822
18168
|
layoutDef = SmartLayoutDef.TABLE;
|
|
17823
18169
|
}
|
|
18170
|
+
else if (kind === GridViewDescriptorKindEnum.TREE_GRID) {
|
|
18171
|
+
layoutDef = SmartLayoutDef.TREE_GRID;
|
|
18172
|
+
}
|
|
17824
18173
|
else if (kind === GridViewDescriptorKindEnum.TREE) {
|
|
17825
18174
|
layoutDef = SmartLayoutDef.TREE;
|
|
17826
18175
|
}
|
|
@@ -17846,6 +18195,9 @@ class SmartGridComponent {
|
|
|
17846
18195
|
if (this.smartGrid.layoutDef === SmartLayoutDef.TABLE) {
|
|
17847
18196
|
this.renderTable();
|
|
17848
18197
|
}
|
|
18198
|
+
else if (this.smartGrid.layoutDef === SmartLayoutDef.TREE_GRID) {
|
|
18199
|
+
this.renderTable();
|
|
18200
|
+
}
|
|
17849
18201
|
else if (this.smartGrid.layoutDef === SmartLayoutDef.EXPANDABLE) {
|
|
17850
18202
|
this.renderExpandableSections();
|
|
17851
18203
|
}
|
|
@@ -17883,7 +18235,7 @@ class SmartGridComponent {
|
|
|
17883
18235
|
else {
|
|
17884
18236
|
this.tableType = SmartTableType.INHERITED;
|
|
17885
18237
|
}
|
|
17886
|
-
if (this.smartGrid.layoutDef === SmartLayoutDef.TABLE) {
|
|
18238
|
+
if (this.smartGrid.layoutDef === SmartLayoutDef.TABLE || this.smartGrid.layoutDef === SmartLayoutDef.TREE_GRID) {
|
|
17887
18239
|
let tableConfig = {
|
|
17888
18240
|
...this.smartGrid.tableConfig,
|
|
17889
18241
|
title: this.smartGrid?.gridModel.title,
|
|
@@ -18413,12 +18765,21 @@ class SmartGridComponent {
|
|
|
18413
18765
|
};
|
|
18414
18766
|
this.dialog.open(TableLayoutDefinerComponent, { data: dialogData });
|
|
18415
18767
|
}
|
|
18768
|
+
get showEditColumns() {
|
|
18769
|
+
return {
|
|
18770
|
+
title: '',
|
|
18771
|
+
color: 'primary',
|
|
18772
|
+
type: UiActionButtonType.MINI_FAB,
|
|
18773
|
+
icon: 'view_columns',
|
|
18774
|
+
iconPosition: IconPosition.PRE,
|
|
18775
|
+
};
|
|
18776
|
+
}
|
|
18416
18777
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartGridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
18417
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartGridComponent, isStandalone: true, selector: "smart-grid", inputs: { smartGrid: { classPropertyName: "smartGrid", publicName: "smartGrid", isSignal: false, isRequired: false, transformFunction: null }, uuid: { classPropertyName: "uuid", publicName: "uuid", isSignal: false, isRequired: false, transformFunction: null }, parentLayoutComponent: { classPropertyName: "parentLayoutComponent", publicName: "parentLayoutComponent", isSignal: true, isRequired: false, transformFunction: null }, dev: { classPropertyName: "dev", publicName: "dev", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-testid": "this.testId" } }, providers: [SmartGridService], viewQueries: [{ propertyName: "vcRefTable", first: true, predicate: ["table"], descendants: true, read: ViewContainerRef }, { propertyName: "expandedRowsComps", predicate: ExpandedRowRendererComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (smartGrid) {\n
|
|
18778
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: SmartGridComponent, isStandalone: true, selector: "smart-grid", inputs: { smartGrid: { classPropertyName: "smartGrid", publicName: "smartGrid", isSignal: false, isRequired: false, transformFunction: null }, uuid: { classPropertyName: "uuid", publicName: "uuid", isSignal: false, isRequired: false, transformFunction: null }, parentLayoutComponent: { classPropertyName: "parentLayoutComponent", publicName: "parentLayoutComponent", isSignal: true, isRequired: false, transformFunction: null }, dev: { classPropertyName: "dev", publicName: "dev", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-testid": "this.testId" } }, providers: [SmartGridService], viewQueries: [{ propertyName: "vcRefTable", first: true, predicate: ["table"], descendants: true, read: ViewContainerRef }, { propertyName: "expandedRowsComps", predicate: ExpandedRowRendererComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "@if (smartGrid) {\n<div class=\"smartGrid-container\">\n <div class=\"smart-grid-toolbar\">\n <smart-ui-action-toolbar [id]=\"toolbarId\"></smart-ui-action-toolbar>\n @if (smartGrid.showEditColumns) {\n <ui-action-button (actionClick)=\"editColumns()\" [descriptor]=\"showEditColumns\">\n </ui-action-button>\n }\n </div>\n <!-- <div [ngClass]=\"isBlocked ? 'blocked' : ''\"></div> -->\n <div class=\"smartGridContent\">\n <div>\n @if (smartGrid.showResultCount) {\n <div>\n <div class=\"smartGrid-data-number\">\n {{ smartGrid.gridModel.totalRowCount }}\n </div>\n </div>\n }\n </div>\n <div class=\"smart-grid-table-container\">\n <ng-template #table></ng-template>\n </div>\n @if (smartGrid.layoutDef === layoutDef().EXPANDABLE) {\n <div>\n @for (expandableSection of expandableSections; track expandableSection) {\n <smart-expandable-section #gridExpandableSection [data]=\"expandableSection\"></smart-expandable-section>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().CARD && smartGrid.dataLayoutDef) {\n <div class=\"cards-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n @for (row of smartGrid.gridModel.page.rows; track row.id) {\n <app-smart-grid-card class=\"smartGrid-card-container\" [class.clickable-row]=\"row.layoutDescriptor\"\n (click)=\"row.layoutDescriptor && onClick(row)\" [item]=\"row\" [smartGrid]=\"smartGrid\"\n [parentLayoutComponent]=\"parentLayoutComponent()\"></app-smart-grid-card>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().TREE && treeControl) {\n <div class=\"tree-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n <mat-tree [dataSource]=\"treeDataSource!\" [treeControl]=\"treeControl!\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button disabled class=\"tree-button\"></button>\n <mat-checkbox class=\"checklist-leaf-node\"\n [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n (change)=\"treeNodeSelectionToggle(node)\">{{ getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button matTreeNodeToggle class=\"tree-button\" [attr.aria-label]=\"'Toggle ' + node.item\">\n <mat-icon class=\"mat-icon-rtl-mirror\">\n {{ treeControl!.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-checkbox [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n [indeterminate]=\"descendantsPartiallySelected(node)\" (change)=\"treeNodeSelectionToggle(node)\">{{\n getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n </mat-tree>\n </div>\n }\n </div>\n @if (smartGrid.paginator) {\n <div class=\"paginator-row-material\">\n @if (smartGrid.gridModel.refreshEnabled) {\n <button mat-icon-button type=\"button\" matTooltip=\"Friss\u00EDt\u00E9s\" (click)=\"refreshPartialResults()\">\n <mat-icon>refresh</mat-icon>\n </button>\n }\n @if (smartGrid.paginator && !treeControl) {\n <mat-paginator #paginator [length]=\"length\" [pageIndex]=\"pageIndex\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" (page)=\"onChangePage($event)\"></mat-paginator>\n }\n </div>\n }\n</div>\n}", styles: [".smartGrid-container{position:relative;padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.smartGrid-data-number{padding-bottom:1rem}.cards-container{display:grid;gap:1rem;padding:1rem}.smartGrid-container ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-underline{bottom:0}.smartGridContent{width:100%;flex:1;overflow:auto}.blocked{position:absolute;width:calc(100% - 3rem);height:calc(100% - 3rem);z-index:110;background-color:#0003}.smart-grid-table-container{display:flex;flex-direction:column;gap:1rem}.smart-grid-toolbar{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.smart-grid-toolbar smart-ui-action-toolbar{width:100%}.smart-grid-edit-icon{color:var(--light-gray)}.tree-button{width:24px!important;height:24px!important}.paginator-row-material{display:flex;align-items:center;align-self:flex-end;gap:.25rem}.clickable-row{cursor:pointer}\n"], dependencies: [{ kind: "component", type: UiActionToolbarComponent, selector: "smart-ui-action-toolbar", inputs: ["uiActionModels", "uiActionDescriptorService", "id", "executor", "widgetId", "nodeId", "actionParams", "scrollOnWrap", "toolbarPropertes"] }, { kind: "component", type: UiActionButtonComponent, selector: "ui-action-button", inputs: ["disabled", "descriptor", "code", "identifier", "viewActivated", "addedCssClass", "addBasicClasses", "iconPlaceholder"], outputs: ["actionClick", "actionDoubleClick"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ExpandableSectionComponent, selector: "smart-expandable-section", inputs: ["data", "index"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SmartGridCardComponent, selector: "app-smart-grid-card", inputs: ["item", "smartGrid", "parentLayoutComponent"] }, { kind: "component", type: MatTree, selector: "mat-tree", exportAs: ["matTree"] }, { kind: "directive", type: MatTreeNodeDef, selector: "[matTreeNodeDef]", inputs: ["matTreeNodeDefWhen", "matTreeNode"] }, { kind: "directive", type: MatTreeNode, selector: "mat-tree-node", inputs: ["tabIndex", "disabled"], outputs: ["activation", "expandedChange"], exportAs: ["matTreeNode"] }, { kind: "directive", type: MatTreeNodeToggle, selector: "[matTreeNodeToggle]", inputs: ["matTreeNodeToggleRecursive"] }, { kind: "directive", type: MatTreeNodePadding, selector: "[matTreeNodePadding]", inputs: ["matTreeNodePadding", "matTreeNodePaddingIndent"] }, { kind: "component", type: MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "directive", type: MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: MatPaginator, selector: "mat-paginator", inputs: ["color", "pageIndex", "length", "pageSize", "pageSizeOptions", "hidePageSize", "showFirstLastButtons", "selectConfig", "disabled"], outputs: ["page"], exportAs: ["matPaginator"] }] }); }
|
|
18418
18779
|
}
|
|
18419
18780
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: SmartGridComponent, decorators: [{
|
|
18420
18781
|
type: Component,
|
|
18421
|
-
args: [{ selector: 'smart-grid', providers: [SmartGridService], imports: [UiActionToolbarComponent, MatMiniFabButton, MatIcon, ExpandableSectionComponent, NgStyle, SmartGridCardComponent, MatTree, MatTreeNodeDef, MatTreeNode, MatTreeNodeToggle, MatTreeNodePadding, MatIconButton, MatCheckbox, MatTooltip, MatPaginator], template: "@if (smartGrid) {\n
|
|
18782
|
+
args: [{ selector: 'smart-grid', providers: [SmartGridService], imports: [UiActionToolbarComponent, UiActionButtonComponent, MatMiniFabButton, MatIcon, ExpandableSectionComponent, NgStyle, SmartGridCardComponent, MatTree, MatTreeNodeDef, MatTreeNode, MatTreeNodeToggle, MatTreeNodePadding, MatIconButton, MatCheckbox, MatTooltip, MatPaginator], template: "@if (smartGrid) {\n<div class=\"smartGrid-container\">\n <div class=\"smart-grid-toolbar\">\n <smart-ui-action-toolbar [id]=\"toolbarId\"></smart-ui-action-toolbar>\n @if (smartGrid.showEditColumns) {\n <ui-action-button (actionClick)=\"editColumns()\" [descriptor]=\"showEditColumns\">\n </ui-action-button>\n }\n </div>\n <!-- <div [ngClass]=\"isBlocked ? 'blocked' : ''\"></div> -->\n <div class=\"smartGridContent\">\n <div>\n @if (smartGrid.showResultCount) {\n <div>\n <div class=\"smartGrid-data-number\">\n {{ smartGrid.gridModel.totalRowCount }}\n </div>\n </div>\n }\n </div>\n <div class=\"smart-grid-table-container\">\n <ng-template #table></ng-template>\n </div>\n @if (smartGrid.layoutDef === layoutDef().EXPANDABLE) {\n <div>\n @for (expandableSection of expandableSections; track expandableSection) {\n <smart-expandable-section #gridExpandableSection [data]=\"expandableSection\"></smart-expandable-section>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().CARD && smartGrid.dataLayoutDef) {\n <div class=\"cards-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n @for (row of smartGrid.gridModel.page.rows; track row.id) {\n <app-smart-grid-card class=\"smartGrid-card-container\" [class.clickable-row]=\"row.layoutDescriptor\"\n (click)=\"row.layoutDescriptor && onClick(row)\" [item]=\"row\" [smartGrid]=\"smartGrid\"\n [parentLayoutComponent]=\"parentLayoutComponent()\"></app-smart-grid-card>\n }\n </div>\n }\n @if (smartGrid.layoutDef === layoutDef().TREE && treeControl) {\n <div class=\"tree-container\" [ngStyle]=\"{\n 'grid-template-columns':\n smartGrid.numberOfColumn !== undefined\n ? 'repeat(' + smartGrid.numberOfColumn + ', 1fr)'\n : '',\n }\">\n <mat-tree [dataSource]=\"treeDataSource!\" [treeControl]=\"treeControl!\">\n <mat-tree-node *matTreeNodeDef=\"let node\" matTreeNodeToggle matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button disabled class=\"tree-button\"></button>\n <mat-checkbox class=\"checklist-leaf-node\"\n [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n (change)=\"treeNodeSelectionToggle(node)\">{{ getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n <mat-tree-node *matTreeNodeDef=\"let node; when: hasChild\" matTreeNodePadding matTreeNodePaddingIndent=\"24\">\n <button mat-icon-button matTreeNodeToggle class=\"tree-button\" [attr.aria-label]=\"'Toggle ' + node.item\">\n <mat-icon class=\"mat-icon-rtl-mirror\">\n {{ treeControl!.isExpanded(node) ? 'expand_more' : 'chevron_right' }}\n </mat-icon>\n </button>\n <mat-checkbox [checked]=\"$safeNavigationMigration(treeChecklistSelection?.isSelected(node))\"\n [indeterminate]=\"descendantsPartiallySelected(node)\" (change)=\"treeNodeSelectionToggle(node)\">{{\n getTreeItem(node) }}</mat-checkbox>\n </mat-tree-node>\n </mat-tree>\n </div>\n }\n </div>\n @if (smartGrid.paginator) {\n <div class=\"paginator-row-material\">\n @if (smartGrid.gridModel.refreshEnabled) {\n <button mat-icon-button type=\"button\" matTooltip=\"Friss\u00EDt\u00E9s\" (click)=\"refreshPartialResults()\">\n <mat-icon>refresh</mat-icon>\n </button>\n }\n @if (smartGrid.paginator && !treeControl) {\n <mat-paginator #paginator [length]=\"length\" [pageIndex]=\"pageIndex\" [pageSize]=\"pageSize\"\n [pageSizeOptions]=\"pageSizeOptions\" (page)=\"onChangePage($event)\"></mat-paginator>\n }\n </div>\n }\n</div>\n}", styles: [".smartGrid-container{position:relative;padding:1.5rem;display:flex;flex-direction:column;gap:1rem}.smartGrid-data-number{padding-bottom:1rem}.cards-container{display:grid;gap:1rem;padding:1rem}.smartGrid-container ::ng-deep .mat-form-field-appearance-legacy .mat-form-field-underline{bottom:0}.smartGridContent{width:100%;flex:1;overflow:auto}.blocked{position:absolute;width:calc(100% - 3rem);height:calc(100% - 3rem);z-index:110;background-color:#0003}.smart-grid-table-container{display:flex;flex-direction:column;gap:1rem}.smart-grid-toolbar{display:flex;flex-direction:row;justify-content:flex-end;align-items:center}.smart-grid-toolbar smart-ui-action-toolbar{width:100%}.smart-grid-edit-icon{color:var(--light-gray)}.tree-button{width:24px!important;height:24px!important}.paginator-row-material{display:flex;align-items:center;align-self:flex-end;gap:.25rem}.clickable-row{cursor:pointer}\n"] }]
|
|
18422
18783
|
}], ctorParameters: () => [], propDecorators: { smartGrid: [{
|
|
18423
18784
|
type: Input
|
|
18424
18785
|
}], uuid: [{
|
|
@@ -22374,7 +22735,6 @@ class GenericPageComponent extends SmartComponent {
|
|
|
22374
22735
|
/** Written from `dataChanged`, so a signal — the page has no template event that would. */
|
|
22375
22736
|
this.componentLayoutState = signal(undefined, /* @ts-ignore */
|
|
22376
22737
|
...(ngDevMode ? [{ debugName: "componentLayoutState" }] : /* istanbul ignore next */ []));
|
|
22377
|
-
this.sendModelOnWidgetAction = true;
|
|
22378
22738
|
this.dataChanged.pipe(takeUntil(this._destroy$)).subscribe(() => {
|
|
22379
22739
|
if (this.model?.componentLayouts) {
|
|
22380
22740
|
this.setUpComponentLayout();
|
|
@@ -22436,7 +22796,6 @@ class SearchPageComponent extends SmartComponent {
|
|
|
22436
22796
|
this.layoutComponent = viewChild(SmartComponentLayoutComponent, /* @ts-ignore */
|
|
22437
22797
|
...(ngDevMode ? [{ debugName: "layoutComponent" }] : /* istanbul ignore next */ []));
|
|
22438
22798
|
this.setupGrid();
|
|
22439
|
-
this.sendModelOnWidgetAction = true;
|
|
22440
22799
|
// uuid is set in onUuidResolved — it is not known at construction for
|
|
22441
22800
|
// dynamic default-component views. (#28870)
|
|
22442
22801
|
this.filterService.config = {
|
|
@@ -23357,7 +23716,6 @@ class NoPermissionPageComponent extends SmartComponent {
|
|
|
23357
23716
|
/** Written from `dataChanged`, so a signal. */
|
|
23358
23717
|
this.componentLayoutState = signal(undefined, /* @ts-ignore */
|
|
23359
23718
|
...(ngDevMode ? [{ debugName: "componentLayoutState" }] : /* istanbul ignore next */ []));
|
|
23360
|
-
this.sendModelOnWidgetAction = true;
|
|
23361
23719
|
this.dataChanged.pipe(takeUntil(this._destroy$)).subscribe(() => {
|
|
23362
23720
|
if (this.model?.componentLayouts) {
|
|
23363
23721
|
this.setUpComponentLayout();
|
|
@@ -23399,7 +23757,6 @@ class InvalidSmartlinkComponent extends SmartComponent {
|
|
|
23399
23757
|
/** Written from `dataChanged`, so a signal. */
|
|
23400
23758
|
this.componentLayoutState = signal(undefined, /* @ts-ignore */
|
|
23401
23759
|
...(ngDevMode ? [{ debugName: "componentLayoutState" }] : /* istanbul ignore next */ []));
|
|
23402
|
-
this.sendModelOnWidgetAction = true;
|
|
23403
23760
|
this.dataChanged.pipe(takeUntil(this._destroy$)).subscribe(() => {
|
|
23404
23761
|
if (this.model?.componentLayouts) {
|
|
23405
23762
|
this.setUpComponentLayout();
|