@masterteam/work-center 0.0.54 → 0.0.56
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.
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import * as i1$1 from '@angular/common';
|
|
1
2
|
import { CommonModule } from '@angular/common';
|
|
2
3
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, viewChild, input, computed, signal, Component, Injectable, DestroyRef,
|
|
4
|
+
import { inject, viewChild, input, computed, signal, Component, Injectable, DestroyRef, effect, untracked, output } from '@angular/core';
|
|
4
5
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
5
6
|
import { TranslocoService, TranslocoDirective } from '@jsverse/transloco';
|
|
6
7
|
import { Button } from '@masterteam/components/button';
|
|
@@ -15,17 +16,17 @@ import { catchError, EMPTY, map, take } from 'rxjs';
|
|
|
15
16
|
import { ModalRef } from '@masterteam/components/dialog';
|
|
16
17
|
import { DrawerController } from '@masterteam/components/dynamic-drawer';
|
|
17
18
|
import { ClientForm } from '@masterteam/forms/client-form';
|
|
18
|
-
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
19
19
|
import { HttpClient } from '@angular/common/http';
|
|
20
|
+
import { Router, ActivatedRoute } from '@angular/router';
|
|
21
|
+
import { Drawer } from '@masterteam/components/drawer';
|
|
22
|
+
import { RuntimeActionContextStore, RuntimeActionRunner, resolveActionLabel } from '@masterteam/components/runtime-action';
|
|
23
|
+
import { Action, Selector, State, Store, select } from '@ngxs/store';
|
|
20
24
|
import { handleApiRequest } from '@masterteam/components';
|
|
21
25
|
import { ClientInstancePreview } from '@masterteam/client-components/client-instance-preview';
|
|
22
26
|
import { EntitiesPreview } from '@masterteam/components/entities';
|
|
23
27
|
import { Tabs } from '@masterteam/components/tabs';
|
|
24
28
|
import { DiscussionThread } from '@masterteam/discussion';
|
|
25
29
|
import { StructureBuilder } from '@masterteam/structure-builder';
|
|
26
|
-
import { RuntimeActionContextStore, RuntimeActionRunner, resolveActionLabel } from '@masterteam/components/runtime-action';
|
|
27
|
-
import { Router, ActivatedRoute } from '@angular/router';
|
|
28
|
-
import { Drawer } from '@masterteam/components/drawer';
|
|
29
30
|
|
|
30
31
|
class WorkCenterClientFormModal {
|
|
31
32
|
modal = inject(ModalService);
|
|
@@ -48,8 +49,14 @@ class WorkCenterClientFormModal {
|
|
|
48
49
|
: 'create', ...(ngDevMode ? [{ debugName: "formMode" }] : /* istanbul ignore next */ []));
|
|
49
50
|
validationMessage = signal(null, ...(ngDevMode ? [{ debugName: "validationMessage" }] : /* istanbul ignore next */ []));
|
|
50
51
|
submitError = signal(null, ...(ngDevMode ? [{ debugName: "submitError" }] : /* istanbul ignore next */ []));
|
|
51
|
-
isSubmitting = signal(false, ...(ngDevMode ? [{ debugName: "isSubmitting" }] : /* istanbul ignore next */ []));
|
|
52
52
|
submitStatus = signal(null, ...(ngDevMode ? [{ debugName: "submitStatus" }] : /* istanbul ignore next */ []));
|
|
53
|
+
/**
|
|
54
|
+
* Mirrors the client form's own submit state instead of tracking it locally.
|
|
55
|
+
* A blocking `process-submit/validate` failure ends the submit without
|
|
56
|
+
* emitting `submitted` or `errored`, so a local flag would stay stuck at
|
|
57
|
+
* `true` and permanently disable Submit / keep the "Submitting…" hint up.
|
|
58
|
+
*/
|
|
59
|
+
isSubmitting = computed(() => this.processForm().submitting(), ...(ngDevMode ? [{ debugName: "isSubmitting" }] : /* istanbul ignore next */ []));
|
|
53
60
|
onSubmit() {
|
|
54
61
|
this.validationMessage.set(null);
|
|
55
62
|
this.submitError.set(null);
|
|
@@ -58,11 +65,9 @@ class WorkCenterClientFormModal {
|
|
|
58
65
|
this.validationMessage.set(this.transloco.translate('workCenter.validation.fillRequiredFields'));
|
|
59
66
|
return;
|
|
60
67
|
}
|
|
61
|
-
this.isSubmitting.set(true);
|
|
62
68
|
this.processForm().submit();
|
|
63
69
|
}
|
|
64
70
|
onSubmitted(response) {
|
|
65
|
-
this.isSubmitting.set(false);
|
|
66
71
|
this.submitError.set(null);
|
|
67
72
|
const status = response.status === 'PendingApproval' ? 'pending' : 'executed';
|
|
68
73
|
this.submitStatus.set(status);
|
|
@@ -71,7 +76,6 @@ class WorkCenterClientFormModal {
|
|
|
71
76
|
}
|
|
72
77
|
}
|
|
73
78
|
onErrored(error) {
|
|
74
|
-
this.isSubmitting.set(false);
|
|
75
79
|
this.submitError.set(error ??
|
|
76
80
|
this.transloco.translate('workCenter.error.failedSubmit'));
|
|
77
81
|
}
|
|
@@ -449,6 +453,7 @@ function createDefaultContext(area) {
|
|
|
449
453
|
return {
|
|
450
454
|
area,
|
|
451
455
|
templateId: null,
|
|
456
|
+
levelDataId: null,
|
|
452
457
|
selectedCardKey: null,
|
|
453
458
|
page: 1,
|
|
454
459
|
pageSize: WORK_CENTER_LOCAL_FETCH_SIZE,
|
|
@@ -496,6 +501,7 @@ const WORK_CENTER_DEFAULT_STATE = {
|
|
|
496
501
|
byArea: {
|
|
497
502
|
MyInbox: createDefaultAreaState('MyInbox'),
|
|
498
503
|
TasksCenter: createDefaultAreaState('TasksCenter'),
|
|
504
|
+
Workspace: createDefaultAreaState('Workspace'),
|
|
499
505
|
},
|
|
500
506
|
lookups: [],
|
|
501
507
|
loadingActive: [],
|
|
@@ -513,6 +519,7 @@ function normalizeContext(context) {
|
|
|
513
519
|
function buildContextFromInputs(currentContext, area, inputs = {}) {
|
|
514
520
|
const parsedCardKey = toSelectedCardKey(inputs.card);
|
|
515
521
|
const parsedTemplateId = toOptionalInt(inputs.templateId);
|
|
522
|
+
const parsedLevelDataId = toOptionalInt(inputs.levelDataId);
|
|
516
523
|
const hasPageInput = hasParamValue(inputs.page);
|
|
517
524
|
const parsedPage = hasPageInput ? toOptionalInt(inputs.page) : null;
|
|
518
525
|
const parsedPageSize = toOptionalInt(inputs.pageSize);
|
|
@@ -523,6 +530,7 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
|
|
|
523
530
|
page: hasPageInput ? (parsedPage ?? 1) : 1,
|
|
524
531
|
pageSize: parsedPageSize ?? currentContext.pageSize,
|
|
525
532
|
templateId: parsedTemplateId ?? currentContext.templateId,
|
|
533
|
+
levelDataId: parsedLevelDataId ?? currentContext.levelDataId,
|
|
526
534
|
sort: hasParamValue(inputs.sort)
|
|
527
535
|
? parseSortInput(inputs.sort)
|
|
528
536
|
: inputs.sort === null
|
|
@@ -538,6 +546,7 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
|
|
|
538
546
|
function isSameContext(left, right) {
|
|
539
547
|
return (left.area === right.area &&
|
|
540
548
|
left.templateId === right.templateId &&
|
|
549
|
+
left.levelDataId === right.levelDataId &&
|
|
541
550
|
left.selectedCardKey === right.selectedCardKey &&
|
|
542
551
|
left.page === right.page &&
|
|
543
552
|
left.pageSize === right.pageSize &&
|
|
@@ -1027,489 +1036,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
1027
1036
|
}]
|
|
1028
1037
|
}] });
|
|
1029
1038
|
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
In: 'In',
|
|
1034
|
-
Contains: 'Contains',
|
|
1035
|
-
StartsWith: 'Starts with',
|
|
1036
|
-
Gt: 'Greater than',
|
|
1037
|
-
Gte: 'Greater than or equal',
|
|
1038
|
-
Lt: 'Less than',
|
|
1039
|
-
Lte: 'Less than or equal',
|
|
1040
|
-
Between: 'Between',
|
|
1041
|
-
IsNull: 'Is empty',
|
|
1042
|
-
IsNotNull: 'Is not empty',
|
|
1043
|
-
};
|
|
1044
|
-
const OPERATOR_VALUE_MODE = {
|
|
1045
|
-
In: 'multi',
|
|
1046
|
-
Between: 'range',
|
|
1047
|
-
IsNull: 'none',
|
|
1048
|
-
IsNotNull: 'none',
|
|
1049
|
-
};
|
|
1050
|
-
const GENERAL_TASK_CARD_KEYS = new Set([
|
|
1051
|
-
'mygeneraltasks',
|
|
1052
|
-
'generaltask',
|
|
1053
|
-
'generaltasks',
|
|
1054
|
-
]);
|
|
1055
|
-
function toLabel(value) {
|
|
1056
|
-
const normalized = value.split('.').pop() ?? value;
|
|
1057
|
-
return normalized
|
|
1058
|
-
.replace(/[_-]/g, ' ')
|
|
1059
|
-
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
1060
|
-
.trim()
|
|
1061
|
-
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
1062
|
-
}
|
|
1063
|
-
function columnTypeToViewType(type) {
|
|
1064
|
-
if (type === 'date')
|
|
1065
|
-
return 'Date';
|
|
1066
|
-
return undefined;
|
|
1067
|
-
}
|
|
1068
|
-
function normalizeCardKey(value) {
|
|
1069
|
-
if (typeof value !== 'string') {
|
|
1070
|
-
return '';
|
|
1071
|
-
}
|
|
1072
|
-
return value
|
|
1073
|
-
.trim()
|
|
1074
|
-
.replace(/[\s_-]/g, '')
|
|
1075
|
-
.toLowerCase();
|
|
1076
|
-
}
|
|
1077
|
-
/**
|
|
1078
|
-
* Strips the user envelope used by `mt-table` user filters down to the
|
|
1079
|
-
* scalar id that the BE rule payload accepts. Falls back to the original
|
|
1080
|
-
* value for non-user shapes (e.g. simple string in a select filter).
|
|
1081
|
-
*/
|
|
1082
|
-
function extractIdScalar(value) {
|
|
1083
|
-
if (value !== null &&
|
|
1084
|
-
typeof value === 'object' &&
|
|
1085
|
-
'id' in value) {
|
|
1086
|
-
return value['id'];
|
|
1087
|
-
}
|
|
1088
|
-
return value;
|
|
1089
|
-
}
|
|
1090
|
-
function toIsoDate(value) {
|
|
1091
|
-
if (value instanceof Date)
|
|
1092
|
-
return value.toISOString();
|
|
1093
|
-
return value;
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
* Translates one in-table column filter value into a `WorkCenterFilterRule`.
|
|
1097
|
-
*
|
|
1098
|
-
* The shape of `raw` depends on the column's filter type — see
|
|
1099
|
-
* `mt-table` `table-filter-field` outputs:
|
|
1100
|
-
* - text → string → `Contains`
|
|
1101
|
-
* - select → scalar | scalar[] → `Eq` | `In`
|
|
1102
|
-
* - boolean → boolean → `Eq`
|
|
1103
|
-
* - date → `{ from?, to?, value? }` (Date|null)→ `Between`/`Gte`/`Lte`/`Eq`
|
|
1104
|
-
* - user → `{ id, ... }` | `{ id, ... }[]` → `Eq` (id) | `In` (ids)
|
|
1105
|
-
*
|
|
1106
|
-
* Returns `null` when the value is empty / nothing to send.
|
|
1107
|
-
*/
|
|
1108
|
-
function toRuntimeFilterRule(field, raw, column) {
|
|
1109
|
-
if (raw === null || raw === undefined || raw === '')
|
|
1039
|
+
function readItemContext(details) {
|
|
1040
|
+
const item = details.item;
|
|
1041
|
+
if (!item || typeof item !== 'object') {
|
|
1110
1042
|
return null;
|
|
1111
|
-
if (typeof raw === 'boolean') {
|
|
1112
|
-
return { field, op: 'Eq', value: raw };
|
|
1113
|
-
}
|
|
1114
|
-
if (typeof raw === 'number') {
|
|
1115
|
-
return { field, op: 'Eq', value: raw };
|
|
1116
|
-
}
|
|
1117
|
-
if (typeof raw === 'string') {
|
|
1118
|
-
if (!raw.trim().length)
|
|
1119
|
-
return null;
|
|
1120
|
-
return { field, op: 'Contains', value: raw };
|
|
1121
|
-
}
|
|
1122
|
-
if (Array.isArray(raw)) {
|
|
1123
|
-
const values = raw
|
|
1124
|
-
.map(extractIdScalar)
|
|
1125
|
-
.filter((v) => v !== null && v !== undefined && v !== '');
|
|
1126
|
-
if (!values.length)
|
|
1127
|
-
return null;
|
|
1128
|
-
return { field, op: 'In', values };
|
|
1129
|
-
}
|
|
1130
|
-
if (typeof raw === 'object') {
|
|
1131
|
-
const obj = raw;
|
|
1132
|
-
// User filter envelope -> single-id Eq.
|
|
1133
|
-
if (obj.id !== undefined && obj.id !== null && obj.id !== '') {
|
|
1134
|
-
return { field, op: 'Eq', value: obj.id };
|
|
1135
|
-
}
|
|
1136
|
-
const hasFrom = obj.from !== undefined && obj.from !== null;
|
|
1137
|
-
const hasTo = obj.to !== undefined && obj.to !== null;
|
|
1138
|
-
if (hasFrom && hasTo) {
|
|
1139
|
-
return {
|
|
1140
|
-
field,
|
|
1141
|
-
op: 'Between',
|
|
1142
|
-
from: toIsoDate(obj.from),
|
|
1143
|
-
to: toIsoDate(obj.to),
|
|
1144
|
-
};
|
|
1145
|
-
}
|
|
1146
|
-
if (hasFrom) {
|
|
1147
|
-
return { field, op: 'Gte', value: toIsoDate(obj.from) };
|
|
1148
|
-
}
|
|
1149
|
-
if (hasTo) {
|
|
1150
|
-
return { field, op: 'Lte', value: toIsoDate(obj.to) };
|
|
1151
|
-
}
|
|
1152
|
-
if (obj.value !== undefined && obj.value !== null && obj.value !== '') {
|
|
1153
|
-
const treatAsContains = column?.type === 'text' ||
|
|
1154
|
-
(column?.filterConfig?.type === 'text' &&
|
|
1155
|
-
typeof obj.value === 'string');
|
|
1156
|
-
if (treatAsContains) {
|
|
1157
|
-
return { field, op: 'Contains', value: obj.value };
|
|
1158
|
-
}
|
|
1159
|
-
return { field, op: 'Eq', value: extractIdScalar(obj.value) };
|
|
1160
|
-
}
|
|
1161
1043
|
}
|
|
1162
|
-
|
|
1044
|
+
const context = item['context'];
|
|
1045
|
+
return context && typeof context === 'object'
|
|
1046
|
+
? context
|
|
1047
|
+
: null;
|
|
1163
1048
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
*/
|
|
1169
|
-
function buildColumnRuntimeFilters(filters, columns, allowedFields) {
|
|
1170
|
-
if (!filters)
|
|
1171
|
-
return [];
|
|
1172
|
-
const allowed = allowedFields && allowedFields.length ? new Set(allowedFields) : null;
|
|
1173
|
-
const columnByKey = new Map(columns.map((col) => [col.key, col]));
|
|
1174
|
-
const rules = [];
|
|
1175
|
-
for (const [key, raw] of Object.entries(filters)) {
|
|
1176
|
-
if (key === 'generalSearch')
|
|
1177
|
-
continue;
|
|
1178
|
-
if (allowed && !allowed.has(key))
|
|
1179
|
-
continue;
|
|
1180
|
-
const rule = toRuntimeFilterRule(key, raw, columnByKey.get(key));
|
|
1181
|
-
if (rule)
|
|
1182
|
-
rules.push(rule);
|
|
1049
|
+
function readNumber(source, key) {
|
|
1050
|
+
const value = source?.[key];
|
|
1051
|
+
if (typeof value === 'number') {
|
|
1052
|
+
return Number.isFinite(value) ? value : undefined;
|
|
1183
1053
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
return JSON.stringify(left) === JSON.stringify(right);
|
|
1188
|
-
}
|
|
1189
|
-
function mapAllowedFields(schema) {
|
|
1190
|
-
const properties = schema.properties ?? [];
|
|
1191
|
-
const fromProperties = properties
|
|
1192
|
-
.filter((property) => typeof property?.key === 'string' && property.key.length > 0)
|
|
1193
|
-
.map((property) => ({
|
|
1194
|
-
key: property.key,
|
|
1195
|
-
label: property.name?.display ||
|
|
1196
|
-
property.name?.en ||
|
|
1197
|
-
property.name?.ar ||
|
|
1198
|
-
toLabel(property.key),
|
|
1199
|
-
viewType: property.viewType,
|
|
1200
|
-
}));
|
|
1201
|
-
if (fromProperties.length) {
|
|
1202
|
-
return fromProperties;
|
|
1054
|
+
if (typeof value === 'string' && value.trim().length) {
|
|
1055
|
+
const parsed = Number(value);
|
|
1056
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1203
1057
|
}
|
|
1204
|
-
return
|
|
1205
|
-
key: field,
|
|
1206
|
-
label: toLabel(field),
|
|
1207
|
-
}));
|
|
1058
|
+
return undefined;
|
|
1208
1059
|
}
|
|
1209
|
-
function
|
|
1210
|
-
const
|
|
1211
|
-
|
|
1212
|
-
if (typeof operator === 'string') {
|
|
1213
|
-
options.push({
|
|
1214
|
-
key: operator,
|
|
1215
|
-
label: getLabel(operator),
|
|
1216
|
-
valueMode: OPERATOR_VALUE_MODE[operator] ?? 'single',
|
|
1217
|
-
});
|
|
1218
|
-
continue;
|
|
1219
|
-
}
|
|
1220
|
-
const key = operator?.value;
|
|
1221
|
-
if (!key) {
|
|
1222
|
-
continue;
|
|
1223
|
-
}
|
|
1224
|
-
options.push({
|
|
1225
|
-
key,
|
|
1226
|
-
label: operator.display?.display ||
|
|
1227
|
-
operator.display?.en ||
|
|
1228
|
-
operator.display?.ar ||
|
|
1229
|
-
getLabel(key),
|
|
1230
|
-
valueMode: OPERATOR_VALUE_MODE[key] ?? 'single',
|
|
1231
|
-
});
|
|
1232
|
-
}
|
|
1233
|
-
return options;
|
|
1060
|
+
function readString$1(source, key) {
|
|
1061
|
+
const value = source?.[key];
|
|
1062
|
+
return typeof value === 'string' && value.trim().length ? value : undefined;
|
|
1234
1063
|
}
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1064
|
+
|
|
1065
|
+
class WorkCenterEscalationInstanceType {
|
|
1066
|
+
http = inject(HttpClient);
|
|
1238
1067
|
transloco = inject(TranslocoService);
|
|
1239
1068
|
destroyRef = inject(DestroyRef);
|
|
1069
|
+
loadSub;
|
|
1070
|
+
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : /* istanbul ignore next */ []));
|
|
1071
|
+
activeTab = signal('escalationDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
1240
1072
|
activeLang = signal(this.transloco.getActiveLang(), ...(ngDevMode ? [{ debugName: "activeLang" }] : /* istanbul ignore next */ []));
|
|
1241
|
-
|
|
1242
|
-
pageTitle = input('', ...(ngDevMode ? [{ debugName: "pageTitle" }] : /* istanbul ignore next */ []));
|
|
1243
|
-
menuIcon = input('communication.inbox-01', ...(ngDevMode ? [{ debugName: "menuIcon" }] : /* istanbul ignore next */ []));
|
|
1244
|
-
lookups = input([], ...(ngDevMode ? [{ debugName: "lookups" }] : /* istanbul ignore next */ []));
|
|
1245
|
-
openItemsInModal = input(true, ...(ngDevMode ? [{ debugName: "openItemsInModal" }] : /* istanbul ignore next */ []));
|
|
1246
|
-
itemModal = input(null, ...(ngDevMode ? [{ debugName: "itemModal" }] : /* istanbul ignore next */ []));
|
|
1247
|
-
generalTaskModal = input(null, ...(ngDevMode ? [{ debugName: "generalTaskModal" }] : /* istanbul ignore next */ []));
|
|
1248
|
-
runtimeFiltersChanged = output();
|
|
1249
|
-
itemClicked = output();
|
|
1250
|
-
cardSelected = output();
|
|
1251
|
-
context = this.facade.context;
|
|
1252
|
-
headerFilters = this.facade.headerFilters;
|
|
1253
|
-
tableFilters = signal({}, ...(ngDevMode ? [{ debugName: "tableFilters" }] : /* istanbul ignore next */ []));
|
|
1254
|
-
_menuItems = this.facade.menuItems;
|
|
1255
|
-
menuItems = computed(() => {
|
|
1256
|
-
this.activeLang();
|
|
1257
|
-
return this._menuItems().map((item) => ({
|
|
1258
|
-
...item,
|
|
1259
|
-
subtitle: `${item.count} ${item.title}`,
|
|
1260
|
-
}));
|
|
1261
|
-
}, ...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
1262
|
-
rows = this.facade.rows;
|
|
1263
|
-
columns = this.facade.columns;
|
|
1264
|
-
kpis = this.facade.kpis;
|
|
1265
|
-
runtimeFilterSchema = this.facade.runtimeFilterSchema;
|
|
1266
|
-
totalCount = this.facade.totalCount;
|
|
1267
|
-
columnFilters = this.facade.columnFilters;
|
|
1268
|
-
loading = this.facade.loading;
|
|
1269
|
-
tableColumns = computed(() => this.columns().map((column) => ({
|
|
1270
|
-
...column,
|
|
1271
|
-
sortable: true,
|
|
1272
|
-
})), ...(ngDevMode ? [{ debugName: "tableColumns" }] : /* istanbul ignore next */ []));
|
|
1273
|
-
/**
|
|
1274
|
-
* Maps each status/group display label to its total count from the KPI
|
|
1275
|
-
* summary cards so the group header shows the real backend total rather than
|
|
1276
|
-
* the current-page row count.
|
|
1277
|
-
*/
|
|
1278
|
-
statusGroupCountMap = computed(() => {
|
|
1279
|
-
const map = new Map();
|
|
1280
|
-
for (const kpi of this.kpis()) {
|
|
1281
|
-
const label = kpi.subTitle;
|
|
1282
|
-
const count = Number(kpi.title);
|
|
1283
|
-
if (label && !isNaN(count)) {
|
|
1284
|
-
map.set(label, count);
|
|
1285
|
-
}
|
|
1286
|
-
}
|
|
1287
|
-
return map;
|
|
1288
|
-
}, ...(ngDevMode ? [{ debugName: "statusGroupCountMap" }] : /* istanbul ignore next */ []));
|
|
1289
|
-
propertyFilterSchema = computed(() => {
|
|
1290
|
-
this.activeLang();
|
|
1291
|
-
const schema = this.runtimeFilterSchema();
|
|
1292
|
-
if (schema) {
|
|
1293
|
-
const allowedFields = mapAllowedFields(schema);
|
|
1294
|
-
const allowedOperators = mapAllowedOperators(schema, (key) => this.getOpLabel(key));
|
|
1295
|
-
if (allowedFields.length && allowedOperators.length) {
|
|
1296
|
-
return { allowedFields, allowedOperators };
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1299
|
-
const fallbackFields = this.columns()
|
|
1300
|
-
.filter((column) => typeof column?.key === 'string' && column.key.length > 0)
|
|
1301
|
-
.map((column) => ({
|
|
1302
|
-
key: column.key,
|
|
1303
|
-
label: column.label || toLabel(column.key),
|
|
1304
|
-
viewType: columnTypeToViewType(column.type),
|
|
1305
|
-
}));
|
|
1306
|
-
if (!fallbackFields.length) {
|
|
1307
|
-
return null;
|
|
1308
|
-
}
|
|
1309
|
-
const fallbackOperators = Object.keys(OPERATOR_LABELS).map((key) => ({
|
|
1310
|
-
key,
|
|
1311
|
-
label: this.getOpLabel(key),
|
|
1312
|
-
valueMode: OPERATOR_VALUE_MODE[key] ?? 'single',
|
|
1313
|
-
}));
|
|
1314
|
-
return {
|
|
1315
|
-
allowedFields: fallbackFields,
|
|
1316
|
-
allowedOperators: fallbackOperators,
|
|
1317
|
-
};
|
|
1318
|
-
}, ...(ngDevMode ? [{ debugName: "propertyFilterSchema" }] : /* istanbul ignore next */ []));
|
|
1319
|
-
showGeneralTaskCreateButton = computed(() => GENERAL_TASK_CARD_KEYS.has(normalizeCardKey(this.context().selectedCardKey)), ...(ngDevMode ? [{ debugName: "showGeneralTaskCreateButton" }] : /* istanbul ignore next */ []));
|
|
1320
|
-
generalTaskButtonLabel = computed(() => {
|
|
1321
|
-
this.activeLang();
|
|
1322
|
-
return (this.generalTaskModal()?.buttonLabel?.trim() ||
|
|
1323
|
-
this.transloco.translate('workCenter.page.new'));
|
|
1324
|
-
}, ...(ngDevMode ? [{ debugName: "generalTaskButtonLabel" }] : /* istanbul ignore next */ []));
|
|
1325
|
-
resolvedPageTitle = computed(() => {
|
|
1326
|
-
this.activeLang();
|
|
1327
|
-
return (this.pageTitle() ||
|
|
1328
|
-
this.transloco.translate('workCenter.page.title'));
|
|
1329
|
-
}, ...(ngDevMode ? [{ debugName: "resolvedPageTitle" }] : /* istanbul ignore next */ []));
|
|
1330
|
-
generalTaskButtonIcon = computed(() => this.generalTaskModal()?.buttonIcon?.trim() || 'general.plus', ...(ngDevMode ? [{ debugName: "generalTaskButtonIcon" }] : /* istanbul ignore next */ []));
|
|
1331
|
-
defaultModalStyleClass = '!w-[96vw] md:!w-[84vw] xl:!w-[70vw] !shadow-none';
|
|
1332
|
-
defaultGeneralTaskModalStyleClass = '!w-[70vw] !h-[90vh]';
|
|
1333
|
-
constructor() {
|
|
1334
|
-
this.transloco.langChanges$
|
|
1335
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
1336
|
-
.subscribe((lang) => this.activeLang.set(lang));
|
|
1337
|
-
effect(() => {
|
|
1338
|
-
this.facade.setLookups(this.lookups());
|
|
1339
|
-
});
|
|
1340
|
-
}
|
|
1341
|
-
onMenuItemClick(item) {
|
|
1342
|
-
if (item.key === this.context().selectedCardKey) {
|
|
1343
|
-
return;
|
|
1344
|
-
}
|
|
1345
|
-
this.facade.selectCardAndLoad(this.area(), item.key);
|
|
1346
|
-
this.cardSelected.emit(item.key);
|
|
1347
|
-
}
|
|
1348
|
-
onRuntimeFiltersApplied(filters) {
|
|
1349
|
-
const mappedFilters = filters.map((filter) => ({
|
|
1350
|
-
field: filter.field,
|
|
1351
|
-
op: filter.op,
|
|
1352
|
-
value: filter.value,
|
|
1353
|
-
values: filter.values,
|
|
1354
|
-
from: filter.from,
|
|
1355
|
-
to: filter.to,
|
|
1356
|
-
}));
|
|
1357
|
-
this.facade.applyHeaderFiltersAndLoad(this.area(), mappedFilters);
|
|
1358
|
-
this.runtimeFiltersChanged.emit(mappedFilters);
|
|
1359
|
-
}
|
|
1360
|
-
onRuntimeFiltersCleared() {
|
|
1361
|
-
this.facade.clearAllFiltersAndLoad(this.area());
|
|
1362
|
-
this.tableFilters.set({});
|
|
1363
|
-
this.runtimeFiltersChanged.emit([]);
|
|
1364
|
-
}
|
|
1365
|
-
/**
|
|
1366
|
-
* Single entry point for `mt-table` (`lazy=true`) — handles both column
|
|
1367
|
-
* filters and pagination/sort. Filter changes always reset the page to 1
|
|
1368
|
-
* (handled by `applyColumnFiltersAndLoad`); when only paging/sort changed
|
|
1369
|
-
* we fall through to `applyTableLazyLoadAndLoad`.
|
|
1370
|
-
*/
|
|
1371
|
-
onTableLazyLoad(event) {
|
|
1372
|
-
const schema = this.runtimeFilterSchema();
|
|
1373
|
-
const propertyKeys = (schema?.properties ?? [])
|
|
1374
|
-
.map((p) => p?.key)
|
|
1375
|
-
.filter((k) => typeof k === 'string' && k.length > 0);
|
|
1376
|
-
const allowedKeys = schema?.allowedFields ?? [];
|
|
1377
|
-
const allowedFields = propertyKeys.length ? propertyKeys : allowedKeys;
|
|
1378
|
-
const nextColumnFilters = buildColumnRuntimeFilters(event?.filters, this.columns(), allowedFields.length ? allowedFields : undefined);
|
|
1379
|
-
if (!areFilterRulesEqual(nextColumnFilters, this.columnFilters())) {
|
|
1380
|
-
this.facade.applyColumnFiltersAndLoad(this.area(), nextColumnFilters);
|
|
1381
|
-
return;
|
|
1382
|
-
}
|
|
1383
|
-
this.facade.applyTableLazyLoadAndLoad(this.area(), event);
|
|
1384
|
-
}
|
|
1385
|
-
onGeneralTaskCreateClick() {
|
|
1386
|
-
const modalOptions = this.generalTaskModal();
|
|
1387
|
-
const modalData = {
|
|
1388
|
-
moduleKey: 'GeneralTask',
|
|
1389
|
-
...(modalOptions?.data ?? {}),
|
|
1390
|
-
};
|
|
1391
|
-
const modalHeader = modalOptions?.header ??
|
|
1392
|
-
this.transloco.translate('workCenter.page.createGeneralTask');
|
|
1393
|
-
const modalStyleClass = modalOptions?.styleClass ?? this.defaultGeneralTaskModalStyleClass;
|
|
1394
|
-
const operationKey = modalOptions?.operationKey ?? 'Create';
|
|
1395
|
-
const closeOnPendingApproval = modalOptions?.closeOnPendingApproval ?? true;
|
|
1396
|
-
const lookups = modalOptions?.lookups ?? this.lookups();
|
|
1397
|
-
const ref = this.modal.openModal(WorkCenterClientFormModal, 'dialog', {
|
|
1398
|
-
header: modalHeader,
|
|
1399
|
-
styleClass: modalStyleClass,
|
|
1400
|
-
position: 'end',
|
|
1401
|
-
dismissableMask: true,
|
|
1402
|
-
inputValues: {
|
|
1403
|
-
data: modalData,
|
|
1404
|
-
operationKey,
|
|
1405
|
-
closeOnPendingApproval,
|
|
1406
|
-
lookups,
|
|
1407
|
-
},
|
|
1408
|
-
});
|
|
1409
|
-
ref.onClose.pipe(take(1)).subscribe((result) => {
|
|
1410
|
-
if (result) {
|
|
1411
|
-
this.facade.loadRuntime(this.area(), 'refresh');
|
|
1412
|
-
}
|
|
1413
|
-
});
|
|
1414
|
-
}
|
|
1415
|
-
onRowClick(row) {
|
|
1416
|
-
const contextKey = this.resolveRowContextKey(row);
|
|
1417
|
-
console.log('[work-center-debug] page row click', {
|
|
1418
|
-
contextKey,
|
|
1419
|
-
row,
|
|
1420
|
-
openItemsInModal: this.openItemsInModal(),
|
|
1421
|
-
hasModalComponent: !!this.itemModal()?.component,
|
|
1422
|
-
});
|
|
1423
|
-
if (!contextKey) {
|
|
1424
|
-
return;
|
|
1425
|
-
}
|
|
1426
|
-
this.itemClicked.emit(contextKey);
|
|
1427
|
-
if (!this.openItemsInModal()) {
|
|
1428
|
-
return;
|
|
1429
|
-
}
|
|
1430
|
-
const modalOptions = this.itemModal();
|
|
1431
|
-
if (!modalOptions?.component) {
|
|
1432
|
-
return;
|
|
1433
|
-
}
|
|
1434
|
-
const ref = this.modal.openModal(modalOptions.component, 'drawer', {
|
|
1435
|
-
header: modalOptions?.header ??
|
|
1436
|
-
this.transloco.translate('workCenter.page.itemDetails'),
|
|
1437
|
-
styleClass: modalOptions?.styleClass ?? this.defaultModalStyleClass,
|
|
1438
|
-
position: modalOptions?.position ?? 'end',
|
|
1439
|
-
dismissible: true,
|
|
1440
|
-
modal: true,
|
|
1441
|
-
...(modalOptions?.appendTo ? { appendTo: modalOptions.appendTo } : {}),
|
|
1442
|
-
inputValues: { contextKey },
|
|
1443
|
-
});
|
|
1444
|
-
ref.onClose.pipe(take(1)).subscribe(() => {
|
|
1445
|
-
this.facade.loadRuntime(this.area(), 'refresh');
|
|
1446
|
-
});
|
|
1447
|
-
}
|
|
1448
|
-
rowsClickable = computed(() => this.openItemsInModal(), ...(ngDevMode ? [{ debugName: "rowsClickable" }] : /* istanbul ignore next */ []));
|
|
1449
|
-
getOpLabel(key) {
|
|
1450
|
-
return (this.transloco.translate('workCenter.operator.' + key) ||
|
|
1451
|
-
OPERATOR_LABELS[key] ||
|
|
1452
|
-
toLabel(key));
|
|
1453
|
-
}
|
|
1454
|
-
resolveRowContextKey(row) {
|
|
1455
|
-
const value = row['contextKey'];
|
|
1456
|
-
if (typeof value !== 'string') {
|
|
1457
|
-
return null;
|
|
1458
|
-
}
|
|
1459
|
-
const normalized = value.trim();
|
|
1460
|
-
return normalized.length ? normalized : null;
|
|
1461
|
-
}
|
|
1462
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1463
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterPage, isStandalone: true, selector: "mt-work-center-page", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, menuIcon: { classPropertyName: "menuIcon", publicName: "menuIcon", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, openItemsInModal: { classPropertyName: "openItemsInModal", publicName: "openItemsInModal", isSignal: true, isRequired: false, transformFunction: null }, itemModal: { classPropertyName: "itemModal", publicName: "itemModal", isSignal: true, isRequired: false, transformFunction: null }, generalTaskModal: { classPropertyName: "generalTaskModal", publicName: "generalTaskModal", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeFiltersChanged: "runtimeFiltersChanged", itemClicked: "itemClicked", cardSelected: "cardSelected" }, ngImport: i0, template: "<mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"resolvedPageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n storageKey=\"work-center-client-page\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n>\r\n <ng-template #headerClientPageEnd>\r\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"headerFilters()\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n\r\n @if (showGeneralTaskCreateButton()) {\r\n <mt-button\r\n [label]=\"generalTaskButtonLabel()\"\r\n [icon]=\"generalTaskButtonIcon()\"\r\n size=\"small\"\r\n (onClick)=\"onGeneralTaskCreateClick()\"\r\n />\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-8\">\r\n @if (loading()) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\r\n <p-skeleton height=\"6.5rem\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div class=\"gap-3 flex flex-wrap\">\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n noCard\r\n [data]=\"rows()\"\r\n [columns]=\"tableColumns()\"\r\n tableLayout=\"auto\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [cellClickFilter]=\"true\"\r\n [generalSearch]=\"true\"\r\n [exportable]=\"true\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [freezeActions]=\"true\"\r\n [lazy]=\"true\"\r\n [lazyLocalSearch]=\"true\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"context().page - 1\"\r\n [first]=\"(context().page - 1) * context().pageSize\"\r\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\r\n [groupCountMap]=\"statusGroupCountMap()\"\r\n storageKey=\"work-center-page-table\"\r\n [filters]=\"tableFilters()\"\r\n (filtersChange)=\"tableFilters.set($event)\"\r\n (lazyLoad)=\"onTableLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</mt-client-page>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ClientPage, selector: "mt-client-page", inputs: ["menuIcon", "menuTitle", "menuItems", "menuItemsLoading", "activeItem", "collapsed", "resizable", "storageKey", "storageMode", "minSidebarWidth", "maxSidebarWidth", "defaultSidebarWidth"], outputs: ["collapsedChange", "menuItemClick", "loadChildren"] }, { kind: "component", type: PropertyFilterBuilder, selector: "mt-property-filter-builder", inputs: ["schema", "filters", "title", "buttonLabel", "disabled"], outputs: ["filtersChange", "applied", "cleared"] }, { kind: "component", type: StatisticCard, selector: "mt-statistic-card", inputs: ["data", "cardClass"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
|
|
1464
|
-
}
|
|
1465
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterPage, decorators: [{
|
|
1466
|
-
type: Component,
|
|
1467
|
-
args: [{ selector: 'mt-work-center-page', standalone: true, imports: [
|
|
1468
|
-
CommonModule,
|
|
1469
|
-
Button,
|
|
1470
|
-
ClientPage,
|
|
1471
|
-
PropertyFilterBuilder,
|
|
1472
|
-
StatisticCard,
|
|
1473
|
-
Table,
|
|
1474
|
-
SkeletonModule,
|
|
1475
|
-
], template: "<mt-client-page\r\n [menuIcon]=\"menuIcon()\"\r\n [menuTitle]=\"resolvedPageTitle()\"\r\n [menuItems]=\"menuItems()\"\r\n [menuItemsLoading]=\"loading() && !menuItems().length\"\r\n [activeItem]=\"context().selectedCardKey ?? undefined\"\r\n storageKey=\"work-center-client-page\"\r\n (menuItemClick)=\"onMenuItemClick($event)\"\r\n>\r\n <ng-template #headerClientPageEnd>\r\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\r\n <mt-property-filter-builder\r\n [schema]=\"propertyFilterSchema()\"\r\n [filters]=\"headerFilters()\"\r\n (applied)=\"onRuntimeFiltersApplied($event)\"\r\n (cleared)=\"onRuntimeFiltersCleared()\"\r\n />\r\n\r\n @if (showGeneralTaskCreateButton()) {\r\n <mt-button\r\n [label]=\"generalTaskButtonLabel()\"\r\n [icon]=\"generalTaskButtonIcon()\"\r\n size=\"small\"\r\n (onClick)=\"onGeneralTaskCreateClick()\"\r\n />\r\n }\r\n </div>\r\n </ng-template>\r\n\r\n <div class=\"flex flex-col gap-8\">\r\n @if (loading()) {\r\n <div\r\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\r\n >\r\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\r\n <p-skeleton height=\"6.5rem\" class=\"rounded-lg\" />\r\n }\r\n </div>\r\n } @else if (kpis().length) {\r\n <div class=\"gap-3 flex flex-wrap\">\r\n @for (kpi of kpis(); track $index) {\r\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\r\n }\r\n </div>\r\n }\r\n\r\n <mt-table\r\n noCard\r\n [data]=\"rows()\"\r\n [columns]=\"tableColumns()\"\r\n tableLayout=\"auto\"\r\n [clickableRows]=\"rowsClickable()\"\r\n [loading]=\"loading()\"\r\n [showFilters]=\"true\"\r\n filterMode=\"column\"\r\n [cellClickFilter]=\"true\"\r\n [generalSearch]=\"true\"\r\n [exportable]=\"true\"\r\n [printable]=\"true\"\r\n [groupable]=\"true\"\r\n [freezeActions]=\"true\"\r\n [lazy]=\"true\"\r\n [lazyLocalSearch]=\"true\"\r\n [lazyTotalRecords]=\"totalCount()\"\r\n [pageSize]=\"context().pageSize\"\r\n [currentPage]=\"context().page - 1\"\r\n [first]=\"(context().page - 1) * context().pageSize\"\r\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\r\n [groupCountMap]=\"statusGroupCountMap()\"\r\n storageKey=\"work-center-page-table\"\r\n [filters]=\"tableFilters()\"\r\n (filtersChange)=\"tableFilters.set($event)\"\r\n (lazyLoad)=\"onTableLazyLoad($event)\"\r\n (rowClick)=\"onRowClick($event)\"\r\n />\r\n </div>\r\n</mt-client-page>\r\n" }]
|
|
1476
|
-
}], ctorParameters: () => [], propDecorators: { area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], menuIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuIcon", required: false }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], openItemsInModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemsInModal", required: false }] }], itemModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemModal", required: false }] }], generalTaskModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalTaskModal", required: false }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }], cardSelected: [{ type: i0.Output, args: ["cardSelected"] }] } });
|
|
1477
|
-
|
|
1478
|
-
function readItemContext(details) {
|
|
1479
|
-
const item = details.item;
|
|
1480
|
-
if (!item || typeof item !== 'object') {
|
|
1481
|
-
return null;
|
|
1482
|
-
}
|
|
1483
|
-
const context = item['context'];
|
|
1484
|
-
return context && typeof context === 'object'
|
|
1485
|
-
? context
|
|
1486
|
-
: null;
|
|
1487
|
-
}
|
|
1488
|
-
function readNumber(source, key) {
|
|
1489
|
-
const value = source?.[key];
|
|
1490
|
-
if (typeof value === 'number') {
|
|
1491
|
-
return Number.isFinite(value) ? value : undefined;
|
|
1492
|
-
}
|
|
1493
|
-
if (typeof value === 'string' && value.trim().length) {
|
|
1494
|
-
const parsed = Number(value);
|
|
1495
|
-
return Number.isFinite(parsed) ? parsed : undefined;
|
|
1496
|
-
}
|
|
1497
|
-
return undefined;
|
|
1498
|
-
}
|
|
1499
|
-
function readString$1(source, key) {
|
|
1500
|
-
const value = source?.[key];
|
|
1501
|
-
return typeof value === 'string' && value.trim().length ? value : undefined;
|
|
1502
|
-
}
|
|
1503
|
-
|
|
1504
|
-
class WorkCenterEscalationInstanceType {
|
|
1505
|
-
http = inject(HttpClient);
|
|
1506
|
-
transloco = inject(TranslocoService);
|
|
1507
|
-
destroyRef = inject(DestroyRef);
|
|
1508
|
-
loadSub;
|
|
1509
|
-
details = input.required(...(ngDevMode ? [{ debugName: "details" }] : /* istanbul ignore next */ []));
|
|
1510
|
-
activeTab = signal('escalationDetails', ...(ngDevMode ? [{ debugName: "activeTab" }] : /* istanbul ignore next */ []));
|
|
1511
|
-
activeLang = signal(this.transloco.getActiveLang(), ...(ngDevMode ? [{ debugName: "activeLang" }] : /* istanbul ignore next */ []));
|
|
1512
|
-
tabOptions = computed(() => {
|
|
1073
|
+
tabOptions = computed(() => {
|
|
1513
1074
|
this.activeLang();
|
|
1514
1075
|
return [
|
|
1515
1076
|
{
|
|
@@ -1718,7 +1279,7 @@ class WorkCenterEscalationInstanceType {
|
|
|
1718
1279
|
});
|
|
1719
1280
|
}
|
|
1720
1281
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterEscalationInstanceType, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1721
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterEscalationInstanceType, isStandalone: true, selector: "mt-work-center-escalation-instance-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\r\n class=\"mt-modal-content flex h-full min-h-0 flex-col gap-4 p-4 lg:overflow-hidden\"\r\n *transloco=\"let t; prefix: 'workCenter'\"\r\n>\r\n <div\r\n class=\"flex flex-1 min-h-0 flex-col gap-4 lg:grid lg:grid-cols-[13rem_minmax(0,1fr)] lg:gap-6\"\r\n >\r\n @if (tabOptions().length > 1) {\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n mode=\"vertical\"\r\n size=\"small\"\r\n />\r\n }\r\n\r\n <div class=\"min-w-0 flex-1 min-h-0 lg:overflow-hidden\">\r\n <div\r\n class=\"h-full min-h-0 lg:overflow-hidden\"\r\n [hidden]=\"activeTab() !== 'escalationDetails'\"\r\n >\r\n <div\r\n class=\"min-w-0 h-full min-h-0 lg:overflow-y-auto lg:overscroll-contain lg:pr-2\"\r\n >\r\n @if (canRenderDetails()) {\r\n @if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"loading.escalationDetails\") }}\r\n </p>\r\n </div>\r\n } @else if (error(); as error) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">\r\n {{ error }}\r\n </p>\r\n </div>\r\n } @else if (preview()) {\r\n <mt-entities-preview [entities]=\"detailEntities()\" />\r\n }\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationDetailsUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"h-full min-h-0 lg:overflow-hidden\"\r\n [hidden]=\"activeTab() !== 'moduleDetails'\"\r\n >\r\n @if (moduleDetailsConfig(); as moduleDetailsConfig) {\r\n <div\r\n class=\"min-w-0 h-full min-h-0 lg:overflow-y-auto lg:overscroll-contain lg:pr-2\"\r\n >\r\n <mt-client-instance-preview [config]=\"moduleDetailsConfig\" />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"flex-1 min-h-0 overflow-auto\"\r\n [hidden]=\"activeTab() !== 'schema'\"\r\n >\r\n @if (canRenderDetails()) {\r\n @if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"loading.escalationSchema\") }}\r\n </p>\r\n </div>\r\n } @else if (error(); as error) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">\r\n {{ error }}\r\n </p>\r\n </div>\r\n } @else if (hasSchema()) {\r\n <!--\r\n Only mount the flow once the schema tab is actually active. The\r\n structure-builder fits the diagram to the host size on load\r\n (fLoaded -> fitToScreen) and never re-fits, so mounting it inside\r\n the [hidden] (display:none, zero-size) container produces a blank\r\n canvas that doesn't recover when the tab is shown.\r\n -->\r\n @if (activeTab() === \"schema\") {\r\n <!--\r\n Use a concrete height (not lg:h-full). The diagram has no\r\n intrinsic height, and the tab's ancestor chain is block (not\r\n flex) on lg, so `h-full` collapses to 0 and the canvas renders\r\n blank. Mirrors the process preview's `h-[70vh]`.\r\n -->\r\n <div class=\"h-[70vh] min-h-[22rem] overflow-hidden rounded-lg\">\r\n <mt-structure-builder\r\n class=\"h-full\"\r\n [layoutDirection]=\"'LR'\"\r\n [readonly]=\"true\"\r\n [structureMode]=\"'workflow'\"\r\n [nodeFields]=\"previewNodeFields\"\r\n [nodes]=\"schemaNodes()\"\r\n [connections]=\"schemaConnections()\"\r\n />\r\n </div>\r\n }\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationSchemaUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationSchemaContextUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"h-full min-h-0 overflow-hidden\"\r\n [hidden]=\"activeTab() !== 'discussion'\"\r\n >\r\n @if (canRenderDiscussion()) {\r\n <div\r\n class=\"h-[32rem] min-h-[22rem] overflow-hidden rounded-lg border border-surface-200 bg-surface-50 lg:h-full lg:min-h-0\"\r\n >\r\n <mt-discussion-thread\r\n [moduleType]=\"'EscalationInstance'\"\r\n [recordId]=\"resolvedInstanceId()\"\r\n [mentionSearchEndpoint]=\"'Identity/users'\"\r\n [mentionSearchParam]=\"'query'\"\r\n [mentionSearchDataPath]=\"'data'\"\r\n [uploadEndpoint]=\"'uploader'\"\r\n [attachmentDownloadEndpoint]=\"'uploader'\"\r\n [showParticipants]=\"true\"\r\n [autoMarkRead]=\"true\"\r\n [refreshIntervalMs]=\"0\"\r\n [styleClass]=\"'h-full'\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationDiscussionUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DiscussionThread, selector: "mt-discussion-thread", inputs: ["moduleType", "recordId", "title", "subtitle", "placeholder", "pageSize", "currentUserId", "requestContext", "mentionableUsers", "mentionSearchEndpoint", "mentionSearchParam", "mentionSearchDataPath", "allowAttachments", "uploadEndpoint", "attachmentDownloadEndpoint", "showParticipants", "autoMarkRead", "refreshIntervalMs", "styleClass", "disabled"], outputs: ["loaded", "errored", "commentCreated", "commentUpdated", "commentDeleted", "readStateChanged"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape", "stackOnNarrow", "clickableKeys", "activeKeys", "clickableTooltip", "activeTooltip"], outputs: ["entityClick"] }, { kind: "component", type: ClientInstancePreview, selector: "mt-client-instance-preview", inputs: ["config", "hideEmptyState", "stackOnNarrow"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "availableNodesLabel", "nodeForm", "nodeDialogFooterConfig", "connectionForm", "connectionFormulaSchemaId", "connectionFormulaConfig", "
|
|
1282
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterEscalationInstanceType, isStandalone: true, selector: "mt-work-center-escalation-instance-type", inputs: { details: { classPropertyName: "details", publicName: "details", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div\r\n class=\"mt-modal-content flex h-full min-h-0 flex-col gap-4 p-4 lg:overflow-hidden\"\r\n *transloco=\"let t; prefix: 'workCenter'\"\r\n>\r\n <div\r\n class=\"flex flex-1 min-h-0 flex-col gap-4 lg:grid lg:grid-cols-[13rem_minmax(0,1fr)] lg:gap-6\"\r\n >\r\n @if (tabOptions().length > 1) {\r\n <mt-tabs\r\n [(active)]=\"activeTab\"\r\n [options]=\"tabOptions()\"\r\n mode=\"vertical\"\r\n size=\"small\"\r\n />\r\n }\r\n\r\n <div class=\"min-w-0 flex-1 min-h-0 lg:overflow-hidden\">\r\n <div\r\n class=\"h-full min-h-0 lg:overflow-hidden\"\r\n [hidden]=\"activeTab() !== 'escalationDetails'\"\r\n >\r\n <div\r\n class=\"min-w-0 h-full min-h-0 lg:overflow-y-auto lg:overscroll-contain lg:pr-2\"\r\n >\r\n @if (canRenderDetails()) {\r\n @if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"loading.escalationDetails\") }}\r\n </p>\r\n </div>\r\n } @else if (error(); as error) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">\r\n {{ error }}\r\n </p>\r\n </div>\r\n } @else if (preview()) {\r\n <mt-entities-preview [entities]=\"detailEntities()\" />\r\n }\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationDetailsUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div\r\n class=\"h-full min-h-0 lg:overflow-hidden\"\r\n [hidden]=\"activeTab() !== 'moduleDetails'\"\r\n >\r\n @if (moduleDetailsConfig(); as moduleDetailsConfig) {\r\n <div\r\n class=\"min-w-0 h-full min-h-0 lg:overflow-y-auto lg:overscroll-contain lg:pr-2\"\r\n >\r\n <mt-client-instance-preview [config]=\"moduleDetailsConfig\" />\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"flex-1 min-h-0 overflow-auto\"\r\n [hidden]=\"activeTab() !== 'schema'\"\r\n >\r\n @if (canRenderDetails()) {\r\n @if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"loading.escalationSchema\") }}\r\n </p>\r\n </div>\r\n } @else if (error(); as error) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">\r\n {{ error }}\r\n </p>\r\n </div>\r\n } @else if (hasSchema()) {\r\n <!--\r\n Only mount the flow once the schema tab is actually active. The\r\n structure-builder fits the diagram to the host size on load\r\n (fLoaded -> fitToScreen) and never re-fits, so mounting it inside\r\n the [hidden] (display:none, zero-size) container produces a blank\r\n canvas that doesn't recover when the tab is shown.\r\n -->\r\n @if (activeTab() === \"schema\") {\r\n <!--\r\n Use a concrete height (not lg:h-full). The diagram has no\r\n intrinsic height, and the tab's ancestor chain is block (not\r\n flex) on lg, so `h-full` collapses to 0 and the canvas renders\r\n blank. Mirrors the process preview's `h-[70vh]`.\r\n -->\r\n <div class=\"h-[70vh] min-h-[22rem] overflow-hidden rounded-lg\">\r\n <mt-structure-builder\r\n class=\"h-full\"\r\n [layoutDirection]=\"'LR'\"\r\n [readonly]=\"true\"\r\n [structureMode]=\"'workflow'\"\r\n [nodeFields]=\"previewNodeFields\"\r\n [nodes]=\"schemaNodes()\"\r\n [connections]=\"schemaConnections()\"\r\n />\r\n </div>\r\n }\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationSchemaUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationSchemaContextUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n\r\n <div\r\n class=\"h-full min-h-0 overflow-hidden\"\r\n [hidden]=\"activeTab() !== 'discussion'\"\r\n >\r\n @if (canRenderDiscussion()) {\r\n <div\r\n class=\"h-[32rem] min-h-[22rem] overflow-hidden rounded-lg border border-surface-200 bg-surface-50 lg:h-full lg:min-h-0\"\r\n >\r\n <mt-discussion-thread\r\n [moduleType]=\"'EscalationInstance'\"\r\n [recordId]=\"resolvedInstanceId()\"\r\n [mentionSearchEndpoint]=\"'Identity/users'\"\r\n [mentionSearchParam]=\"'query'\"\r\n [mentionSearchDataPath]=\"'data'\"\r\n [uploadEndpoint]=\"'uploader'\"\r\n [attachmentDownloadEndpoint]=\"'uploader'\"\r\n [showParticipants]=\"true\"\r\n [autoMarkRead]=\"true\"\r\n [refreshIntervalMs]=\"0\"\r\n [styleClass]=\"'h-full'\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n {{ t(\"context.escalationDiscussionUnavailable\") }}\r\n </p>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Tabs, selector: "mt-tabs", inputs: ["options", "optionLabel", "optionValue", "active", "mode", "moreLabel", "defaultIcon", "size", "fluid", "disabled", "searchThreshold"], outputs: ["activeChange", "onChange"] }, { kind: "component", type: DiscussionThread, selector: "mt-discussion-thread", inputs: ["moduleType", "recordId", "title", "subtitle", "placeholder", "pageSize", "currentUserId", "requestContext", "mentionableUsers", "mentionSearchEndpoint", "mentionSearchParam", "mentionSearchDataPath", "allowAttachments", "uploadEndpoint", "attachmentDownloadEndpoint", "showParticipants", "autoMarkRead", "refreshIntervalMs", "styleClass", "disabled"], outputs: ["loaded", "errored", "commentCreated", "commentUpdated", "commentDeleted", "readStateChanged"] }, { kind: "component", type: EntitiesPreview, selector: "mt-entities-preview", inputs: ["entities", "attachmentShape", "stackOnNarrow", "clickableKeys", "activeKeys", "clickableTooltip", "activeTooltip"], outputs: ["entityClick"] }, { kind: "component", type: ClientInstancePreview, selector: "mt-client-instance-preview", inputs: ["config", "hideEmptyState", "stackOnNarrow"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "availableNodesLabel", "nodeForm", "nodeDialogFooterConfig", "connectionForm", "connectionFormulaSchemaId", "connectionFormulaConfig", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "structureMode", "nodeStyle", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
|
|
1722
1283
|
}
|
|
1723
1284
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterEscalationInstanceType, decorators: [{
|
|
1724
1285
|
type: Component,
|
|
@@ -2107,7 +1668,7 @@ class WorkCenterProcessPreview {
|
|
|
2107
1668
|
});
|
|
2108
1669
|
}
|
|
2109
1670
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterProcessPreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2110
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterProcessPreview, isStandalone: true, selector: "mt-work-center-process-preview", inputs: { requestId: { classPropertyName: "requestId", publicName: "requestId", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (!canRenderPreview()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process preview is not available for this item yet.\r\n </p>\r\n </div>\r\n} @else if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"text-sm text-surface-500\">Loading process preview...</p>\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">{{ error() }}</p>\r\n </div>\r\n} @else {\r\n @if (view() === \"schema\") {\r\n @if (hasSchema()) {\r\n <div class=\"wc-process-preview-schema h-[70vh] overflow-hidden\">\r\n <mt-structure-builder\r\n class=\"h-full\"\r\n [layoutDirection]=\"'LR'\"\r\n [readonly]=\"true\"\r\n [structureMode]=\"'workflow'\"\r\n [nodeFields]=\"previewNodeFields\"\r\n [nodes]=\"schemaNodes()\"\r\n [connections]=\"schemaConnections()\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process steps are not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n } @else if (hasApprovals()) {\r\n <div class=\"max-h-[70vh] overflow-y-auto\">\r\n <mt-table\r\n noCard\r\n [data]=\"approvalRows()\"\r\n [columns]=\"approvalColumns()\"\r\n storageKey=\"work-center-process-preview-table\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [clickableRows]=\"false\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process approvals data is not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n}\r\n", styles: [":host ::ng-deep .wc-process-preview-schema .wf-detail-row{align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "availableNodesLabel", "nodeForm", "nodeDialogFooterConfig", "connectionForm", "connectionFormulaSchemaId", "connectionFormulaConfig", "
|
|
1671
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterProcessPreview, isStandalone: true, selector: "mt-work-center-process-preview", inputs: { requestId: { classPropertyName: "requestId", publicName: "requestId", isSignal: true, isRequired: false, transformFunction: null }, view: { classPropertyName: "view", publicName: "view", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (!canRenderPreview()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process preview is not available for this item yet.\r\n </p>\r\n </div>\r\n} @else if (loading()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"text-sm text-surface-500\">Loading process preview...</p>\r\n </div>\r\n} @else if (error()) {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-red-300 bg-red-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-red-600\">{{ error() }}</p>\r\n </div>\r\n} @else {\r\n @if (view() === \"schema\") {\r\n @if (hasSchema()) {\r\n <div class=\"wc-process-preview-schema h-[70vh] overflow-hidden\">\r\n <mt-structure-builder\r\n class=\"h-full\"\r\n [layoutDirection]=\"'LR'\"\r\n [readonly]=\"true\"\r\n [structureMode]=\"'workflow'\"\r\n [nodeFields]=\"previewNodeFields\"\r\n [nodes]=\"schemaNodes()\"\r\n [connections]=\"schemaConnections()\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process steps are not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n } @else if (hasApprovals()) {\r\n <div class=\"max-h-[70vh] overflow-y-auto\">\r\n <mt-table\r\n noCard\r\n [data]=\"approvalRows()\"\r\n [columns]=\"approvalColumns()\"\r\n storageKey=\"work-center-process-preview-table\"\r\n [showFilters]=\"false\"\r\n [generalSearch]=\"false\"\r\n [clickableRows]=\"false\"\r\n />\r\n </div>\r\n } @else {\r\n <div\r\n class=\"flex min-h-[22rem] items-center justify-center rounded-lg border border-dashed border-surface-300 bg-surface-50 p-6\"\r\n >\r\n <p class=\"max-w-md text-center text-sm text-surface-500\">\r\n Process approvals data is not available for this item yet.\r\n </p>\r\n </div>\r\n }\r\n}\r\n", styles: [":host ::ng-deep .wc-process-preview-schema .wf-detail-row{align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "component", type: StructureBuilder, selector: "mt-structure-builder", inputs: ["availableNodes", "availableNodesLabel", "nodeForm", "nodeDialogFooterConfig", "connectionForm", "connectionFormulaSchemaId", "connectionFormulaConfig", "nodeActions", "nodeFields", "isAutoLayout", "readonly", "structureMode", "nodeStyle", "addModalType", "updateModalType", "addModalStyleClass", "updateModalStyleClass", "addModalHeader", "updateModalHeader", "appendTo", "availableTabsClass", "layoutDirection", "nodes", "connections", "nodeTemplate"], outputs: ["nodeActionsEvent", "action", "nodesChange", "connectionsChange"] }] });
|
|
2111
1672
|
}
|
|
2112
1673
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterProcessPreview, decorators: [{
|
|
2113
1674
|
type: Component,
|
|
@@ -2690,7 +2251,10 @@ class WorkCenterItemModalRoute {
|
|
|
2690
2251
|
modal = inject(ModalService);
|
|
2691
2252
|
lookups = this.facade.lookups;
|
|
2692
2253
|
contextKey = input(null, ...(ngDevMode ? [{ debugName: "contextKey" }] : /* istanbul ignore next */ []));
|
|
2254
|
+
manageRouteOutlet = input(true, ...(ngDevMode ? [{ debugName: "manageRouteOutlet" }] : /* istanbul ignore next */ []));
|
|
2255
|
+
showPreviewLevelAction = input(true, ...(ngDevMode ? [{ debugName: "showPreviewLevelAction" }] : /* istanbul ignore next */ []));
|
|
2693
2256
|
previewLevel = output();
|
|
2257
|
+
closed = output();
|
|
2694
2258
|
drawerVisible = signal(true, ...(ngDevMode ? [{ debugName: "drawerVisible" }] : /* istanbul ignore next */ []));
|
|
2695
2259
|
loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
|
|
2696
2260
|
error = signal(null, ...(ngDevMode ? [{ debugName: "error" }] : /* istanbul ignore next */ []));
|
|
@@ -2702,6 +2266,7 @@ class WorkCenterItemModalRoute {
|
|
|
2702
2266
|
this.transloco.translate('workCenter.page.itemDetails'), ...(ngDevMode ? [{ debugName: "drawerTitle" }] : /* istanbul ignore next */ []));
|
|
2703
2267
|
drawerSubtitle = computed(() => this.readDisplayField(this.details()?.item, 'subtitle') ?? '', ...(ngDevMode ? [{ debugName: "drawerSubtitle" }] : /* istanbul ignore next */ []));
|
|
2704
2268
|
previewLevelTarget = computed(() => this.resolvePreviewLevelTarget(this.details()), ...(ngDevMode ? [{ debugName: "previewLevelTarget" }] : /* istanbul ignore next */ []));
|
|
2269
|
+
displayedPreviewLevelTarget = computed(() => this.showPreviewLevelAction() ? this.previewLevelTarget() : null, ...(ngDevMode ? [{ debugName: "displayedPreviewLevelTarget" }] : /* istanbul ignore next */ []));
|
|
2705
2270
|
constructor() {
|
|
2706
2271
|
effect(() => {
|
|
2707
2272
|
this.footerActionsMounted.set(!!this.resolvedContextKey());
|
|
@@ -2763,7 +2328,7 @@ class WorkCenterItemModalRoute {
|
|
|
2763
2328
|
// menu/KPI counters are stale regardless of whether the dialog closes.
|
|
2764
2329
|
this.facade.loadRuntime(this.facade.activeArea(), 'refresh');
|
|
2765
2330
|
if (result.afterSuccess === 'close') {
|
|
2766
|
-
void this.
|
|
2331
|
+
void this.close();
|
|
2767
2332
|
return;
|
|
2768
2333
|
}
|
|
2769
2334
|
this.detailsReloadTick.update((value) => value + 1);
|
|
@@ -2780,7 +2345,14 @@ class WorkCenterItemModalRoute {
|
|
|
2780
2345
|
if (visible) {
|
|
2781
2346
|
return;
|
|
2782
2347
|
}
|
|
2783
|
-
await this.
|
|
2348
|
+
await this.close();
|
|
2349
|
+
}
|
|
2350
|
+
close() {
|
|
2351
|
+
if (!this.manageRouteOutlet()) {
|
|
2352
|
+
this.closed.emit();
|
|
2353
|
+
return Promise.resolve(true);
|
|
2354
|
+
}
|
|
2355
|
+
return this.closeRouteOutlet();
|
|
2784
2356
|
}
|
|
2785
2357
|
closeRouteOutlet() {
|
|
2786
2358
|
console.log('[work-center-debug] modal route closing', {
|
|
@@ -2842,7 +2414,7 @@ class WorkCenterItemModalRoute {
|
|
|
2842
2414
|
};
|
|
2843
2415
|
}
|
|
2844
2416
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterItemModalRoute, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2845
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterItemModalRoute, isStandalone: true, selector: "mt-work-center-item-modal-route", inputs: { contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previewLevel: "previewLevel" }, providers: [RuntimeActionContextStore], ngImport: i0, template: "<mt-drawer\
|
|
2417
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterItemModalRoute, isStandalone: true, selector: "mt-work-center-item-modal-route", inputs: { contextKey: { classPropertyName: "contextKey", publicName: "contextKey", isSignal: true, isRequired: false, transformFunction: null }, manageRouteOutlet: { classPropertyName: "manageRouteOutlet", publicName: "manageRouteOutlet", isSignal: true, isRequired: false, transformFunction: null }, showPreviewLevelAction: { classPropertyName: "showPreviewLevelAction", publicName: "showPreviewLevelAction", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { previewLevel: "previewLevel", closed: "closed" }, providers: [RuntimeActionContextStore], ngImport: i0, template: "<mt-drawer\n [visible]=\"drawerVisible()\"\n [loadingHeader]=\"loading()\"\n [title]=\"drawerTitle()\"\n styleClass=\"mt-work-center-item-drawer !absolute !w-[96vw] md:!w-[84vw] xl:!w-[70vw]\"\n position=\"right\"\n [modal]=\"true\"\n (visibleChange)=\"onVisibleChange($event)\"\n *transloco=\"let t; prefix: 'workCenter'\"\n>\n <ng-container content>\n @if (loading()) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] flex-col gap-5\">\n <div class=\"flex items-center gap-3\">\n <p-skeleton shape=\"circle\" size=\"3rem\" />\n <div class=\"flex flex-1 flex-col gap-2\">\n <p-skeleton width=\"12rem\" height=\"1rem\" />\n <p-skeleton width=\"8rem\" height=\"0.875rem\" />\n </div>\n </div>\n\n <div class=\"grid gap-3 md:grid-cols-2\">\n @for (_ of [1, 2, 3, 4]; track $index) {\n <p-skeleton height=\"5rem\" class=\"rounded-lg\" />\n }\n </div>\n\n <p-skeleton height=\"16rem\" class=\"rounded-lg\" />\n </div>\n </div>\n } @else if (error(); as errorMessage) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"max-w-xl text-sm font-medium text-red-600\">\n {{ errorMessage }}\n </p>\n </div>\n </div>\n } @else if (details(); as details) {\n <div [class]=\"modal.contentClass + ' h-full min-h-0'\">\n <mt-work-center-item-modal [details]=\"details\" [lookups]=\"lookups()\" />\n </div>\n } @else {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"text-sm font-medium text-surface-500\">\n {{ t(\"modal.noItemSelected\") }}\n </p>\n </div>\n </div>\n }\n </ng-container>\n\n @if (footerActionsMounted()) {\n <div footer [class]=\"modal.footerClass\">\n <mt-work-center-item-modal-footer-actions\n [contextKey]=\"resolvedContextKey()\"\n [previewLevelTarget]=\"displayedPreviewLevelTarget()\"\n (actionExecuted)=\"onActionExecuted($event)\"\n (previewLevelSelected)=\"onPreviewLevelSelected($event)\"\n (visibilityChange)=\"onFooterVisibilityChange($event)\"\n />\n </div>\n }\n</mt-drawer>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: TranslocoDirective, selector: "[transloco]", inputs: ["transloco", "translocoParams", "translocoScope", "translocoRead", "translocoPrefix", "translocoLang", "translocoLoadingTpl"] }, { kind: "component", type: Drawer, selector: "mt-drawer", inputs: ["visible", "position", "fullScreen", "closeOnEscape", "blockScroll", "dismissible", "title", "subtitle", "loadingHeader", "styleClass", "transitionOptions", "appendTo", "modal", "showMaximizeToggle", "maximizeTooltip", "restoreTooltip", "maximized"], outputs: ["visibleChange", "onShow", "onHide", "maximizedChange"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }, { kind: "component", type: WorkCenterItemModal, selector: "mt-work-center-item-modal", inputs: ["details", "lookups"] }, { kind: "component", type: WorkCenterItemModalFooterActions, selector: "mt-work-center-item-modal-footer-actions", inputs: ["contextKey", "previewLevelTarget"], outputs: ["actionExecuted", "previewLevelSelected", "visibilityChange"] }] });
|
|
2846
2418
|
}
|
|
2847
2419
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterItemModalRoute, decorators: [{
|
|
2848
2420
|
type: Component,
|
|
@@ -2853,8 +2425,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
2853
2425
|
SkeletonModule,
|
|
2854
2426
|
WorkCenterItemModal,
|
|
2855
2427
|
WorkCenterItemModalFooterActions,
|
|
2856
|
-
], providers: [RuntimeActionContextStore], template: "<mt-drawer\
|
|
2857
|
-
}], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }], previewLevel: [{ type: i0.Output, args: ["previewLevel"] }] } });
|
|
2428
|
+
], providers: [RuntimeActionContextStore], template: "<mt-drawer\n [visible]=\"drawerVisible()\"\n [loadingHeader]=\"loading()\"\n [title]=\"drawerTitle()\"\n styleClass=\"mt-work-center-item-drawer !absolute !w-[96vw] md:!w-[84vw] xl:!w-[70vw]\"\n position=\"right\"\n [modal]=\"true\"\n (visibleChange)=\"onVisibleChange($event)\"\n *transloco=\"let t; prefix: 'workCenter'\"\n>\n <ng-container content>\n @if (loading()) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] flex-col gap-5\">\n <div class=\"flex items-center gap-3\">\n <p-skeleton shape=\"circle\" size=\"3rem\" />\n <div class=\"flex flex-1 flex-col gap-2\">\n <p-skeleton width=\"12rem\" height=\"1rem\" />\n <p-skeleton width=\"8rem\" height=\"0.875rem\" />\n </div>\n </div>\n\n <div class=\"grid gap-3 md:grid-cols-2\">\n @for (_ of [1, 2, 3, 4]; track $index) {\n <p-skeleton height=\"5rem\" class=\"rounded-lg\" />\n }\n </div>\n\n <p-skeleton height=\"16rem\" class=\"rounded-lg\" />\n </div>\n </div>\n } @else if (error(); as errorMessage) {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"max-w-xl text-sm font-medium text-red-600\">\n {{ errorMessage }}\n </p>\n </div>\n </div>\n } @else if (details(); as details) {\n <div [class]=\"modal.contentClass + ' h-full min-h-0'\">\n <mt-work-center-item-modal [details]=\"details\" [lookups]=\"lookups()\" />\n </div>\n } @else {\n <div class=\"p-4\" [class]=\"modal.contentClass\">\n <div class=\"flex min-h-[22rem] items-center justify-center\">\n <p class=\"text-sm font-medium text-surface-500\">\n {{ t(\"modal.noItemSelected\") }}\n </p>\n </div>\n </div>\n }\n </ng-container>\n\n @if (footerActionsMounted()) {\n <div footer [class]=\"modal.footerClass\">\n <mt-work-center-item-modal-footer-actions\n [contextKey]=\"resolvedContextKey()\"\n [previewLevelTarget]=\"displayedPreviewLevelTarget()\"\n (actionExecuted)=\"onActionExecuted($event)\"\n (previewLevelSelected)=\"onPreviewLevelSelected($event)\"\n (visibilityChange)=\"onFooterVisibilityChange($event)\"\n />\n </div>\n }\n</mt-drawer>\n" }]
|
|
2429
|
+
}], ctorParameters: () => [], propDecorators: { contextKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "contextKey", required: false }] }], manageRouteOutlet: [{ type: i0.Input, args: [{ isSignal: true, alias: "manageRouteOutlet", required: false }] }], showPreviewLevelAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreviewLevelAction", required: false }] }], previewLevel: [{ type: i0.Output, args: ["previewLevel"] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
2858
2430
|
// Accepts either a plain string (e.g. `moduleKey`) or a localized
|
|
2859
2431
|
// `{ display, en, ar }` translatable, returning the display string.
|
|
2860
2432
|
function normalizeDisplayName(value) {
|
|
@@ -2882,6 +2454,469 @@ function normalizeRouteId(value) {
|
|
|
2882
2454
|
return null;
|
|
2883
2455
|
}
|
|
2884
2456
|
|
|
2457
|
+
const OPERATOR_LABELS = {
|
|
2458
|
+
Eq: 'Equals',
|
|
2459
|
+
Neq: 'Not equal',
|
|
2460
|
+
In: 'In',
|
|
2461
|
+
Contains: 'Contains',
|
|
2462
|
+
StartsWith: 'Starts with',
|
|
2463
|
+
Gt: 'Greater than',
|
|
2464
|
+
Gte: 'Greater than or equal',
|
|
2465
|
+
Lt: 'Less than',
|
|
2466
|
+
Lte: 'Less than or equal',
|
|
2467
|
+
Between: 'Between',
|
|
2468
|
+
IsNull: 'Is empty',
|
|
2469
|
+
IsNotNull: 'Is not empty',
|
|
2470
|
+
};
|
|
2471
|
+
const OPERATOR_VALUE_MODE = {
|
|
2472
|
+
In: 'multi',
|
|
2473
|
+
Between: 'range',
|
|
2474
|
+
IsNull: 'none',
|
|
2475
|
+
IsNotNull: 'none',
|
|
2476
|
+
};
|
|
2477
|
+
const GENERAL_TASK_CARD_KEYS = new Set([
|
|
2478
|
+
'mygeneraltasks',
|
|
2479
|
+
'generaltask',
|
|
2480
|
+
'generaltasks',
|
|
2481
|
+
]);
|
|
2482
|
+
function toLabel(value) {
|
|
2483
|
+
const normalized = value.split('.').pop() ?? value;
|
|
2484
|
+
return normalized
|
|
2485
|
+
.replace(/[_-]/g, ' ')
|
|
2486
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
2487
|
+
.trim()
|
|
2488
|
+
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
2489
|
+
}
|
|
2490
|
+
function columnTypeToViewType(type) {
|
|
2491
|
+
if (type === 'date')
|
|
2492
|
+
return 'Date';
|
|
2493
|
+
return undefined;
|
|
2494
|
+
}
|
|
2495
|
+
function normalizeCardKey(value) {
|
|
2496
|
+
if (typeof value !== 'string') {
|
|
2497
|
+
return '';
|
|
2498
|
+
}
|
|
2499
|
+
return value
|
|
2500
|
+
.trim()
|
|
2501
|
+
.replace(/[\s_-]/g, '')
|
|
2502
|
+
.toLowerCase();
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2505
|
+
* Strips the user envelope used by `mt-table` user filters down to the
|
|
2506
|
+
* scalar id that the BE rule payload accepts. Falls back to the original
|
|
2507
|
+
* value for non-user shapes (e.g. simple string in a select filter).
|
|
2508
|
+
*/
|
|
2509
|
+
function extractIdScalar(value) {
|
|
2510
|
+
if (value !== null &&
|
|
2511
|
+
typeof value === 'object' &&
|
|
2512
|
+
'id' in value) {
|
|
2513
|
+
return value['id'];
|
|
2514
|
+
}
|
|
2515
|
+
return value;
|
|
2516
|
+
}
|
|
2517
|
+
function toIsoDate(value) {
|
|
2518
|
+
if (value instanceof Date)
|
|
2519
|
+
return value.toISOString();
|
|
2520
|
+
return value;
|
|
2521
|
+
}
|
|
2522
|
+
/**
|
|
2523
|
+
* Translates one in-table column filter value into a `WorkCenterFilterRule`.
|
|
2524
|
+
*
|
|
2525
|
+
* The shape of `raw` depends on the column's filter type — see
|
|
2526
|
+
* `mt-table` `table-filter-field` outputs:
|
|
2527
|
+
* - text → string → `Contains`
|
|
2528
|
+
* - select → scalar | scalar[] → `Eq` | `In`
|
|
2529
|
+
* - boolean → boolean → `Eq`
|
|
2530
|
+
* - date → `{ from?, to?, value? }` (Date|null)→ `Between`/`Gte`/`Lte`/`Eq`
|
|
2531
|
+
* - user → `{ id, ... }` | `{ id, ... }[]` → `Eq` (id) | `In` (ids)
|
|
2532
|
+
*
|
|
2533
|
+
* Returns `null` when the value is empty / nothing to send.
|
|
2534
|
+
*/
|
|
2535
|
+
function toRuntimeFilterRule(field, raw, column) {
|
|
2536
|
+
if (raw === null || raw === undefined || raw === '')
|
|
2537
|
+
return null;
|
|
2538
|
+
if (typeof raw === 'boolean') {
|
|
2539
|
+
return { field, op: 'Eq', value: raw };
|
|
2540
|
+
}
|
|
2541
|
+
if (typeof raw === 'number') {
|
|
2542
|
+
return { field, op: 'Eq', value: raw };
|
|
2543
|
+
}
|
|
2544
|
+
if (typeof raw === 'string') {
|
|
2545
|
+
if (!raw.trim().length)
|
|
2546
|
+
return null;
|
|
2547
|
+
return { field, op: 'Contains', value: raw };
|
|
2548
|
+
}
|
|
2549
|
+
if (Array.isArray(raw)) {
|
|
2550
|
+
const values = raw
|
|
2551
|
+
.map(extractIdScalar)
|
|
2552
|
+
.filter((v) => v !== null && v !== undefined && v !== '');
|
|
2553
|
+
if (!values.length)
|
|
2554
|
+
return null;
|
|
2555
|
+
return { field, op: 'In', values };
|
|
2556
|
+
}
|
|
2557
|
+
if (typeof raw === 'object') {
|
|
2558
|
+
const obj = raw;
|
|
2559
|
+
// User filter envelope -> single-id Eq.
|
|
2560
|
+
if (obj.id !== undefined && obj.id !== null && obj.id !== '') {
|
|
2561
|
+
return { field, op: 'Eq', value: obj.id };
|
|
2562
|
+
}
|
|
2563
|
+
const hasFrom = obj.from !== undefined && obj.from !== null;
|
|
2564
|
+
const hasTo = obj.to !== undefined && obj.to !== null;
|
|
2565
|
+
if (hasFrom && hasTo) {
|
|
2566
|
+
return {
|
|
2567
|
+
field,
|
|
2568
|
+
op: 'Between',
|
|
2569
|
+
from: toIsoDate(obj.from),
|
|
2570
|
+
to: toIsoDate(obj.to),
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
if (hasFrom) {
|
|
2574
|
+
return { field, op: 'Gte', value: toIsoDate(obj.from) };
|
|
2575
|
+
}
|
|
2576
|
+
if (hasTo) {
|
|
2577
|
+
return { field, op: 'Lte', value: toIsoDate(obj.to) };
|
|
2578
|
+
}
|
|
2579
|
+
if (obj.value !== undefined && obj.value !== null && obj.value !== '') {
|
|
2580
|
+
const treatAsContains = column?.type === 'text' ||
|
|
2581
|
+
(column?.filterConfig?.type === 'text' &&
|
|
2582
|
+
typeof obj.value === 'string');
|
|
2583
|
+
if (treatAsContains) {
|
|
2584
|
+
return { field, op: 'Contains', value: obj.value };
|
|
2585
|
+
}
|
|
2586
|
+
return { field, op: 'Eq', value: extractIdScalar(obj.value) };
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
return null;
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* Walks `mt-table`'s filter map and produces the `WorkCenterFilterRule[]`
|
|
2593
|
+
* sent on the BE column-filter slice. The synthetic `generalSearch` key is
|
|
2594
|
+
* skipped because the page keeps general search local-only.
|
|
2595
|
+
*/
|
|
2596
|
+
function buildColumnRuntimeFilters(filters, columns, allowedFields) {
|
|
2597
|
+
if (!filters)
|
|
2598
|
+
return [];
|
|
2599
|
+
const allowed = allowedFields && allowedFields.length ? new Set(allowedFields) : null;
|
|
2600
|
+
const columnByKey = new Map(columns.map((col) => [col.key, col]));
|
|
2601
|
+
const rules = [];
|
|
2602
|
+
for (const [key, raw] of Object.entries(filters)) {
|
|
2603
|
+
if (key === 'generalSearch')
|
|
2604
|
+
continue;
|
|
2605
|
+
if (allowed && !allowed.has(key))
|
|
2606
|
+
continue;
|
|
2607
|
+
const rule = toRuntimeFilterRule(key, raw, columnByKey.get(key));
|
|
2608
|
+
if (rule)
|
|
2609
|
+
rules.push(rule);
|
|
2610
|
+
}
|
|
2611
|
+
return rules;
|
|
2612
|
+
}
|
|
2613
|
+
function areFilterRulesEqual(left, right) {
|
|
2614
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
2615
|
+
}
|
|
2616
|
+
function mapAllowedFields(schema) {
|
|
2617
|
+
const properties = schema.properties ?? [];
|
|
2618
|
+
const fromProperties = properties
|
|
2619
|
+
.filter((property) => typeof property?.key === 'string' && property.key.length > 0)
|
|
2620
|
+
.map((property) => ({
|
|
2621
|
+
key: property.key,
|
|
2622
|
+
label: property.name?.display ||
|
|
2623
|
+
property.name?.en ||
|
|
2624
|
+
property.name?.ar ||
|
|
2625
|
+
toLabel(property.key),
|
|
2626
|
+
viewType: property.viewType,
|
|
2627
|
+
}));
|
|
2628
|
+
if (fromProperties.length) {
|
|
2629
|
+
return fromProperties;
|
|
2630
|
+
}
|
|
2631
|
+
return (schema.allowedFields ?? []).map((field) => ({
|
|
2632
|
+
key: field,
|
|
2633
|
+
label: toLabel(field),
|
|
2634
|
+
}));
|
|
2635
|
+
}
|
|
2636
|
+
function mapAllowedOperators(schema, getLabel) {
|
|
2637
|
+
const options = [];
|
|
2638
|
+
for (const operator of schema.allowedOperators ?? []) {
|
|
2639
|
+
if (typeof operator === 'string') {
|
|
2640
|
+
options.push({
|
|
2641
|
+
key: operator,
|
|
2642
|
+
label: getLabel(operator),
|
|
2643
|
+
valueMode: OPERATOR_VALUE_MODE[operator] ?? 'single',
|
|
2644
|
+
});
|
|
2645
|
+
continue;
|
|
2646
|
+
}
|
|
2647
|
+
const key = operator?.value;
|
|
2648
|
+
if (!key) {
|
|
2649
|
+
continue;
|
|
2650
|
+
}
|
|
2651
|
+
options.push({
|
|
2652
|
+
key,
|
|
2653
|
+
label: operator.display?.display ||
|
|
2654
|
+
operator.display?.en ||
|
|
2655
|
+
operator.display?.ar ||
|
|
2656
|
+
getLabel(key),
|
|
2657
|
+
valueMode: OPERATOR_VALUE_MODE[key] ?? 'single',
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2660
|
+
return options;
|
|
2661
|
+
}
|
|
2662
|
+
class WorkCenterPage {
|
|
2663
|
+
facade = inject(WorkCenterFacade);
|
|
2664
|
+
modal = inject(ModalService);
|
|
2665
|
+
transloco = inject(TranslocoService);
|
|
2666
|
+
destroyRef = inject(DestroyRef);
|
|
2667
|
+
activeLang = signal(this.transloco.getActiveLang(), ...(ngDevMode ? [{ debugName: "activeLang" }] : /* istanbul ignore next */ []));
|
|
2668
|
+
area = input('MyInbox', ...(ngDevMode ? [{ debugName: "area" }] : /* istanbul ignore next */ []));
|
|
2669
|
+
pageTitle = input('', ...(ngDevMode ? [{ debugName: "pageTitle" }] : /* istanbul ignore next */ []));
|
|
2670
|
+
menuIcon = input('communication.inbox-01', ...(ngDevMode ? [{ debugName: "menuIcon" }] : /* istanbul ignore next */ []));
|
|
2671
|
+
lookups = input([], ...(ngDevMode ? [{ debugName: "lookups" }] : /* istanbul ignore next */ []));
|
|
2672
|
+
showSidebar = input(true, ...(ngDevMode ? [{ debugName: "showSidebar" }] : /* istanbul ignore next */ []));
|
|
2673
|
+
bootstrapInputs = input(null, ...(ngDevMode ? [{ debugName: "bootstrapInputs" }] : /* istanbul ignore next */ []));
|
|
2674
|
+
openItemDrawer = input(false, ...(ngDevMode ? [{ debugName: "openItemDrawer" }] : /* istanbul ignore next */ []));
|
|
2675
|
+
openItemsInModal = input(true, ...(ngDevMode ? [{ debugName: "openItemsInModal" }] : /* istanbul ignore next */ []));
|
|
2676
|
+
itemModal = input(null, ...(ngDevMode ? [{ debugName: "itemModal" }] : /* istanbul ignore next */ []));
|
|
2677
|
+
generalTaskModal = input(null, ...(ngDevMode ? [{ debugName: "generalTaskModal" }] : /* istanbul ignore next */ []));
|
|
2678
|
+
runtimeFiltersChanged = output();
|
|
2679
|
+
itemClicked = output();
|
|
2680
|
+
cardSelected = output();
|
|
2681
|
+
context = this.facade.context;
|
|
2682
|
+
headerFilters = this.facade.headerFilters;
|
|
2683
|
+
tableFilters = signal({}, ...(ngDevMode ? [{ debugName: "tableFilters" }] : /* istanbul ignore next */ []));
|
|
2684
|
+
selectedItemContextKey = signal(null, ...(ngDevMode ? [{ debugName: "selectedItemContextKey" }] : /* istanbul ignore next */ []));
|
|
2685
|
+
_menuItems = this.facade.menuItems;
|
|
2686
|
+
menuItems = computed(() => {
|
|
2687
|
+
this.activeLang();
|
|
2688
|
+
return this._menuItems().map((item) => ({
|
|
2689
|
+
...item,
|
|
2690
|
+
subtitle: `${item.count} ${item.title}`,
|
|
2691
|
+
}));
|
|
2692
|
+
}, ...(ngDevMode ? [{ debugName: "menuItems" }] : /* istanbul ignore next */ []));
|
|
2693
|
+
rows = this.facade.rows;
|
|
2694
|
+
columns = this.facade.columns;
|
|
2695
|
+
kpis = this.facade.kpis;
|
|
2696
|
+
runtimeFilterSchema = this.facade.runtimeFilterSchema;
|
|
2697
|
+
totalCount = this.facade.totalCount;
|
|
2698
|
+
columnFilters = this.facade.columnFilters;
|
|
2699
|
+
loading = this.facade.loading;
|
|
2700
|
+
tableColumns = computed(() => this.columns().map((column) => ({
|
|
2701
|
+
...column,
|
|
2702
|
+
sortable: true,
|
|
2703
|
+
})), ...(ngDevMode ? [{ debugName: "tableColumns" }] : /* istanbul ignore next */ []));
|
|
2704
|
+
/**
|
|
2705
|
+
* Maps each status/group display label to its total count from the KPI
|
|
2706
|
+
* summary cards so the group header shows the real backend total rather than
|
|
2707
|
+
* the current-page row count.
|
|
2708
|
+
*/
|
|
2709
|
+
statusGroupCountMap = computed(() => {
|
|
2710
|
+
const map = new Map();
|
|
2711
|
+
for (const kpi of this.kpis()) {
|
|
2712
|
+
const label = kpi.subTitle;
|
|
2713
|
+
const count = Number(kpi.title);
|
|
2714
|
+
if (label && !isNaN(count)) {
|
|
2715
|
+
map.set(label, count);
|
|
2716
|
+
}
|
|
2717
|
+
}
|
|
2718
|
+
return map;
|
|
2719
|
+
}, ...(ngDevMode ? [{ debugName: "statusGroupCountMap" }] : /* istanbul ignore next */ []));
|
|
2720
|
+
propertyFilterSchema = computed(() => {
|
|
2721
|
+
this.activeLang();
|
|
2722
|
+
const schema = this.runtimeFilterSchema();
|
|
2723
|
+
if (schema) {
|
|
2724
|
+
const allowedFields = mapAllowedFields(schema);
|
|
2725
|
+
const allowedOperators = mapAllowedOperators(schema, (key) => this.getOpLabel(key));
|
|
2726
|
+
if (allowedFields.length && allowedOperators.length) {
|
|
2727
|
+
return { allowedFields, allowedOperators };
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2730
|
+
const fallbackFields = this.columns()
|
|
2731
|
+
.filter((column) => typeof column?.key === 'string' && column.key.length > 0)
|
|
2732
|
+
.map((column) => ({
|
|
2733
|
+
key: column.key,
|
|
2734
|
+
label: column.label || toLabel(column.key),
|
|
2735
|
+
viewType: columnTypeToViewType(column.type),
|
|
2736
|
+
}));
|
|
2737
|
+
if (!fallbackFields.length) {
|
|
2738
|
+
return null;
|
|
2739
|
+
}
|
|
2740
|
+
const fallbackOperators = Object.keys(OPERATOR_LABELS).map((key) => ({
|
|
2741
|
+
key,
|
|
2742
|
+
label: this.getOpLabel(key),
|
|
2743
|
+
valueMode: OPERATOR_VALUE_MODE[key] ?? 'single',
|
|
2744
|
+
}));
|
|
2745
|
+
return {
|
|
2746
|
+
allowedFields: fallbackFields,
|
|
2747
|
+
allowedOperators: fallbackOperators,
|
|
2748
|
+
};
|
|
2749
|
+
}, ...(ngDevMode ? [{ debugName: "propertyFilterSchema" }] : /* istanbul ignore next */ []));
|
|
2750
|
+
showGeneralTaskCreateButton = computed(() => GENERAL_TASK_CARD_KEYS.has(normalizeCardKey(this.context().selectedCardKey)), ...(ngDevMode ? [{ debugName: "showGeneralTaskCreateButton" }] : /* istanbul ignore next */ []));
|
|
2751
|
+
generalTaskButtonLabel = computed(() => {
|
|
2752
|
+
this.activeLang();
|
|
2753
|
+
return (this.generalTaskModal()?.buttonLabel?.trim() ||
|
|
2754
|
+
this.transloco.translate('workCenter.page.new'));
|
|
2755
|
+
}, ...(ngDevMode ? [{ debugName: "generalTaskButtonLabel" }] : /* istanbul ignore next */ []));
|
|
2756
|
+
resolvedPageTitle = computed(() => {
|
|
2757
|
+
this.activeLang();
|
|
2758
|
+
return (this.pageTitle() ||
|
|
2759
|
+
this.transloco.translate('workCenter.page.title'));
|
|
2760
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedPageTitle" }] : /* istanbul ignore next */ []));
|
|
2761
|
+
generalTaskButtonIcon = computed(() => this.generalTaskModal()?.buttonIcon?.trim() || 'general.plus', ...(ngDevMode ? [{ debugName: "generalTaskButtonIcon" }] : /* istanbul ignore next */ []));
|
|
2762
|
+
defaultModalStyleClass = '!w-[96vw] md:!w-[84vw] xl:!w-[70vw] !shadow-none';
|
|
2763
|
+
defaultGeneralTaskModalStyleClass = '!w-[70vw] !h-[90vh]';
|
|
2764
|
+
constructor() {
|
|
2765
|
+
this.transloco.langChanges$
|
|
2766
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
2767
|
+
.subscribe((lang) => this.activeLang.set(lang));
|
|
2768
|
+
effect(() => {
|
|
2769
|
+
this.facade.setLookups(this.lookups());
|
|
2770
|
+
});
|
|
2771
|
+
effect(() => {
|
|
2772
|
+
const inputs = this.bootstrapInputs();
|
|
2773
|
+
if (inputs) {
|
|
2774
|
+
this.facade.setParams(this.area(), inputs);
|
|
2775
|
+
}
|
|
2776
|
+
});
|
|
2777
|
+
}
|
|
2778
|
+
onMenuItemClick(item) {
|
|
2779
|
+
if (item.key === this.context().selectedCardKey) {
|
|
2780
|
+
return;
|
|
2781
|
+
}
|
|
2782
|
+
this.facade.selectCardAndLoad(this.area(), item.key);
|
|
2783
|
+
this.cardSelected.emit(item.key);
|
|
2784
|
+
}
|
|
2785
|
+
onRuntimeFiltersApplied(filters) {
|
|
2786
|
+
const mappedFilters = filters.map((filter) => ({
|
|
2787
|
+
field: filter.field,
|
|
2788
|
+
op: filter.op,
|
|
2789
|
+
value: filter.value,
|
|
2790
|
+
values: filter.values,
|
|
2791
|
+
from: filter.from,
|
|
2792
|
+
to: filter.to,
|
|
2793
|
+
}));
|
|
2794
|
+
this.facade.applyHeaderFiltersAndLoad(this.area(), mappedFilters);
|
|
2795
|
+
this.runtimeFiltersChanged.emit(mappedFilters);
|
|
2796
|
+
}
|
|
2797
|
+
onRuntimeFiltersCleared() {
|
|
2798
|
+
this.facade.clearAllFiltersAndLoad(this.area());
|
|
2799
|
+
this.tableFilters.set({});
|
|
2800
|
+
this.runtimeFiltersChanged.emit([]);
|
|
2801
|
+
}
|
|
2802
|
+
/**
|
|
2803
|
+
* Single entry point for `mt-table` (`lazy=true`) — handles both column
|
|
2804
|
+
* filters and pagination/sort. Filter changes always reset the page to 1
|
|
2805
|
+
* (handled by `applyColumnFiltersAndLoad`); when only paging/sort changed
|
|
2806
|
+
* we fall through to `applyTableLazyLoadAndLoad`.
|
|
2807
|
+
*/
|
|
2808
|
+
onTableLazyLoad(event) {
|
|
2809
|
+
const schema = this.runtimeFilterSchema();
|
|
2810
|
+
const propertyKeys = (schema?.properties ?? [])
|
|
2811
|
+
.map((p) => p?.key)
|
|
2812
|
+
.filter((k) => typeof k === 'string' && k.length > 0);
|
|
2813
|
+
const allowedKeys = schema?.allowedFields ?? [];
|
|
2814
|
+
const allowedFields = propertyKeys.length ? propertyKeys : allowedKeys;
|
|
2815
|
+
const nextColumnFilters = buildColumnRuntimeFilters(event?.filters, this.columns(), allowedFields.length ? allowedFields : undefined);
|
|
2816
|
+
if (!areFilterRulesEqual(nextColumnFilters, this.columnFilters())) {
|
|
2817
|
+
this.facade.applyColumnFiltersAndLoad(this.area(), nextColumnFilters);
|
|
2818
|
+
return;
|
|
2819
|
+
}
|
|
2820
|
+
this.facade.applyTableLazyLoadAndLoad(this.area(), event);
|
|
2821
|
+
}
|
|
2822
|
+
onGeneralTaskCreateClick() {
|
|
2823
|
+
const modalOptions = this.generalTaskModal();
|
|
2824
|
+
const modalData = {
|
|
2825
|
+
moduleKey: 'GeneralTask',
|
|
2826
|
+
...(modalOptions?.data ?? {}),
|
|
2827
|
+
};
|
|
2828
|
+
const modalHeader = modalOptions?.header ??
|
|
2829
|
+
this.transloco.translate('workCenter.page.createGeneralTask');
|
|
2830
|
+
const modalStyleClass = modalOptions?.styleClass ?? this.defaultGeneralTaskModalStyleClass;
|
|
2831
|
+
const operationKey = modalOptions?.operationKey ?? 'Create';
|
|
2832
|
+
const closeOnPendingApproval = modalOptions?.closeOnPendingApproval ?? true;
|
|
2833
|
+
const lookups = modalOptions?.lookups ?? this.lookups();
|
|
2834
|
+
const ref = this.modal.openModal(WorkCenterClientFormModal, 'dialog', {
|
|
2835
|
+
header: modalHeader,
|
|
2836
|
+
styleClass: modalStyleClass,
|
|
2837
|
+
position: 'end',
|
|
2838
|
+
dismissableMask: true,
|
|
2839
|
+
inputValues: {
|
|
2840
|
+
data: modalData,
|
|
2841
|
+
operationKey,
|
|
2842
|
+
closeOnPendingApproval,
|
|
2843
|
+
lookups,
|
|
2844
|
+
},
|
|
2845
|
+
});
|
|
2846
|
+
ref.onClose.pipe(take(1)).subscribe((result) => {
|
|
2847
|
+
if (result) {
|
|
2848
|
+
this.facade.loadRuntime(this.area(), 'refresh');
|
|
2849
|
+
}
|
|
2850
|
+
});
|
|
2851
|
+
}
|
|
2852
|
+
onRowClick(row) {
|
|
2853
|
+
const contextKey = this.resolveRowContextKey(row);
|
|
2854
|
+
console.log('[work-center-debug] page row click', {
|
|
2855
|
+
contextKey,
|
|
2856
|
+
row,
|
|
2857
|
+
openItemsInModal: this.openItemsInModal(),
|
|
2858
|
+
hasModalComponent: !!this.itemModal()?.component,
|
|
2859
|
+
});
|
|
2860
|
+
if (!contextKey) {
|
|
2861
|
+
return;
|
|
2862
|
+
}
|
|
2863
|
+
this.itemClicked.emit(contextKey);
|
|
2864
|
+
if (this.openItemDrawer()) {
|
|
2865
|
+
this.selectedItemContextKey.set(contextKey);
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2868
|
+
if (!this.openItemsInModal()) {
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
const modalOptions = this.itemModal();
|
|
2872
|
+
if (!modalOptions?.component) {
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2875
|
+
const ref = this.modal.openModal(modalOptions.component, 'drawer', {
|
|
2876
|
+
header: modalOptions?.header ??
|
|
2877
|
+
this.transloco.translate('workCenter.page.itemDetails'),
|
|
2878
|
+
styleClass: modalOptions?.styleClass ?? this.defaultModalStyleClass,
|
|
2879
|
+
position: modalOptions?.position ?? 'end',
|
|
2880
|
+
dismissible: true,
|
|
2881
|
+
modal: true,
|
|
2882
|
+
...(modalOptions?.appendTo ? { appendTo: modalOptions.appendTo } : {}),
|
|
2883
|
+
inputValues: { contextKey },
|
|
2884
|
+
});
|
|
2885
|
+
ref.onClose.pipe(take(1)).subscribe(() => {
|
|
2886
|
+
this.facade.loadRuntime(this.area(), 'refresh');
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
rowsClickable = computed(() => this.openItemDrawer() || this.openItemsInModal(), ...(ngDevMode ? [{ debugName: "rowsClickable" }] : /* istanbul ignore next */ []));
|
|
2890
|
+
getOpLabel(key) {
|
|
2891
|
+
return (this.transloco.translate('workCenter.operator.' + key) ||
|
|
2892
|
+
OPERATOR_LABELS[key] ||
|
|
2893
|
+
toLabel(key));
|
|
2894
|
+
}
|
|
2895
|
+
resolveRowContextKey(row) {
|
|
2896
|
+
const value = row['contextKey'];
|
|
2897
|
+
if (typeof value !== 'string') {
|
|
2898
|
+
return null;
|
|
2899
|
+
}
|
|
2900
|
+
const normalized = value.trim();
|
|
2901
|
+
return normalized.length ? normalized : null;
|
|
2902
|
+
}
|
|
2903
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterPage, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2904
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: WorkCenterPage, isStandalone: true, selector: "mt-work-center-page", inputs: { area: { classPropertyName: "area", publicName: "area", isSignal: true, isRequired: false, transformFunction: null }, pageTitle: { classPropertyName: "pageTitle", publicName: "pageTitle", isSignal: true, isRequired: false, transformFunction: null }, menuIcon: { classPropertyName: "menuIcon", publicName: "menuIcon", isSignal: true, isRequired: false, transformFunction: null }, lookups: { classPropertyName: "lookups", publicName: "lookups", isSignal: true, isRequired: false, transformFunction: null }, showSidebar: { classPropertyName: "showSidebar", publicName: "showSidebar", isSignal: true, isRequired: false, transformFunction: null }, bootstrapInputs: { classPropertyName: "bootstrapInputs", publicName: "bootstrapInputs", isSignal: true, isRequired: false, transformFunction: null }, openItemDrawer: { classPropertyName: "openItemDrawer", publicName: "openItemDrawer", isSignal: true, isRequired: false, transformFunction: null }, openItemsInModal: { classPropertyName: "openItemsInModal", publicName: "openItemsInModal", isSignal: true, isRequired: false, transformFunction: null }, itemModal: { classPropertyName: "itemModal", publicName: "itemModal", isSignal: true, isRequired: false, transformFunction: null }, generalTaskModal: { classPropertyName: "generalTaskModal", publicName: "generalTaskModal", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { runtimeFiltersChanged: "runtimeFiltersChanged", itemClicked: "itemClicked", cardSelected: "cardSelected" }, ngImport: i0, template: "<ng-template #headerActions>\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\n <mt-property-filter-builder\n [schema]=\"propertyFilterSchema()\"\n [filters]=\"headerFilters()\"\n (applied)=\"onRuntimeFiltersApplied($event)\"\n (cleared)=\"onRuntimeFiltersCleared()\"\n />\n\n @if (showGeneralTaskCreateButton()) {\n <mt-button\n [label]=\"generalTaskButtonLabel()\"\n [icon]=\"generalTaskButtonIcon()\"\n size=\"small\"\n (onClick)=\"onGeneralTaskCreateClick()\"\n />\n }\n </div>\n</ng-template>\n\n<ng-template #pageContent>\n <div class=\"flex flex-col gap-8\">\n @if (loading()) {\n <div\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\n >\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\n <p-skeleton height=\"6.5rem\" class=\"rounded-lg\" />\n }\n </div>\n } @else if (kpis().length) {\n <div class=\"gap-3 flex flex-wrap\">\n @for (kpi of kpis(); track $index) {\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\n }\n </div>\n }\n\n <mt-table\n noCard\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n tableLayout=\"auto\"\n [clickableRows]=\"rowsClickable()\"\n [loading]=\"loading()\"\n [showFilters]=\"true\"\n filterMode=\"column\"\n [cellClickFilter]=\"true\"\n [generalSearch]=\"true\"\n [exportable]=\"true\"\n [printable]=\"true\"\n [groupable]=\"true\"\n [freezeActions]=\"true\"\n [lazy]=\"true\"\n [lazyLocalSearch]=\"true\"\n [lazyTotalRecords]=\"totalCount()\"\n [pageSize]=\"context().pageSize\"\n [currentPage]=\"context().page - 1\"\n [first]=\"(context().page - 1) * context().pageSize\"\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\n [groupCountMap]=\"statusGroupCountMap()\"\n storageKey=\"work-center-page-table\"\n [filters]=\"tableFilters()\"\n (filtersChange)=\"tableFilters.set($event)\"\n (lazyLoad)=\"onTableLazyLoad($event)\"\n (rowClick)=\"onRowClick($event)\"\n />\n </div>\n</ng-template>\n\n@if (showSidebar()) {\n <mt-client-page\n [menuIcon]=\"menuIcon()\"\n [menuTitle]=\"resolvedPageTitle()\"\n [menuItems]=\"menuItems()\"\n [menuItemsLoading]=\"loading() && !menuItems().length\"\n [activeItem]=\"context().selectedCardKey ?? undefined\"\n storageKey=\"work-center-client-page\"\n (menuItemClick)=\"onMenuItemClick($event)\"\n >\n <ng-template #headerClientPageEnd>\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\n </ng-template>\n\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\n </mt-client-page>\n} @else {\n <div class=\"flex h-full min-h-0 flex-col bg-surface-0\">\n <div\n class=\"flex shrink-0 items-center justify-end border-b border-surface px-7 py-4\"\n >\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\n </div>\n <div class=\"min-h-0 flex-1 overflow-y-auto px-7 py-5\">\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\n </div>\n </div>\n}\n\n@if (selectedItemContextKey(); as contextKey) {\n <mt-work-center-item-modal-route\n [contextKey]=\"contextKey\"\n [manageRouteOutlet]=\"false\"\n [showPreviewLevelAction]=\"false\"\n (closed)=\"selectedItemContextKey.set(null)\"\n />\n}\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: ClientPage, selector: "mt-client-page", inputs: ["menuIcon", "menuTitle", "menuItems", "menuItemsLoading", "activeItem", "collapsed", "resizable", "storageKey", "storageMode", "minSidebarWidth", "maxSidebarWidth", "defaultSidebarWidth"], outputs: ["collapsedChange", "menuItemClick", "loadChildren"] }, { kind: "component", type: PropertyFilterBuilder, selector: "mt-property-filter-builder", inputs: ["schema", "filters", "title", "buttonLabel", "disabled"], outputs: ["filtersChange", "applied", "cleared"] }, { kind: "component", type: StatisticCard, selector: "mt-statistic-card", inputs: ["data", "cardClass"] }, { kind: "component", type: Table, selector: "mt-table", inputs: ["filters", "data", "columns", "rowActions", "size", "showGridlines", "stripedRows", "selectableRows", "clickableRows", "generalSearch", "lazyLocalSearch", "showFilters", "filterMode", "loading", "updating", "lazy", "lazyLocalSort", "lazyTotalRecords", "reorderableColumns", "reorderableRows", "dataKey", "storageKey", "storageMode", "persistStateExclude", "exportable", "printable", "groupable", "groupCountMap", "cellClickFilter", "freezeActions", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "printTitle", "exportFilename", "actionShape", "rowActionsLoadingFn", "tableLayout", "noCard", "tabs", "tabsOptionLabel", "tabsOptionValue", "activeTab", "actions", "paginatorPosition", "alwaysShowPaginator", "rowsPerPageOptions", "pageSize", "currentPage", "first", "filterTerm", "groupBy"], outputs: ["selectionChange", "cellChange", "lazyLoad", "columnReorder", "rowReorder", "rowClick", "rowActionsRequested", "filtersChange", "activeTabChange", "onTabChange", "pageSizeChange", "currentPageChange", "firstChange", "filterTermChange", "groupByChange"] }, { kind: "component", type: WorkCenterItemModalRoute, selector: "mt-work-center-item-modal-route", inputs: ["contextKey", "manageRouteOutlet", "showPreviewLevelAction"], outputs: ["previewLevel", "closed"] }, { kind: "ngmodule", type: SkeletonModule }, { kind: "component", type: i1.Skeleton, selector: "p-skeleton", inputs: ["styleClass", "shape", "animation", "borderRadius", "size", "width", "height"] }] });
|
|
2905
|
+
}
|
|
2906
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterPage, decorators: [{
|
|
2907
|
+
type: Component,
|
|
2908
|
+
args: [{ selector: 'mt-work-center-page', standalone: true, imports: [
|
|
2909
|
+
CommonModule,
|
|
2910
|
+
Button,
|
|
2911
|
+
ClientPage,
|
|
2912
|
+
PropertyFilterBuilder,
|
|
2913
|
+
StatisticCard,
|
|
2914
|
+
Table,
|
|
2915
|
+
WorkCenterItemModalRoute,
|
|
2916
|
+
SkeletonModule,
|
|
2917
|
+
], template: "<ng-template #headerActions>\n <div class=\"flex flex-wrap items-center justify-end gap-2\">\n <mt-property-filter-builder\n [schema]=\"propertyFilterSchema()\"\n [filters]=\"headerFilters()\"\n (applied)=\"onRuntimeFiltersApplied($event)\"\n (cleared)=\"onRuntimeFiltersCleared()\"\n />\n\n @if (showGeneralTaskCreateButton()) {\n <mt-button\n [label]=\"generalTaskButtonLabel()\"\n [icon]=\"generalTaskButtonIcon()\"\n size=\"small\"\n (onClick)=\"onGeneralTaskCreateClick()\"\n />\n }\n </div>\n</ng-template>\n\n<ng-template #pageContent>\n <div class=\"flex flex-col gap-8\">\n @if (loading()) {\n <div\n class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 xl:grid-cols-5 gap-3\"\n >\n @for (_ of [1, 2, 3, 4, 5]; track $index) {\n <p-skeleton height=\"6.5rem\" class=\"rounded-lg\" />\n }\n </div>\n } @else if (kpis().length) {\n <div class=\"gap-3 flex flex-wrap\">\n @for (kpi of kpis(); track $index) {\n <mt-statistic-card [data]=\"kpi\" class=\"min-w-[200px]\" />\n }\n </div>\n }\n\n <mt-table\n noCard\n [data]=\"rows()\"\n [columns]=\"tableColumns()\"\n tableLayout=\"auto\"\n [clickableRows]=\"rowsClickable()\"\n [loading]=\"loading()\"\n [showFilters]=\"true\"\n filterMode=\"column\"\n [cellClickFilter]=\"true\"\n [generalSearch]=\"true\"\n [exportable]=\"true\"\n [printable]=\"true\"\n [groupable]=\"true\"\n [freezeActions]=\"true\"\n [lazy]=\"true\"\n [lazyLocalSearch]=\"true\"\n [lazyTotalRecords]=\"totalCount()\"\n [pageSize]=\"context().pageSize\"\n [currentPage]=\"context().page - 1\"\n [first]=\"(context().page - 1) * context().pageSize\"\n [rowsPerPageOptions]=\"[10, 20, 50, 100]\"\n [groupCountMap]=\"statusGroupCountMap()\"\n storageKey=\"work-center-page-table\"\n [filters]=\"tableFilters()\"\n (filtersChange)=\"tableFilters.set($event)\"\n (lazyLoad)=\"onTableLazyLoad($event)\"\n (rowClick)=\"onRowClick($event)\"\n />\n </div>\n</ng-template>\n\n@if (showSidebar()) {\n <mt-client-page\n [menuIcon]=\"menuIcon()\"\n [menuTitle]=\"resolvedPageTitle()\"\n [menuItems]=\"menuItems()\"\n [menuItemsLoading]=\"loading() && !menuItems().length\"\n [activeItem]=\"context().selectedCardKey ?? undefined\"\n storageKey=\"work-center-client-page\"\n (menuItemClick)=\"onMenuItemClick($event)\"\n >\n <ng-template #headerClientPageEnd>\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\n </ng-template>\n\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\n </mt-client-page>\n} @else {\n <div class=\"flex h-full min-h-0 flex-col bg-surface-0\">\n <div\n class=\"flex shrink-0 items-center justify-end border-b border-surface px-7 py-4\"\n >\n <ng-container [ngTemplateOutlet]=\"headerActions\" />\n </div>\n <div class=\"min-h-0 flex-1 overflow-y-auto px-7 py-5\">\n <ng-container [ngTemplateOutlet]=\"pageContent\" />\n </div>\n </div>\n}\n\n@if (selectedItemContextKey(); as contextKey) {\n <mt-work-center-item-modal-route\n [contextKey]=\"contextKey\"\n [manageRouteOutlet]=\"false\"\n [showPreviewLevelAction]=\"false\"\n (closed)=\"selectedItemContextKey.set(null)\"\n />\n}\n" }]
|
|
2918
|
+
}], ctorParameters: () => [], propDecorators: { area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], pageTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "pageTitle", required: false }] }], menuIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuIcon", required: false }] }], lookups: [{ type: i0.Input, args: [{ isSignal: true, alias: "lookups", required: false }] }], showSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSidebar", required: false }] }], bootstrapInputs: [{ type: i0.Input, args: [{ isSignal: true, alias: "bootstrapInputs", required: false }] }], openItemDrawer: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemDrawer", required: false }] }], openItemsInModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "openItemsInModal", required: false }] }], itemModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "itemModal", required: false }] }], generalTaskModal: [{ type: i0.Input, args: [{ isSignal: true, alias: "generalTaskModal", required: false }] }], runtimeFiltersChanged: [{ type: i0.Output, args: ["runtimeFiltersChanged"] }], itemClicked: [{ type: i0.Output, args: ["itemClicked"] }], cardSelected: [{ type: i0.Output, args: ["cardSelected"] }] } });
|
|
2919
|
+
|
|
2885
2920
|
const APP_STATES = [WorkCenterState];
|
|
2886
2921
|
|
|
2887
2922
|
/**
|