@masterteam/task-schedule 0.0.15 → 0.0.17
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.
|
@@ -3,7 +3,8 @@ import * as i0 from '@angular/core';
|
|
|
3
3
|
import { inject, Injectable, viewChild, input, signal, computed, effect, Component, linkedSignal, Injector, output, ViewChild } from '@angular/core';
|
|
4
4
|
import * as i1$1 from '@syncfusion/ej2-angular-gantt';
|
|
5
5
|
import { GanttModule, DayMarkersService, EditService, ExcelExportService, FilterService, CriticalPathService, PdfExportService, RowDDService, SelectionService, SortService, ToolbarService, ContextMenuService, ResizeService } from '@syncfusion/ej2-angular-gantt';
|
|
6
|
-
import { switchMap, of, map, catchError, throwError, finalize, Subject, Subscription } from 'rxjs';
|
|
6
|
+
import { switchMap, of, map, timeout, catchError, throwError, finalize, Subject, Subscription } from 'rxjs';
|
|
7
|
+
import { MT_DATE_FORMATS, toAngularDateFormat, MTDateFormatPipe } from '@masterteam/components';
|
|
7
8
|
import { ModalService } from '@masterteam/components/modal';
|
|
8
9
|
import { HttpClient } from '@angular/common/http';
|
|
9
10
|
import { L10n, setCulture } from '@syncfusion/ej2-base';
|
|
@@ -20,7 +21,6 @@ import { CheckboxField } from '@masterteam/components/checkbox-field';
|
|
|
20
21
|
import { DateField } from '@masterteam/components/date-field';
|
|
21
22
|
import { EntityPreview } from '@masterteam/components/entities';
|
|
22
23
|
import { NumberField } from '@masterteam/components/number-field';
|
|
23
|
-
import { Table } from '@masterteam/components/table';
|
|
24
24
|
import { TextField } from '@masterteam/components/text-field';
|
|
25
25
|
|
|
26
26
|
function normalizeTaskScheduleModelType(modelType) {
|
|
@@ -109,6 +109,7 @@ const NATIVE_PROPERTY_KEYS = new Set([
|
|
|
109
109
|
'predecessor',
|
|
110
110
|
'order',
|
|
111
111
|
'externalId',
|
|
112
|
+
'externalParentId',
|
|
112
113
|
'parentId',
|
|
113
114
|
'phaseGate',
|
|
114
115
|
'phaseGateId',
|
|
@@ -117,6 +118,21 @@ const NATIVE_PROPERTY_KEYS = new Set([
|
|
|
117
118
|
'isSummary',
|
|
118
119
|
]);
|
|
119
120
|
const NATIVE_PROPERTY_LOOKUP_KEYS = new Set(Array.from(NATIVE_PROPERTY_KEYS).map((key) => normalizeLookupKey(key)));
|
|
121
|
+
const NATIVE_PROPERTY_ALIAS_TARGETS = {
|
|
122
|
+
startdate: 'plannedStart',
|
|
123
|
+
plannedstartdate: 'plannedStart',
|
|
124
|
+
enddate: 'plannedFinish',
|
|
125
|
+
finishdate: 'plannedFinish',
|
|
126
|
+
plannedfinishdate: 'plannedFinish',
|
|
127
|
+
actualstartdate: 'actualStart',
|
|
128
|
+
actualfinishdate: 'actualFinish',
|
|
129
|
+
baselinestartdate: 'baselineStart',
|
|
130
|
+
baselinefinishdate: 'baselineFinish',
|
|
131
|
+
baselineenddate: 'baselineFinish',
|
|
132
|
+
taskname: 'name',
|
|
133
|
+
};
|
|
134
|
+
const DEFAULT_MPP_REQUEST_TIMEOUT_MS$1 = 300_000;
|
|
135
|
+
const DEFAULT_MPP_PREVIEW_MAX_ROWS = 400;
|
|
120
136
|
class TaskScheduleFetchService {
|
|
121
137
|
http = inject(HttpClient);
|
|
122
138
|
load(modelType, context) {
|
|
@@ -140,12 +156,21 @@ class TaskScheduleFetchService {
|
|
|
140
156
|
'levels/{levelId}/{levelDataId}/schedule/mpp', { levelId, levelDataId });
|
|
141
157
|
const formData = new FormData();
|
|
142
158
|
formData.append('file', file, file.name);
|
|
143
|
-
return this.readData(this.http
|
|
159
|
+
return this.readData(this.http
|
|
160
|
+
.post(endpoint, formData)
|
|
161
|
+
.pipe(timeout(this.resolveMppRequestTimeoutMs(context)))).pipe(map((payload) => ({
|
|
144
162
|
fileName: this.toNullableString(this.readObjectValue(payload, ['fileName', 'name'])) ?? file.name,
|
|
145
|
-
tasks: this.mapLooseTasks(this.extractTaskRows(payload), [], context.langCode === 'ar' ? 'ar' : 'en'),
|
|
146
|
-
raw: payload,
|
|
163
|
+
tasks: this.mapLooseTasks(this.extractTaskRows(payload), [], context.langCode === 'ar' ? 'ar' : 'en', new Map(), this.resolveMppPreviewMaxRows(context)),
|
|
164
|
+
raw: context.mppKeepRawPayload ? payload : undefined,
|
|
147
165
|
})));
|
|
148
166
|
}
|
|
167
|
+
exportTasks(context) {
|
|
168
|
+
const endpoint = this.levelEndpoint(context, this.readEndpoint(context, 'exportTasks') ??
|
|
169
|
+
'levels/{levelId}/{levelDataId}/schedule/mpp', 'Export tasks requires levelId and levelDataId.');
|
|
170
|
+
return this.http
|
|
171
|
+
.get(endpoint, { responseType: 'blob' })
|
|
172
|
+
.pipe(timeout(this.resolveMppRequestTimeoutMs(context)));
|
|
173
|
+
}
|
|
149
174
|
loadBaselineSnapshot(context, version = 'latest') {
|
|
150
175
|
const endpoint = this.levelEndpoint(context, version === 'latest'
|
|
151
176
|
? 'levels/{levelId}/{levelDataId}/schedule/baselines/latest'
|
|
@@ -167,11 +192,12 @@ class TaskScheduleFetchService {
|
|
|
167
192
|
modelType === 'custom'
|
|
168
193
|
? this.mapCustomProperties(payload.catalog?.properties ?? [])
|
|
169
194
|
: [];
|
|
195
|
+
const propertyAliases = this.mapPropertyAliases(payload.catalog?.properties ?? []);
|
|
170
196
|
const tasks = modelType === 'resources'
|
|
171
|
-
? this.mapGroupedTasks(payload.data?.groups ?? [], customProperties, langCode)
|
|
197
|
+
? this.mapGroupedTasks(payload.data?.groups ?? [], customProperties, propertyAliases, langCode)
|
|
172
198
|
: modelType === 'unscheduled'
|
|
173
|
-
? this.mapLooseTasks(payload.data?.items ?? [], customProperties, langCode)
|
|
174
|
-
: this.mapQueryTasks(payload.data?.records ?? [], payload.schemas ?? [], customProperties, langCode);
|
|
199
|
+
? this.mapLooseTasks(payload.data?.items ?? [], customProperties, langCode, propertyAliases)
|
|
200
|
+
: this.mapQueryTasks(payload.data?.records ?? [], payload.schemas ?? [], customProperties, propertyAliases, langCode);
|
|
175
201
|
return this.resolveResources(context, modelType, tasks).pipe(map((resources) => ({
|
|
176
202
|
tasks,
|
|
177
203
|
resources,
|
|
@@ -229,20 +255,20 @@ class TaskScheduleFetchService {
|
|
|
229
255
|
'levels/{levelId}/{levelDataId}/schedule/read', fallbackMessage);
|
|
230
256
|
return this.readData(this.http.post(endpoint, body));
|
|
231
257
|
}
|
|
232
|
-
mapQueryTasks(records, schemas, customProperties, langCode) {
|
|
258
|
+
mapQueryTasks(records, schemas, customProperties, propertyAliases, langCode) {
|
|
233
259
|
const schemaMap = new Map((schemas ?? [])
|
|
234
260
|
.filter((schema) => schema.id !== null && schema.id !== undefined)
|
|
235
261
|
.map((schema) => [String(schema.id), schema]));
|
|
236
262
|
return sortTasksByOrder((records ?? [])
|
|
237
|
-
.map((record, index) => this.mapTaskSource(record, index + 1, customProperties, langCode, schemaMap.get(String(record.schemaId ?? '')) ?? null, record.children ?? []))
|
|
263
|
+
.map((record, index) => this.mapTaskSource(record, index + 1, customProperties, langCode, propertyAliases, schemaMap.get(String(record.schemaId ?? '')) ?? null, record.children ?? []))
|
|
238
264
|
.filter((task) => task !== null));
|
|
239
265
|
}
|
|
240
|
-
mapGroupedTasks(groups, customProperties, langCode) {
|
|
266
|
+
mapGroupedTasks(groups, customProperties, propertyAliases, langCode) {
|
|
241
267
|
const byId = new Map();
|
|
242
268
|
for (const group of groups ?? []) {
|
|
243
269
|
const items = Array.isArray(group?.items) ? group.items : [];
|
|
244
270
|
for (let index = 0; index < items.length; index += 1) {
|
|
245
|
-
const task = this.mapTaskSource(items[index], index + 1, customProperties, langCode, null, []);
|
|
271
|
+
const task = this.mapTaskSource(items[index], index + 1, customProperties, langCode, propertyAliases, null, []);
|
|
246
272
|
if (!task) {
|
|
247
273
|
continue;
|
|
248
274
|
}
|
|
@@ -258,26 +284,46 @@ class TaskScheduleFetchService {
|
|
|
258
284
|
}
|
|
259
285
|
return sortTasksByOrder(Array.from(byId.values()));
|
|
260
286
|
}
|
|
261
|
-
mapLooseTasks(rows, customProperties, langCode) {
|
|
262
|
-
|
|
263
|
-
.
|
|
264
|
-
|
|
265
|
-
|
|
287
|
+
mapLooseTasks(rows, customProperties, langCode, propertyAliases = new Map(), maxTasks = Number.POSITIVE_INFINITY) {
|
|
288
|
+
const budget = Number.isFinite(maxTasks)
|
|
289
|
+
? { remaining: Math.max(0, Math.floor(maxTasks)) }
|
|
290
|
+
: undefined;
|
|
291
|
+
const tasks = [];
|
|
292
|
+
for (let index = 0; index < (rows ?? []).length; index += 1) {
|
|
293
|
+
if (budget && budget.remaining <= 0) {
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
const row = rows[index];
|
|
297
|
+
if (!this.isObject(row)) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
const task = this.mapTaskSource(row, index + 1, customProperties, langCode, propertyAliases, null, undefined, budget);
|
|
301
|
+
if (task) {
|
|
302
|
+
tasks.push(task);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return sortTasksByOrder(tasks);
|
|
266
306
|
}
|
|
267
|
-
mapTaskSource(source, fallbackOrder, customProperties, langCode, schema = null, explicitChildren) {
|
|
307
|
+
mapTaskSource(source, fallbackOrder, customProperties, langCode, propertyAliases = new Map(), schema = null, explicitChildren, budget) {
|
|
308
|
+
if (budget && budget.remaining <= 0) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
268
311
|
const id = this.toTaskId(source['id'] ?? source['taskId'] ?? source['Id']);
|
|
269
312
|
if (id === null) {
|
|
270
313
|
return null;
|
|
271
314
|
}
|
|
272
|
-
|
|
315
|
+
if (budget) {
|
|
316
|
+
budget.remaining -= 1;
|
|
317
|
+
}
|
|
318
|
+
const rawType = this.toNullableString(this.readNativeValue(source, 'type', propertyAliases)) ??
|
|
273
319
|
this.toNullableString(schema?.key) ??
|
|
274
320
|
'Task';
|
|
275
321
|
const type = this.normalizeTaskType(rawType);
|
|
276
322
|
const title = this.toNullableString(source['title'] ??
|
|
277
323
|
source['name'] ??
|
|
278
324
|
source['Name'] ??
|
|
279
|
-
this.
|
|
280
|
-
const resources = this.normalizeResources(this.
|
|
325
|
+
this.readNativeValue(source, 'name', propertyAliases)) ?? `Task ${String(id)}`;
|
|
326
|
+
const resources = this.normalizeResources(this.readNativeValue(source, 'resources', propertyAliases), this.readNativeValue(source, 'assignedTo', propertyAliases));
|
|
281
327
|
const customValues = this.mapCustomValues(source, customProperties);
|
|
282
328
|
const childRows = explicitChildren ??
|
|
283
329
|
(Array.isArray(source['children'])
|
|
@@ -285,6 +331,7 @@ class TaskScheduleFetchService {
|
|
|
285
331
|
: Array.isArray(source['subtasks'])
|
|
286
332
|
? source['subtasks']
|
|
287
333
|
: []);
|
|
334
|
+
const subtasks = this.mapTaskChildren(childRows, customProperties, langCode, propertyAliases, budget);
|
|
288
335
|
const task = {
|
|
289
336
|
...source,
|
|
290
337
|
id,
|
|
@@ -294,52 +341,56 @@ class TaskScheduleFetchService {
|
|
|
294
341
|
title,
|
|
295
342
|
name: title,
|
|
296
343
|
guid: this.toNullableString(this.readNestedValue(source, 'externalId') ??
|
|
344
|
+
this.readNativeValue(source, 'externalId', propertyAliases) ??
|
|
297
345
|
this.readNestedValue(source, 'guid') ??
|
|
298
346
|
source['externalId'] ??
|
|
299
347
|
source['guid'] ??
|
|
300
348
|
source['Guid']) ?? `task-${String(id)}`,
|
|
301
349
|
parentGuid: this.toNullableString(this.readNestedValue(source, 'parentId') ??
|
|
302
350
|
this.readNestedValue(source, 'externalParentId') ??
|
|
351
|
+
this.readNativeValue(source, 'parentId', propertyAliases) ??
|
|
352
|
+
this.readNativeValue(source, 'externalParentId', propertyAliases) ??
|
|
303
353
|
source['parentGuid'] ??
|
|
304
354
|
source['ParentGuid'] ??
|
|
305
355
|
source['externalParentId']),
|
|
306
|
-
parentId: this.toTaskId(source['parentId'] ??
|
|
307
|
-
|
|
308
|
-
this.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
this.
|
|
313
|
-
this.
|
|
314
|
-
baselineStartDate: this.toDate(this.
|
|
315
|
-
baselineEndDate: this.toDate(this.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
356
|
+
parentId: this.toTaskId(source['parentId'] ??
|
|
357
|
+
source['ParentId'] ??
|
|
358
|
+
this.readNativeValue(source, 'parentId', propertyAliases)),
|
|
359
|
+
startDate: this.toDate(this.readNativeRawValue(source, 'plannedStart', propertyAliases) ??
|
|
360
|
+
this.readNativeRawValue(source, 'startDate', propertyAliases)),
|
|
361
|
+
finishDate: this.toDate(this.readNativeRawValue(source, 'plannedFinish', propertyAliases) ??
|
|
362
|
+
this.readNativeRawValue(source, 'finishDate', propertyAliases) ??
|
|
363
|
+
this.readNativeRawValue(source, 'endDate', propertyAliases)),
|
|
364
|
+
baselineStartDate: this.toDate(this.readNativeRawValue(source, 'baselineStart', propertyAliases)),
|
|
365
|
+
baselineEndDate: this.toDate(this.readNativeRawValue(source, 'baselineFinish', propertyAliases)),
|
|
366
|
+
actualStart: this.toDate(this.readNativeRawValue(source, 'actualStart', propertyAliases)),
|
|
367
|
+
actualFinish: this.toDate(this.readNativeRawValue(source, 'actualFinish', propertyAliases)),
|
|
368
|
+
baselineStart: this.toDate(this.readNativeRawValue(source, 'baselineStart', propertyAliases)),
|
|
369
|
+
baselineFinish: this.toDate(this.readNativeRawValue(source, 'baselineFinish', propertyAliases)),
|
|
370
|
+
actualStartDate: this.toDate(this.readNativeRawValue(source, 'actualStart', propertyAliases)),
|
|
371
|
+
actualFinishDate: this.toDate(this.readNativeRawValue(source, 'actualFinish', propertyAliases)),
|
|
372
|
+
predecessor: this.toNullableString(this.readNativeValue(source, 'predecessor', propertyAliases)),
|
|
373
|
+
duration: this.normalizeDuration(this.readNativeValue(source, 'duration', propertyAliases), type),
|
|
374
|
+
progress: this.normalizeProgress(this.readNativeValue(source, 'progress', propertyAliases)),
|
|
375
|
+
details: this.toNullableString(this.readNativeValue(source, 'details', propertyAliases) ??
|
|
376
|
+
this.readNativeValue(source, 'description', propertyAliases)),
|
|
377
|
+
status: this.readNamedString(this.readNativeValue(source, 'status', propertyAliases)),
|
|
324
378
|
type,
|
|
325
|
-
typeLabel: this.toNullableString(this.
|
|
326
|
-
this.
|
|
379
|
+
typeLabel: this.toNullableString(this.readNativeValue(source, 'typeLabel', propertyAliases) ??
|
|
380
|
+
this.readNativeValue(source, 'typeLable', propertyAliases) ??
|
|
327
381
|
schema?.name) ?? this.localizeTaskType(type, langCode),
|
|
328
|
-
typeLable: this.toNullableString(this.
|
|
329
|
-
this.
|
|
382
|
+
typeLable: this.toNullableString(this.readNativeValue(source, 'typeLable', propertyAliases) ??
|
|
383
|
+
this.readNativeValue(source, 'typeLabel', propertyAliases) ??
|
|
330
384
|
schema?.name) ?? this.localizeTaskType(type, langCode),
|
|
331
|
-
assignedTo: this.resolveAssignedTo(resources, this.
|
|
385
|
+
assignedTo: this.resolveAssignedTo(resources, this.readNativeValue(source, 'assignedTo', propertyAliases)),
|
|
332
386
|
resources,
|
|
333
|
-
phaseGate: this.toNullableString(this.
|
|
334
|
-
phaseGateId: this.toTaskId(this.
|
|
335
|
-
criticalPath: Boolean(this.
|
|
387
|
+
phaseGate: this.toNullableString(this.readNativeValue(source, 'phaseGate', propertyAliases)),
|
|
388
|
+
phaseGateId: this.toTaskId(this.readNativeValue(source, 'phaseGateId', propertyAliases)),
|
|
389
|
+
criticalPath: Boolean(this.readNativeValue(source, 'criticalPath', propertyAliases)),
|
|
336
390
|
isMilestone: type === 'Milestone',
|
|
337
|
-
order: this.toNullableNumber(this.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
.filter((row) => this.isObject(row))
|
|
341
|
-
.map((row, index) => this.mapTaskSource(row, index + 1, customProperties, langCode))
|
|
342
|
-
.filter((row) => row !== null),
|
|
391
|
+
order: this.toNullableNumber(this.readNativeValue(source, 'order', propertyAliases)) ?? fallbackOrder,
|
|
392
|
+
subtasks,
|
|
393
|
+
children: subtasks,
|
|
343
394
|
props: customValues.props,
|
|
344
395
|
};
|
|
345
396
|
for (const [key, value] of Object.entries(customValues.values)) {
|
|
@@ -347,6 +398,23 @@ class TaskScheduleFetchService {
|
|
|
347
398
|
}
|
|
348
399
|
return task;
|
|
349
400
|
}
|
|
401
|
+
mapTaskChildren(rows, customProperties, langCode, propertyAliases, budget) {
|
|
402
|
+
const tasks = [];
|
|
403
|
+
for (let index = 0; index < (rows ?? []).length; index += 1) {
|
|
404
|
+
if (budget && budget.remaining <= 0) {
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
const row = rows[index];
|
|
408
|
+
if (!this.isObject(row)) {
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
const task = this.mapTaskSource(row, index + 1, customProperties, langCode, propertyAliases, null, undefined, budget);
|
|
412
|
+
if (task) {
|
|
413
|
+
tasks.push(task);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return sortTasksByOrder(tasks);
|
|
417
|
+
}
|
|
350
418
|
mapCustomProperties(properties) {
|
|
351
419
|
return [...(properties ?? [])]
|
|
352
420
|
.filter((property) => {
|
|
@@ -363,6 +431,7 @@ class TaskScheduleFetchService {
|
|
|
363
431
|
id: property.id,
|
|
364
432
|
key: property.normalizedKey ?? property.key,
|
|
365
433
|
normalizedKey: property.normalizedKey ?? property.key,
|
|
434
|
+
sourceKey: property.key,
|
|
366
435
|
name: property.label ?? property.key,
|
|
367
436
|
viewType: property.viewType ?? 'Text',
|
|
368
437
|
configuration: property.configuration,
|
|
@@ -370,17 +439,59 @@ class TaskScheduleFetchService {
|
|
|
370
439
|
isCalculated: !!property.isCalculated,
|
|
371
440
|
}));
|
|
372
441
|
}
|
|
442
|
+
mapPropertyAliases(properties) {
|
|
443
|
+
const aliases = new Map();
|
|
444
|
+
for (const property of properties ?? []) {
|
|
445
|
+
const canonicalKey = this.resolveNativePropertyKey(property.normalizedKey ?? property.key);
|
|
446
|
+
if (!canonicalKey) {
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
449
|
+
this.addPropertyAlias(aliases, canonicalKey, property.key);
|
|
450
|
+
this.addPropertyAlias(aliases, canonicalKey, property.normalizedKey);
|
|
451
|
+
}
|
|
452
|
+
return aliases;
|
|
453
|
+
}
|
|
454
|
+
resolveNativePropertyKey(value) {
|
|
455
|
+
const lookupKey = normalizeLookupKey(String(value ?? ''));
|
|
456
|
+
if (!lookupKey) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
const aliasTarget = NATIVE_PROPERTY_ALIAS_TARGETS[lookupKey];
|
|
460
|
+
if (aliasTarget) {
|
|
461
|
+
return aliasTarget;
|
|
462
|
+
}
|
|
463
|
+
for (const nativeKey of NATIVE_PROPERTY_KEYS) {
|
|
464
|
+
const nativeLookupKey = normalizeLookupKey(nativeKey);
|
|
465
|
+
if (lookupKey === nativeLookupKey ||
|
|
466
|
+
(nativeLookupKey.length >= 5 && lookupKey.endsWith(nativeLookupKey))) {
|
|
467
|
+
return nativeKey;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
addPropertyAlias(aliases, canonicalKey, alias) {
|
|
473
|
+
const resolvedAlias = String(alias ?? '').trim();
|
|
474
|
+
if (!resolvedAlias || resolvedAlias === canonicalKey) {
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
const currentAliases = aliases.get(canonicalKey) ?? [];
|
|
478
|
+
if (!currentAliases.includes(resolvedAlias)) {
|
|
479
|
+
aliases.set(canonicalKey, [...currentAliases, resolvedAlias]);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
373
482
|
mapCustomValues(source, customProperties) {
|
|
374
483
|
const values = {};
|
|
375
484
|
const props = [];
|
|
376
485
|
for (const property of customProperties) {
|
|
377
|
-
const raw = this.readSourceRawValue(source, property.key)
|
|
486
|
+
const raw = this.readSourceRawValue(source, property.key) ??
|
|
487
|
+
this.readSourceRawValue(source, property.sourceKey ?? '');
|
|
378
488
|
if (raw === undefined) {
|
|
379
489
|
continue;
|
|
380
490
|
}
|
|
381
491
|
const value = String(property.viewType ?? '').toLowerCase() === 'date'
|
|
382
492
|
? this.toDate(raw)
|
|
383
|
-
: this.readSourceValue(source, property.key)
|
|
493
|
+
: (this.readSourceValue(source, property.key) ??
|
|
494
|
+
this.readSourceValue(source, property.sourceKey ?? ''));
|
|
384
495
|
values[property.key] = value;
|
|
385
496
|
props.push({
|
|
386
497
|
id: 0,
|
|
@@ -617,6 +728,18 @@ class TaskScheduleFetchService {
|
|
|
617
728
|
}
|
|
618
729
|
return resolved;
|
|
619
730
|
}
|
|
731
|
+
resolveMppRequestTimeoutMs(context) {
|
|
732
|
+
const value = Number(context.mppRequestTimeoutMs);
|
|
733
|
+
return Number.isFinite(value) && value > 0
|
|
734
|
+
? value
|
|
735
|
+
: DEFAULT_MPP_REQUEST_TIMEOUT_MS$1;
|
|
736
|
+
}
|
|
737
|
+
resolveMppPreviewMaxRows(context) {
|
|
738
|
+
const value = Number(context.mppPreviewMaxRows);
|
|
739
|
+
return Number.isFinite(value) && value > 0
|
|
740
|
+
? Math.floor(value) + 1
|
|
741
|
+
: DEFAULT_MPP_PREVIEW_MAX_ROWS + 1;
|
|
742
|
+
}
|
|
620
743
|
readEndpoint(context, key) {
|
|
621
744
|
const value = context.endpoints?.[key];
|
|
622
745
|
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
@@ -698,6 +821,32 @@ class TaskScheduleFetchService {
|
|
|
698
821
|
}
|
|
699
822
|
return undefined;
|
|
700
823
|
}
|
|
824
|
+
readNativeValue(source, key, aliases) {
|
|
825
|
+
const direct = this.readSourceValue(source, key);
|
|
826
|
+
if (direct !== undefined) {
|
|
827
|
+
return direct;
|
|
828
|
+
}
|
|
829
|
+
for (const alias of aliases.get(key) ?? []) {
|
|
830
|
+
const value = this.readSourceValue(source, alias);
|
|
831
|
+
if (value !== undefined) {
|
|
832
|
+
return value;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return undefined;
|
|
836
|
+
}
|
|
837
|
+
readNativeRawValue(source, key, aliases) {
|
|
838
|
+
const direct = this.readSourceRawValue(source, key);
|
|
839
|
+
if (direct !== undefined) {
|
|
840
|
+
return direct;
|
|
841
|
+
}
|
|
842
|
+
for (const alias of aliases.get(key) ?? []) {
|
|
843
|
+
const value = this.readSourceRawValue(source, alias);
|
|
844
|
+
if (value !== undefined) {
|
|
845
|
+
return value;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return undefined;
|
|
849
|
+
}
|
|
701
850
|
readSourceValue(source, key) {
|
|
702
851
|
const direct = this.readObjectValueByKey(source, key);
|
|
703
852
|
if (direct !== undefined) {
|
|
@@ -953,22 +1102,53 @@ class TaskScheduleFetchService {
|
|
|
953
1102
|
if (value === null || value === undefined || value === '') {
|
|
954
1103
|
return null;
|
|
955
1104
|
}
|
|
956
|
-
if (value instanceof Date
|
|
957
|
-
return value;
|
|
1105
|
+
if (value instanceof Date) {
|
|
1106
|
+
return Number.isNaN(value.getTime()) ? null : this.toLocalDate(value);
|
|
1107
|
+
}
|
|
1108
|
+
if (typeof value === 'string') {
|
|
1109
|
+
const raw = value.trim();
|
|
1110
|
+
if (!raw) {
|
|
1111
|
+
return null;
|
|
1112
|
+
}
|
|
1113
|
+
const dateOnly = this.parseDateOnly(raw);
|
|
1114
|
+
if (dateOnly) {
|
|
1115
|
+
return dateOnly;
|
|
1116
|
+
}
|
|
1117
|
+
const date = new Date(raw);
|
|
1118
|
+
return Number.isNaN(date.getTime()) ? value : this.toLocalDate(date);
|
|
958
1119
|
}
|
|
959
1120
|
if (typeof value === 'number') {
|
|
960
1121
|
const date = new Date(value);
|
|
961
|
-
return Number.isNaN(date.getTime()) ? null : date;
|
|
1122
|
+
return Number.isNaN(date.getTime()) ? null : this.toLocalDate(date);
|
|
962
1123
|
}
|
|
963
1124
|
if (!this.isObject(value)) {
|
|
964
1125
|
return String(value);
|
|
965
1126
|
}
|
|
966
1127
|
const row = value;
|
|
967
|
-
|
|
968
|
-
row
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1128
|
+
for (const key of ['raw', 'actualValue', 'value', 'displayValue']) {
|
|
1129
|
+
if (!(key in row)) {
|
|
1130
|
+
continue;
|
|
1131
|
+
}
|
|
1132
|
+
const date = this.toDate(row[key]);
|
|
1133
|
+
if (date !== null) {
|
|
1134
|
+
return date;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
return null;
|
|
1138
|
+
}
|
|
1139
|
+
parseDateOnly(value) {
|
|
1140
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
1141
|
+
if (!match) {
|
|
1142
|
+
return null;
|
|
1143
|
+
}
|
|
1144
|
+
const year = Number(match[1]);
|
|
1145
|
+
const month = Number(match[2]);
|
|
1146
|
+
const day = Number(match[3]);
|
|
1147
|
+
const date = new Date(year, month - 1, day);
|
|
1148
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
1149
|
+
}
|
|
1150
|
+
toLocalDate(value) {
|
|
1151
|
+
return new Date(value.getFullYear(), value.getMonth(), value.getDate());
|
|
972
1152
|
}
|
|
973
1153
|
readLegacyHolidays() {
|
|
974
1154
|
if (typeof localStorage === 'undefined') {
|
|
@@ -1060,6 +1240,7 @@ function normalizeLookupKey(value) {
|
|
|
1060
1240
|
}
|
|
1061
1241
|
|
|
1062
1242
|
const DEFAULT_TASK_MODULE_ID = 3;
|
|
1243
|
+
const DEFAULT_MPP_REQUEST_TIMEOUT_MS = 300_000;
|
|
1063
1244
|
class TaskScheduleActionService {
|
|
1064
1245
|
http = inject(HttpClient);
|
|
1065
1246
|
buildTaskMutation(task, options = {}) {
|
|
@@ -1289,7 +1470,9 @@ class TaskScheduleActionService {
|
|
|
1289
1470
|
'tasks/{levelId}/import', {
|
|
1290
1471
|
levelId: this.requireId(context.levelId, 'Apply import requires levelId.'),
|
|
1291
1472
|
});
|
|
1292
|
-
return this.readData(this.http
|
|
1473
|
+
return this.readData(this.http
|
|
1474
|
+
.patch(endpoint, payload)
|
|
1475
|
+
.pipe(timeout(this.resolveMppRequestTimeoutMs(context))));
|
|
1293
1476
|
}
|
|
1294
1477
|
setBaseline(context, _payload = {}) {
|
|
1295
1478
|
const request = {
|
|
@@ -1617,6 +1800,12 @@ class TaskScheduleActionService {
|
|
|
1617
1800
|
}
|
|
1618
1801
|
return resolved;
|
|
1619
1802
|
}
|
|
1803
|
+
resolveMppRequestTimeoutMs(context) {
|
|
1804
|
+
const value = Number(context.mppRequestTimeoutMs);
|
|
1805
|
+
return Number.isFinite(value) && value > 0
|
|
1806
|
+
? value
|
|
1807
|
+
: DEFAULT_MPP_REQUEST_TIMEOUT_MS;
|
|
1808
|
+
}
|
|
1620
1809
|
requireProcessId(value) {
|
|
1621
1810
|
const resolved = this.toTaskId(value);
|
|
1622
1811
|
if (resolved === null) {
|
|
@@ -2421,7 +2610,7 @@ class TaskScheduleDialog {
|
|
|
2421
2610
|
};
|
|
2422
2611
|
}
|
|
2423
2612
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2424
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleDialog, isStandalone: true, selector: "mt-task-schedule-dialog", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, task: { classPropertyName: "task", publicName: "task", isSignal: true, isRequired: false, transformFunction: null }, typeOptions: { classPropertyName: "typeOptions", publicName: "typeOptions", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, parentGuid: { classPropertyName: "parentGuid", publicName: "parentGuid", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "clientForm", first: true, predicate: ClientForm, descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"'p-4 overflow-y-auto ' + (modal.contentClass || '')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [options]=\"typeSelectOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [label]=\"'task-schedule.dialog.type' | transloco\"\r\n [placeholder]=\"'task-schedule.dialog.typePlaceholder' | transloco\"\r\n [ngModel]=\"selectedType() ?? undefined\"\r\n (onChange)=\"onTypeChange($event)\"\r\n />\r\n\r\n @if (selectedType()) {\r\n <mt-client-form\r\n #clientForm\r\n [moduleKey]=\"'ModuleData'\"\r\n [moduleId]=\"selectedModuleId() ?? undefined\"\r\n [operationKey]=\"mode() === 'edit' ? 'Update' : 'Create'\"\r\n [formMode]=\"mode()\"\r\n [levelId]=\"context()?.levelId ?? undefined\"\r\n [levelDataId]=\"context()?.levelDataId ?? undefined\"\r\n [moduleDataId]=\"selectedModuleDataId() ?? undefined\"\r\n [lang]=\"langCode()\"\r\n [autoLoad]=\"true\"\r\n [ignoredFieldKeys]=\"ignoredFieldKeys()\"\r\n [submitRequestMapper]=\"submitRequestMapper\"\r\n (submitted)=\"onClientFormSubmitted($event)\"\r\n />\r\n } @else {\r\n <div\r\n class=\"rounded-xl border border-surface bg-content px-4 py-4 text-sm text-muted-color\"\r\n >\r\n {{ \"task-schedule.dialog.typeFirst\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <div class=\"flex items-center justify-end gap-3\">\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.cancel' | transloco\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.save' | transloco\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ClientForm, selector: "mt-client-form", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "returnUrl", "defaultValues", "submitRequestMapper", "readonly", "autoLoad", "formMode", "renderMode", "showInternalStepActions", "confirmWarningsOnSubmit", "confirmWarningsOnStepChange", "lookups", "statuses", "ignoredFieldKeys", "allowedFieldKeys"], outputs: ["loaded", "submitted", "errored", "modeDetected", "formSourceDetected", "footerStateChanged"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
2613
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleDialog, isStandalone: true, selector: "mt-task-schedule-dialog", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, task: { classPropertyName: "task", publicName: "task", isSignal: true, isRequired: false, transformFunction: null }, typeOptions: { classPropertyName: "typeOptions", publicName: "typeOptions", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, parentGuid: { classPropertyName: "parentGuid", publicName: "parentGuid", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "clientForm", first: true, predicate: ClientForm, descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"'p-4 overflow-y-auto ' + (modal.contentClass || '')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [options]=\"typeSelectOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [label]=\"'task-schedule.dialog.type' | transloco\"\r\n [placeholder]=\"'task-schedule.dialog.typePlaceholder' | transloco\"\r\n [ngModel]=\"selectedType() ?? undefined\"\r\n (onChange)=\"onTypeChange($event)\"\r\n />\r\n\r\n @if (selectedType()) {\r\n <mt-client-form\r\n #clientForm\r\n [moduleKey]=\"'ModuleData'\"\r\n [moduleId]=\"selectedModuleId() ?? undefined\"\r\n [operationKey]=\"mode() === 'edit' ? 'Update' : 'Create'\"\r\n [formMode]=\"mode()\"\r\n [levelId]=\"context()?.levelId ?? undefined\"\r\n [levelDataId]=\"context()?.levelDataId ?? undefined\"\r\n [moduleDataId]=\"selectedModuleDataId() ?? undefined\"\r\n [lang]=\"langCode()\"\r\n [autoLoad]=\"true\"\r\n [ignoredFieldKeys]=\"ignoredFieldKeys()\"\r\n [submitRequestMapper]=\"submitRequestMapper\"\r\n (submitted)=\"onClientFormSubmitted($event)\"\r\n />\r\n } @else {\r\n <div\r\n class=\"rounded-xl border border-surface bg-content px-4 py-4 text-sm text-muted-color\"\r\n >\r\n {{ \"task-schedule.dialog.typeFirst\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <div class=\"flex items-center justify-end gap-3\">\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.cancel' | transloco\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.save' | transloco\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ClientForm, selector: "mt-client-form", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "returnUrl", "defaultValues", "submitRequestMapper", "readonly", "autoLoad", "formMode", "renderMode", "showInternalStepActions", "confirmWarningsOnSubmit", "confirmWarningsOnStepChange", "readonlyFieldDisplayMode", "lookups", "statuses", "ignoredFieldKeys", "allowedFieldKeys"], outputs: ["loaded", "submitted", "errored", "modeDetected", "formSourceDetected", "footerStateChanged"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
|
|
2425
2614
|
}
|
|
2426
2615
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleDialog, decorators: [{
|
|
2427
2616
|
type: Component,
|
|
@@ -2539,7 +2728,8 @@ class TaskScheduleImportDialog {
|
|
|
2539
2728
|
return output;
|
|
2540
2729
|
}, ...(ngDevMode ? [{ debugName: "resourceOptions" }] : /* istanbul ignore next */ []));
|
|
2541
2730
|
isTruncated = computed(() => {
|
|
2542
|
-
const
|
|
2731
|
+
const maxRows = Math.max(1, this.maxRows());
|
|
2732
|
+
const loadedCount = this.countTasks(this.importResult()?.tasks ?? [], maxRows + 1);
|
|
2543
2733
|
return loadedCount > this.previewRows().length;
|
|
2544
2734
|
}, ...(ngDevMode ? [{ debugName: "isTruncated" }] : /* istanbul ignore next */ []));
|
|
2545
2735
|
allSelected = computed(() => {
|
|
@@ -2551,8 +2741,11 @@ class TaskScheduleImportDialog {
|
|
|
2551
2741
|
return rows.every((row) => selected.has(row.key));
|
|
2552
2742
|
}, ...(ngDevMode ? [{ debugName: "allSelected" }] : /* istanbul ignore next */ []));
|
|
2553
2743
|
hasSelection = computed(() => this.selectedTaskKeys().size > 0, ...(ngDevMode ? [{ debugName: "hasSelection" }] : /* istanbul ignore next */ []));
|
|
2554
|
-
canImport = computed(() => !!this.selectedFile() && !this.loadingImport(), ...(ngDevMode ? [{ debugName: "canImport" }] : /* istanbul ignore next */ []));
|
|
2555
|
-
canApply = computed(() => !!this.importResult() &&
|
|
2744
|
+
canImport = computed(() => !!this.selectedFile() && !this.loadingImport() && !this.loadingApply(), ...(ngDevMode ? [{ debugName: "canImport" }] : /* istanbul ignore next */ []));
|
|
2745
|
+
canApply = computed(() => !!this.importResult() &&
|
|
2746
|
+
this.hasSelection() &&
|
|
2747
|
+
!this.loadingApply() &&
|
|
2748
|
+
!this.loadingImport(), ...(ngDevMode ? [{ debugName: "canApply" }] : /* istanbul ignore next */ []));
|
|
2556
2749
|
previewPageSize = computed(() => Math.min(Math.max(this.previewRows().length, 1), 50), ...(ngDevMode ? [{ debugName: "previewPageSize" }] : /* istanbul ignore next */ []));
|
|
2557
2750
|
previewColumns = linkedSignal(() => [
|
|
2558
2751
|
{
|
|
@@ -2613,6 +2806,9 @@ class TaskScheduleImportDialog {
|
|
|
2613
2806
|
this.errorMessage.set(null);
|
|
2614
2807
|
}
|
|
2615
2808
|
importFile() {
|
|
2809
|
+
if (this.loadingImport() || this.loadingApply()) {
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2616
2812
|
const context = this.context();
|
|
2617
2813
|
const file = this.selectedFile();
|
|
2618
2814
|
if (!context) {
|
|
@@ -2629,8 +2825,12 @@ class TaskScheduleImportDialog {
|
|
|
2629
2825
|
}
|
|
2630
2826
|
this.errorMessage.set(null);
|
|
2631
2827
|
this.loadingImport.set(true);
|
|
2828
|
+
const importContext = {
|
|
2829
|
+
...context,
|
|
2830
|
+
mppPreviewMaxRows: Math.max(1, this.maxRows()),
|
|
2831
|
+
};
|
|
2632
2832
|
this.fetchService
|
|
2633
|
-
.importTasks(
|
|
2833
|
+
.importTasks(importContext, file)
|
|
2634
2834
|
.pipe(finalize(() => this.loadingImport.set(false)))
|
|
2635
2835
|
.subscribe({
|
|
2636
2836
|
next: (result) => {
|
|
@@ -2655,13 +2855,16 @@ class TaskScheduleImportDialog {
|
|
|
2655
2855
|
selectAllRows(checked) {
|
|
2656
2856
|
const next = new Set();
|
|
2657
2857
|
if (checked) {
|
|
2658
|
-
this.
|
|
2858
|
+
this.previewRows().forEach(({ key }) => {
|
|
2659
2859
|
next.add(key);
|
|
2660
2860
|
});
|
|
2661
2861
|
}
|
|
2662
2862
|
this.selectedTaskKeys.set(next);
|
|
2663
2863
|
}
|
|
2664
2864
|
applyImport(overrideCurrent) {
|
|
2865
|
+
if (this.loadingImport() || this.loadingApply()) {
|
|
2866
|
+
return;
|
|
2867
|
+
}
|
|
2665
2868
|
const context = this.context();
|
|
2666
2869
|
const importResult = this.importResult();
|
|
2667
2870
|
if (!context || !importResult) {
|
|
@@ -2674,7 +2877,7 @@ class TaskScheduleImportDialog {
|
|
|
2674
2877
|
}
|
|
2675
2878
|
const payload = {
|
|
2676
2879
|
overrideCurrent,
|
|
2677
|
-
data: this.buildApplyPayloadData(
|
|
2880
|
+
data: this.buildApplyPayloadData(),
|
|
2678
2881
|
};
|
|
2679
2882
|
this.errorMessage.set(null);
|
|
2680
2883
|
this.loadingApply.set(true);
|
|
@@ -2806,6 +3009,9 @@ class TaskScheduleImportDialog {
|
|
|
2806
3009
|
if (!path) {
|
|
2807
3010
|
return null;
|
|
2808
3011
|
}
|
|
3012
|
+
return this.findTaskByPath(path);
|
|
3013
|
+
}
|
|
3014
|
+
findTaskByPath(path) {
|
|
2809
3015
|
const steps = path.split('.').filter((segment) => segment !== '');
|
|
2810
3016
|
if (!steps.length || steps[0] !== 'root') {
|
|
2811
3017
|
return null;
|
|
@@ -2840,42 +3046,53 @@ class TaskScheduleImportDialog {
|
|
|
2840
3046
|
tasks: [...result.tasks],
|
|
2841
3047
|
});
|
|
2842
3048
|
}
|
|
2843
|
-
buildApplyPayloadData(
|
|
3049
|
+
buildApplyPayloadData() {
|
|
2844
3050
|
const selected = this.selectedTaskKeys();
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
payloadTask['startDate'] = this.toApiDate(task.startDate);
|
|
2861
|
-
payloadTask['finishDate'] = this.toApiDate(task.finishDate);
|
|
2862
|
-
payloadTask['baselineStart'] = this.toApiDate(task.baselineStartDate ?? task.baselineStart);
|
|
2863
|
-
payloadTask['baselineFinish'] = this.toApiDate(task.baselineEndDate ?? task.baselineFinish);
|
|
2864
|
-
payloadTask['actualStart'] = this.toApiDate(task.actualStartDate ?? task.actualStart);
|
|
2865
|
-
payloadTask['actualFinish'] = this.toApiDate(task.actualFinishDate ?? task.actualFinish);
|
|
2866
|
-
payloadTask['customProperties'] =
|
|
2867
|
-
task.customProperties ?? task.props ?? [];
|
|
2868
|
-
payloadTask['isMilestone'] =
|
|
2869
|
-
String(task.type ?? task.typeLabel ?? task.typeLable ?? '').toLowerCase() === 'milestone';
|
|
2870
|
-
output.push(payloadTask);
|
|
2871
|
-
const children = this.resolveChildTasks(task);
|
|
2872
|
-
if (children.length) {
|
|
2873
|
-
walk(children, task.guid ?? String(task.id ?? ''), path);
|
|
2874
|
-
}
|
|
2875
|
-
});
|
|
3051
|
+
return this.previewRows()
|
|
3052
|
+
.filter((row) => selected.has(row.key))
|
|
3053
|
+
.map((row) => this.buildApplyPayloadTask(row));
|
|
3054
|
+
}
|
|
3055
|
+
buildApplyPayloadTask(row) {
|
|
3056
|
+
const task = row.task;
|
|
3057
|
+
const payloadTask = {
|
|
3058
|
+
...task,
|
|
3059
|
+
name: String(task.title ?? task.name ?? ''),
|
|
3060
|
+
predecessors: task.predecessor ?? task.predecessors ?? '',
|
|
3061
|
+
parentGuid: task.parentGuid ?? this.resolveParentGuidForPreviewRow(row.key),
|
|
3062
|
+
assignedTo: this.resolveAssignedTo(task),
|
|
3063
|
+
isSelected: true,
|
|
3064
|
+
subtasks: [],
|
|
3065
|
+
children: [],
|
|
2876
3066
|
};
|
|
2877
|
-
|
|
2878
|
-
|
|
3067
|
+
payloadTask['startDate'] = this.toApiDate(task.startDate);
|
|
3068
|
+
payloadTask['finishDate'] = this.toApiDate(task.finishDate);
|
|
3069
|
+
payloadTask['baselineStart'] = this.toApiDate(task.baselineStartDate ?? task.baselineStart);
|
|
3070
|
+
payloadTask['baselineFinish'] = this.toApiDate(task.baselineEndDate ?? task.baselineFinish);
|
|
3071
|
+
payloadTask['actualStart'] = this.toApiDate(task.actualStartDate ?? task.actualStart);
|
|
3072
|
+
payloadTask['actualFinish'] = this.toApiDate(task.actualFinishDate ?? task.actualFinish);
|
|
3073
|
+
payloadTask['customProperties'] =
|
|
3074
|
+
task.customProperties ?? task.props ?? [];
|
|
3075
|
+
payloadTask['isMilestone'] =
|
|
3076
|
+
String(task.type ?? task.typeLabel ?? task.typeLable ?? '').toLowerCase() === 'milestone';
|
|
3077
|
+
return payloadTask;
|
|
3078
|
+
}
|
|
3079
|
+
resolveParentGuidForPreviewRow(rowKey) {
|
|
3080
|
+
const path = this.readPathFromRowKey(rowKey);
|
|
3081
|
+
if (!path) {
|
|
3082
|
+
return null;
|
|
3083
|
+
}
|
|
3084
|
+
const steps = path.split('.').filter((segment) => segment !== '');
|
|
3085
|
+
if (steps.length <= 2) {
|
|
3086
|
+
return null;
|
|
3087
|
+
}
|
|
3088
|
+
const parent = this.findTaskByPath(steps.slice(0, -1).join('.'));
|
|
3089
|
+
if (!parent) {
|
|
3090
|
+
return null;
|
|
3091
|
+
}
|
|
3092
|
+
const parentGuid = parent.guid ?? parent.id ?? null;
|
|
3093
|
+
return parentGuid === null || parentGuid === undefined
|
|
3094
|
+
? null
|
|
3095
|
+
: String(parentGuid);
|
|
2879
3096
|
}
|
|
2880
3097
|
resolveChildTasks(task) {
|
|
2881
3098
|
const subtasks = Array.isArray(task.subtasks) ? task.subtasks : [];
|
|
@@ -2889,21 +3106,6 @@ class TaskScheduleImportDialog {
|
|
|
2889
3106
|
const base = task.guid ?? task.id ?? path;
|
|
2890
3107
|
return `${String(base)}::${path}`;
|
|
2891
3108
|
}
|
|
2892
|
-
collectTaskKeys(tasks) {
|
|
2893
|
-
const keys = new Set();
|
|
2894
|
-
const walk = (rows, pathPrefix) => {
|
|
2895
|
-
rows.forEach((task, index) => {
|
|
2896
|
-
const path = `${pathPrefix}.${index}`;
|
|
2897
|
-
keys.add(this.resolveTaskKey(task, path));
|
|
2898
|
-
const children = this.resolveChildTasks(task);
|
|
2899
|
-
if (children.length) {
|
|
2900
|
-
walk(children, path);
|
|
2901
|
-
}
|
|
2902
|
-
});
|
|
2903
|
-
};
|
|
2904
|
-
walk(tasks, 'root');
|
|
2905
|
-
return keys;
|
|
2906
|
-
}
|
|
2907
3109
|
resolveAssignedTo(task) {
|
|
2908
3110
|
const assignedTo = task.assignedTo;
|
|
2909
3111
|
if ((typeof assignedTo === 'string' || typeof assignedTo === 'number') &&
|
|
@@ -3014,6 +3216,7 @@ class TaskScheduleImportDialog {
|
|
|
3014
3216
|
if (typeof value === 'object') {
|
|
3015
3217
|
const row = value;
|
|
3016
3218
|
return (this.toApiDate(row['actualValue']) ??
|
|
3219
|
+
this.toApiDate(row['raw']) ??
|
|
3017
3220
|
this.toApiDate(row['displayValue']) ??
|
|
3018
3221
|
this.toApiDate(row['value']) ??
|
|
3019
3222
|
null);
|
|
@@ -3026,16 +3229,19 @@ class TaskScheduleImportDialog {
|
|
|
3026
3229
|
const day = String(date.getDate()).padStart(2, '0');
|
|
3027
3230
|
return `${year}-${month}-${day}`;
|
|
3028
3231
|
}
|
|
3029
|
-
countTasks(tasks) {
|
|
3232
|
+
countTasks(tasks, maxCount) {
|
|
3030
3233
|
let count = 0;
|
|
3031
3234
|
const walk = (rows) => {
|
|
3032
|
-
|
|
3235
|
+
for (const task of rows) {
|
|
3236
|
+
if (count >= maxCount) {
|
|
3237
|
+
return;
|
|
3238
|
+
}
|
|
3033
3239
|
count += 1;
|
|
3034
3240
|
const children = this.resolveChildTasks(task);
|
|
3035
3241
|
if (children.length) {
|
|
3036
3242
|
walk(children);
|
|
3037
3243
|
}
|
|
3038
|
-
}
|
|
3244
|
+
}
|
|
3039
3245
|
};
|
|
3040
3246
|
walk(tasks);
|
|
3041
3247
|
return count;
|
|
@@ -3044,24 +3250,24 @@ class TaskScheduleImportDialog {
|
|
|
3044
3250
|
this.errorMessage.set(message);
|
|
3045
3251
|
}
|
|
3046
3252
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleImportDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3047
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleImportDialog, isStandalone: true, selector: "mt-task-schedule-import-dialog", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "selectionCellTpl", first: true, predicate: ["selectionCellTpl"], descendants: true, isSignal: true }, { propertyName: "taskCellTpl", first: true, predicate: ["taskCellTpl"], descendants: true, isSignal: true }, { propertyName: "startDateCellTpl", first: true, predicate: ["startDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "finishDateCellTpl", first: true, predicate: ["finishDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "actualStartDateCellTpl", first: true, predicate: ["actualStartDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "actualFinishDateCellTpl", first: true, predicate: ["actualFinishDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "assignedToCellTpl", first: true, predicate: ["assignedToCellTpl"], descendants: true, isSignal: true }, { propertyName: "progressCellTpl", first: true, predicate: ["progressCellTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\r\n [class]=\"modal.contentClass\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\r\n>\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\r\n <input\r\n #fileInput\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n\r\n <mt-text-field\r\n [ngModel]=\"selectedFile()?.name ?? ''\"\r\n [readonly]=\"true\"\r\n [placeholder]=\"labels().selectFile\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().selectFile\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n [disabled]=\"loadingImport() || loadingApply()\"\r\n (onClick)=\"fileInput.click()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().startImport\"\r\n [disabled]=\"!canImport()\"\r\n [loading]=\"loadingImport()\"\r\n (onClick)=\"importFile()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (errorMessage()) {\r\n <div\r\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\r\n >\r\n {{ errorMessage() }}\r\n </div>\r\n }\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\r\n @if (importResult()) {\r\n @if (!previewRows().length) {\r\n <div\r\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\r\n >\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelected()\"\r\n (ngModelChange)=\"selectAllRows(!!$event)\"\r\n />\r\n <span class=\"text-sm text-surface-600\">\r\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\r\n </span>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-surface-500\">\r\n {{ labels().rowsLimited }}\r\n </p>\r\n }\r\n </div>\r\n\r\n <div class=\"px-2 py-2\">\r\n <mt-table\r\n [data]=\"previewRows()\"\r\n [columns]=\"previewColumns()\"\r\n dataKey=\"key\"\r\n storageKey=\"task-schedule-import-preview-table\"\r\n size=\"small\"\r\n [stripedRows]=\"true\"\r\n [showGridlines]=\"true\"\r\n [pageSize]=\"previewPageSize()\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n variant=\"outlined\"\r\n [disabled]=\"loadingImport() || loadingApply()\"\r\n (onClick)=\"close()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().replace\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(true)\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().append\"\r\n severity=\"secondary\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(false)\"\r\n />\r\n</div>\r\n\r\n<ng-template #selectionCellTpl let-row>\r\n <div class=\"flex items-center justify-center\">\r\n <mt-checkbox-field\r\n [ngModel]=\"selectedTaskKeys().has(row.key)\"\r\n (ngModelChange)=\"toggleRowSelection(row.key, !!$event)\"\r\n />\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #taskCellTpl let-row>\r\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\r\n <mt-text-field\r\n [ngModel]=\"row.task.title || row.task.name || ''\"\r\n (ngModelChange)=\"onTaskTitleChanged(row.key, $event)\"\r\n />\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #startDateCellTpl let-row>\r\n <mt-date-field\r\n [ngModel]=\"toDateFieldValue(row.task.startDate)\"\r\n [showClear]=\"true\"\r\n (ngModelChange)=\"onTaskDateChanged(row.key, 'startDate', $event)\"\r\n />\r\n</ng-template>\r\n\r\n<ng-template #finishDateCellTpl let-row>\r\n <mt-date-field\r\n [ngModel]=\"toDateFieldValue(row.task.finishDate)\"\r\n [showClear]=\"true\"\r\n (ngModelChange)=\"onTaskDateChanged(row.key, 'finishDate', $event)\"\r\n />\r\n</ng-template>\r\n\r\n<ng-template #actualStartDateCellTpl let-row>\r\n <mt-date-field\r\n [ngModel]=\"\r\n toDateFieldValue(row.task.actualStartDate || row.task.actualStart)\r\n \"\r\n [showClear]=\"true\"\r\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualStartDate', $event)\"\r\n />\r\n</ng-template>\r\n\r\n<ng-template #actualFinishDateCellTpl let-row>\r\n <mt-date-field\r\n [ngModel]=\"\r\n toDateFieldValue(row.task.actualFinishDate || row.task.actualFinish)\r\n \"\r\n [showClear]=\"true\"\r\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualFinishDate', $event)\"\r\n />\r\n</ng-template>\r\n\r\n<ng-template #assignedToCellTpl let-row>\r\n <div class=\"min-w-0\">\r\n @if (resourceOptions().length) {\r\n <div class=\"space-y-2\">\r\n <mt-select-field\r\n [ngModel]=\"resolveAssignedValue(row.task)\"\r\n [options]=\"resourceOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"id\"\r\n [showClear]=\"true\"\r\n [hasPlaceholderPrefix]=\"false\"\r\n [placeholder]=\"labels().assignedTo\"\r\n (ngModelChange)=\"onTaskAssignedToChanged(row.key, $event)\"\r\n />\r\n @if (row.task.assignedTo) {\r\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\r\n }\r\n </div>\r\n } @else if (row.task.assignedTo) {\r\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\r\n } @else {\r\n <span class=\"text-slate-400\">-</span>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #progressCellTpl let-row>\r\n <div class=\"space-y-2\">\r\n <mt-number-field\r\n [ngModel]=\"normalizeProgress(row.task.progress)\"\r\n [min]=\"0\"\r\n [max]=\"100\"\r\n [useGrouping]=\"false\"\r\n [maxFractionDigits]=\"0\"\r\n (ngModelChange)=\"onTaskProgressChanged(row.key, $event)\"\r\n />\r\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\r\n </div>\r\n</ng-template>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs", "required"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { 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", "exportable", "printable", "groupable", "cellClickFilter", "freezeActions", "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: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "ngmodule", type: TranslocoModule }] });
|
|
3253
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleImportDialog, isStandalone: true, selector: "mt-task-schedule-import-dialog", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "selectionCellTpl", first: true, predicate: ["selectionCellTpl"], descendants: true, isSignal: true }, { propertyName: "taskCellTpl", first: true, predicate: ["taskCellTpl"], descendants: true, isSignal: true }, { propertyName: "startDateCellTpl", first: true, predicate: ["startDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "finishDateCellTpl", first: true, predicate: ["finishDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "actualStartDateCellTpl", first: true, predicate: ["actualStartDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "actualFinishDateCellTpl", first: true, predicate: ["actualFinishDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "assignedToCellTpl", first: true, predicate: ["assignedToCellTpl"], descendants: true, isSignal: true }, { propertyName: "progressCellTpl", first: true, predicate: ["progressCellTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n [class]=\"modal.contentClass\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\n>\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\n <input\n #fileInput\n class=\"hidden\"\n type=\"file\"\n accept=\".mpp,.xer\"\n (change)=\"onFileChanged($event)\"\n />\n\n <mt-text-field\n [ngModel]=\"selectedFile()?.name ?? ''\"\n [readonly]=\"true\"\n [placeholder]=\"labels().selectFile\"\n />\n\n <mt-button\n [label]=\"labels().selectFile\"\n severity=\"secondary\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"fileInput.click()\"\n />\n\n <mt-button\n [label]=\"labels().startImport\"\n [disabled]=\"!canImport()\"\n [loading]=\"loadingImport()\"\n (onClick)=\"importFile()\"\n />\n </div>\n </div>\n\n @if (errorMessage()) {\n <div\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\n >\n {{ errorMessage() }}\n </div>\n }\n\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\n @if (importResult()) {\n @if (!previewRows().length) {\n <div\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\n >\n {{ labels().noTasks }}\n </div>\n } @else {\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\n <div\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\n >\n <div class=\"flex items-center gap-3\">\n <mt-checkbox-field\n [ngModel]=\"allSelected()\"\n (ngModelChange)=\"selectAllRows(!!$event)\"\n />\n <span class=\"text-sm text-surface-600\">\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\n </span>\n </div>\n\n @if (isTruncated()) {\n <p class=\"text-xs text-surface-500\">\n {{ labels().rowsLimited }}\n </p>\n }\n </div>\n\n <div class=\"px-2 py-2\">\n @defer (on idle) {\n <mt-table\n [data]=\"previewRows()\"\n [columns]=\"previewColumns()\"\n dataKey=\"key\"\n storageKey=\"task-schedule-import-preview-table\"\n size=\"small\"\n [stripedRows]=\"true\"\n [showGridlines]=\"true\"\n [pageSize]=\"previewPageSize()\"\n />\n } @placeholder {\n <div class=\"space-y-2 p-2\">\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button\n [label]=\"labels().cancel\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"close()\"\n />\n\n <mt-button\n [label]=\"labels().replace\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(true)\"\n />\n\n <mt-button\n [label]=\"labels().append\"\n severity=\"secondary\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(false)\"\n />\n</div>\n\n<ng-template #selectionCellTpl let-row>\n <div class=\"flex items-center justify-center\">\n <mt-checkbox-field\n [ngModel]=\"selectedTaskKeys().has(row.key)\"\n (ngModelChange)=\"toggleRowSelection(row.key, !!$event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #taskCellTpl let-row>\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\n <mt-text-field\n [ngModel]=\"row.task.title || row.task.name || ''\"\n (ngModelChange)=\"onTaskTitleChanged(row.key, $event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #startDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.startDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'startDate', $event)\"\n />\n</ng-template>\n\n<ng-template #finishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.finishDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'finishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualStartDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualStartDate || row.task.actualStart)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualStartDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualFinishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualFinishDate || row.task.actualFinish)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualFinishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #assignedToCellTpl let-row>\n <div class=\"min-w-0\">\n @if (resourceOptions().length) {\n <div class=\"space-y-2\">\n <mt-select-field\n [ngModel]=\"resolveAssignedValue(row.task)\"\n [options]=\"resourceOptions()\"\n optionLabel=\"label\"\n optionValue=\"id\"\n [showClear]=\"true\"\n [hasPlaceholderPrefix]=\"false\"\n [placeholder]=\"labels().assignedTo\"\n (ngModelChange)=\"onTaskAssignedToChanged(row.key, $event)\"\n />\n @if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n }\n </div>\n } @else if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n } @else {\n <span class=\"text-slate-400\">-</span>\n }\n </div>\n</ng-template>\n\n<ng-template #progressCellTpl let-row>\n <div class=\"space-y-2\">\n <mt-number-field\n [ngModel]=\"normalizeProgress(row.task.progress)\"\n [min]=\"0\"\n [max]=\"100\"\n [useGrouping]=\"false\"\n [maxFractionDigits]=\"0\"\n (ngModelChange)=\"onTaskProgressChanged(row.key, $event)\"\n />\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs", "required"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "ngmodule", type: TranslocoModule }], deferBlockDependencies: [() => [import('@masterteam/components/table').then(m => m.Table)]] });
|
|
3048
3254
|
}
|
|
3049
|
-
i0.ɵɵ
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3255
|
+
i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleImportDialog, resolveDeferredDeps: () => [import('@masterteam/components/table').then(m => m.Table)], resolveMetadata: Table => ({ decorators: [{
|
|
3256
|
+
type: Component,
|
|
3257
|
+
args: [{ selector: 'mt-task-schedule-import-dialog', standalone: true, imports: [
|
|
3258
|
+
CommonModule,
|
|
3259
|
+
FormsModule,
|
|
3260
|
+
Button,
|
|
3261
|
+
CheckboxField,
|
|
3262
|
+
DateField,
|
|
3263
|
+
EntityPreview,
|
|
3264
|
+
NumberField,
|
|
3265
|
+
SelectField,
|
|
3266
|
+
Table,
|
|
3267
|
+
TextField,
|
|
3268
|
+
TranslocoModule,
|
|
3269
|
+
], template: "<div\n [class]=\"modal.contentClass\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\n>\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\n <input\n #fileInput\n class=\"hidden\"\n type=\"file\"\n accept=\".mpp,.xer\"\n (change)=\"onFileChanged($event)\"\n />\n\n <mt-text-field\n [ngModel]=\"selectedFile()?.name ?? ''\"\n [readonly]=\"true\"\n [placeholder]=\"labels().selectFile\"\n />\n\n <mt-button\n [label]=\"labels().selectFile\"\n severity=\"secondary\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"fileInput.click()\"\n />\n\n <mt-button\n [label]=\"labels().startImport\"\n [disabled]=\"!canImport()\"\n [loading]=\"loadingImport()\"\n (onClick)=\"importFile()\"\n />\n </div>\n </div>\n\n @if (errorMessage()) {\n <div\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\n >\n {{ errorMessage() }}\n </div>\n }\n\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\n @if (importResult()) {\n @if (!previewRows().length) {\n <div\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\n >\n {{ labels().noTasks }}\n </div>\n } @else {\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\n <div\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\n >\n <div class=\"flex items-center gap-3\">\n <mt-checkbox-field\n [ngModel]=\"allSelected()\"\n (ngModelChange)=\"selectAllRows(!!$event)\"\n />\n <span class=\"text-sm text-surface-600\">\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\n </span>\n </div>\n\n @if (isTruncated()) {\n <p class=\"text-xs text-surface-500\">\n {{ labels().rowsLimited }}\n </p>\n }\n </div>\n\n <div class=\"px-2 py-2\">\n @defer (on idle) {\n <mt-table\n [data]=\"previewRows()\"\n [columns]=\"previewColumns()\"\n dataKey=\"key\"\n storageKey=\"task-schedule-import-preview-table\"\n size=\"small\"\n [stripedRows]=\"true\"\n [showGridlines]=\"true\"\n [pageSize]=\"previewPageSize()\"\n />\n } @placeholder {\n <div class=\"space-y-2 p-2\">\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button\n [label]=\"labels().cancel\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"close()\"\n />\n\n <mt-button\n [label]=\"labels().replace\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(true)\"\n />\n\n <mt-button\n [label]=\"labels().append\"\n severity=\"secondary\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(false)\"\n />\n</div>\n\n<ng-template #selectionCellTpl let-row>\n <div class=\"flex items-center justify-center\">\n <mt-checkbox-field\n [ngModel]=\"selectedTaskKeys().has(row.key)\"\n (ngModelChange)=\"toggleRowSelection(row.key, !!$event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #taskCellTpl let-row>\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\n <mt-text-field\n [ngModel]=\"row.task.title || row.task.name || ''\"\n (ngModelChange)=\"onTaskTitleChanged(row.key, $event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #startDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.startDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'startDate', $event)\"\n />\n</ng-template>\n\n<ng-template #finishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.finishDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'finishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualStartDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualStartDate || row.task.actualStart)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualStartDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualFinishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualFinishDate || row.task.actualFinish)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualFinishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #assignedToCellTpl let-row>\n <div class=\"min-w-0\">\n @if (resourceOptions().length) {\n <div class=\"space-y-2\">\n <mt-select-field\n [ngModel]=\"resolveAssignedValue(row.task)\"\n [options]=\"resourceOptions()\"\n optionLabel=\"label\"\n optionValue=\"id\"\n [showClear]=\"true\"\n [hasPlaceholderPrefix]=\"false\"\n [placeholder]=\"labels().assignedTo\"\n (ngModelChange)=\"onTaskAssignedToChanged(row.key, $event)\"\n />\n @if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n }\n </div>\n } @else if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n } @else {\n <span class=\"text-slate-400\">-</span>\n }\n </div>\n</ng-template>\n\n<ng-template #progressCellTpl let-row>\n <div class=\"space-y-2\">\n <mt-number-field\n [ngModel]=\"normalizeProgress(row.task.progress)\"\n [min]=\"0\"\n [max]=\"100\"\n [useGrouping]=\"false\"\n [maxFractionDigits]=\"0\"\n (ngModelChange)=\"onTaskProgressChanged(row.key, $event)\"\n />\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\n </div>\n</ng-template>\n" }]
|
|
3270
|
+
}], ctorParameters: null, propDecorators: { selectionCellTpl: [{ type: i0.ViewChild, args: ['selectionCellTpl', { isSignal: true }] }], taskCellTpl: [{ type: i0.ViewChild, args: ['taskCellTpl', { isSignal: true }] }], startDateCellTpl: [{ type: i0.ViewChild, args: ['startDateCellTpl', { isSignal: true }] }], finishDateCellTpl: [{ type: i0.ViewChild, args: ['finishDateCellTpl', { isSignal: true }] }], actualStartDateCellTpl: [{ type: i0.ViewChild, args: ['actualStartDateCellTpl', { isSignal: true }] }], actualFinishDateCellTpl: [{ type: i0.ViewChild, args: ['actualFinishDateCellTpl', { isSignal: true }] }], assignedToCellTpl: [{ type: i0.ViewChild, args: ['assignedToCellTpl', { isSignal: true }] }], progressCellTpl: [{ type: i0.ViewChild, args: ['progressCellTpl', { isSignal: true }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }] } }) });
|
|
3065
3271
|
|
|
3066
3272
|
class TaskScheduleQueueService {
|
|
3067
3273
|
basicOrderColumns = new Map();
|
|
@@ -3270,6 +3476,7 @@ class TaskSchedule {
|
|
|
3270
3476
|
fetchService = inject(TaskScheduleFetchService);
|
|
3271
3477
|
actionService = inject(TaskScheduleActionService);
|
|
3272
3478
|
modal = inject(ModalService);
|
|
3479
|
+
dateFormats = inject(MT_DATE_FORMATS);
|
|
3273
3480
|
queueService = inject(TaskScheduleQueueService);
|
|
3274
3481
|
injector = inject(Injector);
|
|
3275
3482
|
loadEffect;
|
|
@@ -3299,7 +3506,7 @@ class TaskSchedule {
|
|
|
3299
3506
|
}, ...(ngDevMode ? [{ debugName: "treeColumnIndex" }] : /* istanbul ignore next */ []));
|
|
3300
3507
|
ganttId = `mtTaskScheduleGantt-${Math.random().toString(36).slice(2, 10)}`;
|
|
3301
3508
|
resolvedModelTypeInput = computed(() => this.context()?.modelType ?? 'default', ...(ngDevMode ? [{ debugName: "resolvedModelTypeInput" }] : /* istanbul ignore next */ []));
|
|
3302
|
-
resolvedDateFormat = computed(() => this.context()?.dateFormat ??
|
|
3509
|
+
resolvedDateFormat = computed(() => toAngularDateFormat(this.context()?.dateFormat ?? this.dateFormats.date), ...(ngDevMode ? [{ debugName: "resolvedDateFormat" }] : /* istanbul ignore next */ []));
|
|
3303
3510
|
resolvedHeight = computed(() => this.context()?.height ?? '760px', ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : /* istanbul ignore next */ []));
|
|
3304
3511
|
resolvedModelType = computed(() => normalizeTaskScheduleModelType(this.resolvedModelTypeInput()), ...(ngDevMode ? [{ debugName: "resolvedModelType" }] : /* istanbul ignore next */ []));
|
|
3305
3512
|
resolvedLangCode = computed(() => this.context()?.langCode === 'ar' ? 'ar' : 'en', ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : /* istanbul ignore next */ []));
|
|
@@ -3891,11 +4098,16 @@ class TaskSchedule {
|
|
|
3891
4098
|
ToolbarService,
|
|
3892
4099
|
ContextMenuService,
|
|
3893
4100
|
ResizeService,
|
|
3894
|
-
], viewQueries: [{ propertyName: "ganttObj", first: true, predicate: ["ganttObj"], descendants: true }], ngImport: i0, template: "@if (!loading()) {\r\n <ejs-gantt\r\n #ganttObj\r\n [id]=\"ganttId\"\r\n [enableVirtualization]=\"true\"\r\n [enableTimelineVirtualization]=\"true\"\r\n [enableVirtualMaskRow]=\"false\"\r\n [allowResizing]=\"true\"\r\n [enableRtl]=\"enableRtl()\"\r\n [locale]=\"locale()\"\r\n [height]=\"resolvedHeight()\"\r\n [dataSource]=\"dataSource()\"\r\n [taskFields]=\"ganttConfig().taskFields\"\r\n [columns]=\"ganttConfig().columns\"\r\n [renderBaseline]=\"ganttConfig().renderBaseline\"\r\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\r\n [allowSelection]=\"true\"\r\n [labelSettings]=\"ganttConfig().labelSettings\"\r\n [treeColumnIndex]=\"treeColumnIndex()\"\r\n [workWeek]=\"ganttConfig().workWeek\"\r\n [highlightWeekends]=\"true\"\r\n [enablePredecessorValidation]=\"true\"\r\n [splitterSettings]=\"ganttConfig().splitterSettings\"\r\n [gridLines]=\"ganttConfig().gridLines\"\r\n [toolbar]=\"ganttConfig().toolbar\"\r\n [allowExcelExport]=\"ganttConfig().allowExcelExport\"\r\n [allowPdfExport]=\"ganttConfig().allowPdfExport\"\r\n [enableContextMenu]=\"ganttConfig().enableContextMenu\"\r\n [contextMenuItems]=\"ganttConfig().contextMenuItems\"\r\n [timelineSettings]=\"ganttConfig().timelineSettings\"\r\n [editSettings]=\"ganttConfig().editSettings\"\r\n [allowRowDragAndDrop]=\"ganttConfig().allowRowDragAndDrop\"\r\n [addDialogFields]=\"ganttConfig().addDialogFields\"\r\n [editDialogFields]=\"ganttConfig().editDialogFields\"\r\n [resourceFields]=\"ganttConfig().resourceFields\"\r\n [resources]=\"ganttConfig().resources\"\r\n [viewType]=\"ganttConfig().viewType\"\r\n [showOverAllocation]=\"ganttConfig().showOverAllocation\"\r\n [allowUnscheduledTasks]=\"ganttConfig().allowUnscheduledTasks\"\r\n [eventMarkers]=\"ganttConfig().eventMarkers\"\r\n [projectStartDate]=\"ganttConfig().projectStartDate\"\r\n [projectEndDate]=\"ganttConfig().projectEndDate\"\r\n [autoCalculateDateScheduling]=\"false\"\r\n [dateFormat]=\"resolvedDateFormat()\"\r\n [allowSorting]=\"true\"\r\n [holidays]=\"ganttConfig().holidays\"\r\n [enableWBS]=\"true\"\r\n [enableAutoWbsUpdate]=\"true\"\r\n [allowReordering]=\"true\"\r\n (toolbarClick)=\"onToolbarClick($event)\"\r\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\r\n (contextMenuClick)=\"onContextMenuClick($event)\"\r\n (actionBegin)=\"onActionBegin($event)\"\r\n (actionComplete)=\"onActionComplete($event)\"\r\n (cellEdit)=\"onCellEdit($event)\"\r\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\r\n (dataBound)=\"onDataBound()\"\r\n >\r\n <ng-template #tooltipSettingsTaskbar let-data>\r\n <div class=\"px-2 py-1 text-xs\">\r\n <div class=\"font-medium\">{{ data?.title ?? \"-\" }}</div>\r\n <div>\r\n {{ tooltipTranslations().startsOn }}:\r\n {{ data?.startDate
|
|
4101
|
+
], viewQueries: [{ propertyName: "ganttObj", first: true, predicate: ["ganttObj"], descendants: true }], ngImport: i0, template: "@if (!loading()) {\r\n <ejs-gantt\r\n #ganttObj\r\n [id]=\"ganttId\"\r\n [enableVirtualization]=\"true\"\r\n [enableTimelineVirtualization]=\"true\"\r\n [enableVirtualMaskRow]=\"false\"\r\n [allowResizing]=\"true\"\r\n [enableRtl]=\"enableRtl()\"\r\n [locale]=\"locale()\"\r\n [height]=\"resolvedHeight()\"\r\n [dataSource]=\"dataSource()\"\r\n [taskFields]=\"ganttConfig().taskFields\"\r\n [columns]=\"ganttConfig().columns\"\r\n [renderBaseline]=\"ganttConfig().renderBaseline\"\r\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\r\n [allowSelection]=\"true\"\r\n [labelSettings]=\"ganttConfig().labelSettings\"\r\n [treeColumnIndex]=\"treeColumnIndex()\"\r\n [workWeek]=\"ganttConfig().workWeek\"\r\n [highlightWeekends]=\"true\"\r\n [enablePredecessorValidation]=\"true\"\r\n [splitterSettings]=\"ganttConfig().splitterSettings\"\r\n [gridLines]=\"ganttConfig().gridLines\"\r\n [toolbar]=\"ganttConfig().toolbar\"\r\n [allowExcelExport]=\"ganttConfig().allowExcelExport\"\r\n [allowPdfExport]=\"ganttConfig().allowPdfExport\"\r\n [enableContextMenu]=\"ganttConfig().enableContextMenu\"\r\n [contextMenuItems]=\"ganttConfig().contextMenuItems\"\r\n [timelineSettings]=\"ganttConfig().timelineSettings\"\r\n [editSettings]=\"ganttConfig().editSettings\"\r\n [allowRowDragAndDrop]=\"ganttConfig().allowRowDragAndDrop\"\r\n [addDialogFields]=\"ganttConfig().addDialogFields\"\r\n [editDialogFields]=\"ganttConfig().editDialogFields\"\r\n [resourceFields]=\"ganttConfig().resourceFields\"\r\n [resources]=\"ganttConfig().resources\"\r\n [viewType]=\"ganttConfig().viewType\"\r\n [showOverAllocation]=\"ganttConfig().showOverAllocation\"\r\n [allowUnscheduledTasks]=\"ganttConfig().allowUnscheduledTasks\"\r\n [eventMarkers]=\"ganttConfig().eventMarkers\"\r\n [projectStartDate]=\"ganttConfig().projectStartDate\"\r\n [projectEndDate]=\"ganttConfig().projectEndDate\"\r\n [autoCalculateDateScheduling]=\"false\"\r\n [dateFormat]=\"resolvedDateFormat()\"\r\n [allowSorting]=\"true\"\r\n [holidays]=\"ganttConfig().holidays\"\r\n [enableWBS]=\"true\"\r\n [enableAutoWbsUpdate]=\"true\"\r\n [allowReordering]=\"true\"\r\n (toolbarClick)=\"onToolbarClick($event)\"\r\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\r\n (contextMenuClick)=\"onContextMenuClick($event)\"\r\n (actionBegin)=\"onActionBegin($event)\"\r\n (actionComplete)=\"onActionComplete($event)\"\r\n (cellEdit)=\"onCellEdit($event)\"\r\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\r\n (dataBound)=\"onDataBound()\"\r\n >\r\n <ng-template #tooltipSettingsTaskbar let-data>\r\n <div class=\"px-2 py-1 text-xs\">\r\n <div class=\"font-medium\">{{ data?.title ?? \"-\" }}</div>\r\n <div>\r\n {{ tooltipTranslations().startsOn }}:\r\n {{ data?.startDate ? (data.startDate | mtDateFormat: \"date\") : \"-\" }}\r\n </div>\r\n <div>\r\n {{ tooltipTranslations().endsOn }}:\r\n {{\r\n data?.finishDate ? (data.finishDate | mtDateFormat: \"date\") : \"-\"\r\n }}\r\n </div>\r\n @if (data?.baselineStartDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedStart }}:\r\n {{\r\n data?.baselineStartDate\r\n ? (data.baselineStartDate | mtDateFormat: \"date\")\r\n : \"-\"\r\n }}\r\n </div>\r\n }\r\n @if (data?.baselineEndDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedEnd }}:\r\n {{\r\n data?.baselineEndDate\r\n ? (data.baselineEndDate | mtDateFormat: \"date\")\r\n : \"-\"\r\n }}\r\n </div>\r\n }\r\n <div>\r\n {{ tooltipTranslations().progress }}: {{ data?.progress ?? 0 }}\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #taskbarTemplate let-data>\r\n <mt-task-schedule-taskbar-template\r\n [data]=\"data\"\r\n [langCode]=\"resolvedLangCode()\"\r\n />\r\n </ng-template>\r\n </ejs-gantt>\r\n} @else {\r\n <div class=\"task-schedule-loader\">\r\n <div class=\"task-schedule-loader__spinner\" aria-label=\"Loading\"></div>\r\n </div>\r\n}\r\n", styles: [":host{display:block}:host ::ng-deep .e-headercell .e-headercelldiv{height:auto;display:flex!important}:host ::ng-deep .e-custom-holiday{background-color:#0a0f32}:host ::ng-deep .e-gantt .e-gantt-chart .e-baseline-bar{height:7px!important;border-radius:3px}:host ::ng-deep .e-gantt .e-gantt-chart .e-gantt-child-taskbar-inner-div{height:17px!important}:host ::ng-deep .e-row{cursor:pointer!important}.task-schedule-loader{display:grid;place-items:center;min-height:18rem}.task-schedule-loader__spinner{width:2.25rem;height:2.25rem;border-radius:9999px;border:3px solid rgba(148,163,184,.3);border-top-color:#334155;animation:task-schedule-spin .8s linear infinite}@keyframes task-schedule-spin{to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: GanttModule }, { kind: "component", type: i1$1.GanttComponent, selector: "ejs-gantt", inputs: ["addDialogFields", "allowExcelExport", "allowFiltering", "allowKeyboard", "allowParentDependency", "allowPdfExport", "allowReordering", "allowResizing", "allowRowDragAndDrop", "allowSelection", "allowSorting", "allowTaskbarDragAndDrop", "allowTaskbarOverlap", "allowUnscheduledTasks", "autoCalculateDateScheduling", "autoFocusTasks", "baselineColor", "calendarSettings", "collapseAllParentTasks", "columnMenuItems", "columns", "connectorLineBackground", "connectorLineWidth", "contextMenuItems", "dataSource", "dateFormat", "dayWorkingTime", "disableHtmlEncode", "durationUnit", "editDialogFields", "editSettings", "emptyRecordTemplate", "enableAdaptiveUI", "enableAutoWbsUpdate", "enableContextMenu", "enableCriticalPath", "enableHover", "enableHtmlSanitizer", "enableImmutableMode", "enableMultiTaskbar", "enablePersistence", "enablePredecessorValidation", "enableRtl", "enableTimelineVirtualization", "enableUndoRedo", "enableVirtualMaskRow", "enableVirtualization", "enableWBS", "eventMarkers", "filterSettings", "frozenColumns", "gridLines", "height", "highlightWeekends", "holidays", "includeWeekend", "labelSettings", "loadChildOnDemand", "loadingIndicator", "locale", "milestoneTemplate", "parentTaskbarTemplate", "projectEndDate", "projectStartDate", "query", "readOnly", "renderBaseline", "resourceFields", "resourceIDMapping", "resourceNameMapping", "resources", "rowHeight", "searchSettings", "segmentData", "selectedRowIndex", "selectionSettings", "showColumnMenu", "showInlineNotes", "showOverAllocation", "sortSettings", "splitterSettings", "taskFields", "taskMode", "taskType", "taskbarHeight", "taskbarTemplate", "timelineSettings", "timelineTemplate", "timezone", "toolbar", "tooltipSettings", "treeColumnIndex", "undoRedoActions", "undoRedoStepsCount", "updateOffsetOnTaskbarEdit", "validateManualTasksOnLinking", "viewType", "weekWorkingTime", "width", "workUnit", "workWeek", "zoomingLevels"], outputs: ["actionBegin", "actionComplete", "actionFailure", "beforeDataBound", "beforeExcelExport", "beforePdfExport", "beforeTooltipRender", "cellDeselected", "cellDeselecting", "cellEdit", "cellSave", "cellSelected", "cellSelecting", "collapsed", "collapsing", "columnDrag", "columnDragStart", "columnDrop", "columnMenuClick", "columnMenuOpen", "contextMenuClick", "contextMenuOpen", "created", "dataBound", "dataStateChange", "destroyed", "endEdit", "excelExportComplete", "excelHeaderQueryCellInfo", "excelQueryCellInfo", "expanded", "expanding", "headerCellInfo", "load", "onMouseMove", "onTaskbarClick", "pdfColumnHeaderQueryCellInfo", "pdfExportComplete", "pdfQueryCellInfo", "pdfQueryTaskbarInfo", "pdfQueryTimelineCellInfo", "queryCellInfo", "queryTaskbarInfo", "recordDoubleClick", "resizeStart", "resizeStop", "resizing", "rowDataBound", "rowDeselected", "rowDeselecting", "rowDrag", "rowDragStart", "rowDragStartHelper", "rowDrop", "rowSelected", "rowSelecting", "splitterResizeStart", "splitterResized", "splitterResizing", "taskbarEdited", "taskbarEditing", "toolbarClick", "dataSourceChange"] }, { kind: "component", type: TaskScheduleTaskbarTemplate, selector: "mt-task-schedule-taskbar-template", inputs: ["data", "langCode"] }, { kind: "pipe", type: MTDateFormatPipe, name: "mtDateFormat" }] });
|
|
3895
4102
|
}
|
|
3896
4103
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskSchedule, decorators: [{
|
|
3897
4104
|
type: Component,
|
|
3898
|
-
args: [{ selector: 'mt-task-schedule', standalone: true, imports: [
|
|
4105
|
+
args: [{ selector: 'mt-task-schedule', standalone: true, imports: [
|
|
4106
|
+
CommonModule,
|
|
4107
|
+
GanttModule,
|
|
4108
|
+
MTDateFormatPipe,
|
|
4109
|
+
TaskScheduleTaskbarTemplate,
|
|
4110
|
+
], host: { class: 'block' }, providers: [
|
|
3899
4111
|
DayMarkersService,
|
|
3900
4112
|
EditService,
|
|
3901
4113
|
ExcelExportService,
|
|
@@ -3908,7 +4120,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImpor
|
|
|
3908
4120
|
ToolbarService,
|
|
3909
4121
|
ContextMenuService,
|
|
3910
4122
|
ResizeService,
|
|
3911
|
-
], template: "@if (!loading()) {\r\n <ejs-gantt\r\n #ganttObj\r\n [id]=\"ganttId\"\r\n [enableVirtualization]=\"true\"\r\n [enableTimelineVirtualization]=\"true\"\r\n [enableVirtualMaskRow]=\"false\"\r\n [allowResizing]=\"true\"\r\n [enableRtl]=\"enableRtl()\"\r\n [locale]=\"locale()\"\r\n [height]=\"resolvedHeight()\"\r\n [dataSource]=\"dataSource()\"\r\n [taskFields]=\"ganttConfig().taskFields\"\r\n [columns]=\"ganttConfig().columns\"\r\n [renderBaseline]=\"ganttConfig().renderBaseline\"\r\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\r\n [allowSelection]=\"true\"\r\n [labelSettings]=\"ganttConfig().labelSettings\"\r\n [treeColumnIndex]=\"treeColumnIndex()\"\r\n [workWeek]=\"ganttConfig().workWeek\"\r\n [highlightWeekends]=\"true\"\r\n [enablePredecessorValidation]=\"true\"\r\n [splitterSettings]=\"ganttConfig().splitterSettings\"\r\n [gridLines]=\"ganttConfig().gridLines\"\r\n [toolbar]=\"ganttConfig().toolbar\"\r\n [allowExcelExport]=\"ganttConfig().allowExcelExport\"\r\n [allowPdfExport]=\"ganttConfig().allowPdfExport\"\r\n [enableContextMenu]=\"ganttConfig().enableContextMenu\"\r\n [contextMenuItems]=\"ganttConfig().contextMenuItems\"\r\n [timelineSettings]=\"ganttConfig().timelineSettings\"\r\n [editSettings]=\"ganttConfig().editSettings\"\r\n [allowRowDragAndDrop]=\"ganttConfig().allowRowDragAndDrop\"\r\n [addDialogFields]=\"ganttConfig().addDialogFields\"\r\n [editDialogFields]=\"ganttConfig().editDialogFields\"\r\n [resourceFields]=\"ganttConfig().resourceFields\"\r\n [resources]=\"ganttConfig().resources\"\r\n [viewType]=\"ganttConfig().viewType\"\r\n [showOverAllocation]=\"ganttConfig().showOverAllocation\"\r\n [allowUnscheduledTasks]=\"ganttConfig().allowUnscheduledTasks\"\r\n [eventMarkers]=\"ganttConfig().eventMarkers\"\r\n [projectStartDate]=\"ganttConfig().projectStartDate\"\r\n [projectEndDate]=\"ganttConfig().projectEndDate\"\r\n [autoCalculateDateScheduling]=\"false\"\r\n [dateFormat]=\"resolvedDateFormat()\"\r\n [allowSorting]=\"true\"\r\n [holidays]=\"ganttConfig().holidays\"\r\n [enableWBS]=\"true\"\r\n [enableAutoWbsUpdate]=\"true\"\r\n [allowReordering]=\"true\"\r\n (toolbarClick)=\"onToolbarClick($event)\"\r\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\r\n (contextMenuClick)=\"onContextMenuClick($event)\"\r\n (actionBegin)=\"onActionBegin($event)\"\r\n (actionComplete)=\"onActionComplete($event)\"\r\n (cellEdit)=\"onCellEdit($event)\"\r\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\r\n (dataBound)=\"onDataBound()\"\r\n >\r\n <ng-template #tooltipSettingsTaskbar let-data>\r\n <div class=\"px-2 py-1 text-xs\">\r\n <div class=\"font-medium\">{{ data?.title ?? \"-\" }}</div>\r\n <div>\r\n {{ tooltipTranslations().startsOn }}:\r\n {{ data?.startDate
|
|
4123
|
+
], template: "@if (!loading()) {\r\n <ejs-gantt\r\n #ganttObj\r\n [id]=\"ganttId\"\r\n [enableVirtualization]=\"true\"\r\n [enableTimelineVirtualization]=\"true\"\r\n [enableVirtualMaskRow]=\"false\"\r\n [allowResizing]=\"true\"\r\n [enableRtl]=\"enableRtl()\"\r\n [locale]=\"locale()\"\r\n [height]=\"resolvedHeight()\"\r\n [dataSource]=\"dataSource()\"\r\n [taskFields]=\"ganttConfig().taskFields\"\r\n [columns]=\"ganttConfig().columns\"\r\n [renderBaseline]=\"ganttConfig().renderBaseline\"\r\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\r\n [allowSelection]=\"true\"\r\n [labelSettings]=\"ganttConfig().labelSettings\"\r\n [treeColumnIndex]=\"treeColumnIndex()\"\r\n [workWeek]=\"ganttConfig().workWeek\"\r\n [highlightWeekends]=\"true\"\r\n [enablePredecessorValidation]=\"true\"\r\n [splitterSettings]=\"ganttConfig().splitterSettings\"\r\n [gridLines]=\"ganttConfig().gridLines\"\r\n [toolbar]=\"ganttConfig().toolbar\"\r\n [allowExcelExport]=\"ganttConfig().allowExcelExport\"\r\n [allowPdfExport]=\"ganttConfig().allowPdfExport\"\r\n [enableContextMenu]=\"ganttConfig().enableContextMenu\"\r\n [contextMenuItems]=\"ganttConfig().contextMenuItems\"\r\n [timelineSettings]=\"ganttConfig().timelineSettings\"\r\n [editSettings]=\"ganttConfig().editSettings\"\r\n [allowRowDragAndDrop]=\"ganttConfig().allowRowDragAndDrop\"\r\n [addDialogFields]=\"ganttConfig().addDialogFields\"\r\n [editDialogFields]=\"ganttConfig().editDialogFields\"\r\n [resourceFields]=\"ganttConfig().resourceFields\"\r\n [resources]=\"ganttConfig().resources\"\r\n [viewType]=\"ganttConfig().viewType\"\r\n [showOverAllocation]=\"ganttConfig().showOverAllocation\"\r\n [allowUnscheduledTasks]=\"ganttConfig().allowUnscheduledTasks\"\r\n [eventMarkers]=\"ganttConfig().eventMarkers\"\r\n [projectStartDate]=\"ganttConfig().projectStartDate\"\r\n [projectEndDate]=\"ganttConfig().projectEndDate\"\r\n [autoCalculateDateScheduling]=\"false\"\r\n [dateFormat]=\"resolvedDateFormat()\"\r\n [allowSorting]=\"true\"\r\n [holidays]=\"ganttConfig().holidays\"\r\n [enableWBS]=\"true\"\r\n [enableAutoWbsUpdate]=\"true\"\r\n [allowReordering]=\"true\"\r\n (toolbarClick)=\"onToolbarClick($event)\"\r\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\r\n (contextMenuClick)=\"onContextMenuClick($event)\"\r\n (actionBegin)=\"onActionBegin($event)\"\r\n (actionComplete)=\"onActionComplete($event)\"\r\n (cellEdit)=\"onCellEdit($event)\"\r\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\r\n (dataBound)=\"onDataBound()\"\r\n >\r\n <ng-template #tooltipSettingsTaskbar let-data>\r\n <div class=\"px-2 py-1 text-xs\">\r\n <div class=\"font-medium\">{{ data?.title ?? \"-\" }}</div>\r\n <div>\r\n {{ tooltipTranslations().startsOn }}:\r\n {{ data?.startDate ? (data.startDate | mtDateFormat: \"date\") : \"-\" }}\r\n </div>\r\n <div>\r\n {{ tooltipTranslations().endsOn }}:\r\n {{\r\n data?.finishDate ? (data.finishDate | mtDateFormat: \"date\") : \"-\"\r\n }}\r\n </div>\r\n @if (data?.baselineStartDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedStart }}:\r\n {{\r\n data?.baselineStartDate\r\n ? (data.baselineStartDate | mtDateFormat: \"date\")\r\n : \"-\"\r\n }}\r\n </div>\r\n }\r\n @if (data?.baselineEndDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedEnd }}:\r\n {{\r\n data?.baselineEndDate\r\n ? (data.baselineEndDate | mtDateFormat: \"date\")\r\n : \"-\"\r\n }}\r\n </div>\r\n }\r\n <div>\r\n {{ tooltipTranslations().progress }}: {{ data?.progress ?? 0 }}\r\n </div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #taskbarTemplate let-data>\r\n <mt-task-schedule-taskbar-template\r\n [data]=\"data\"\r\n [langCode]=\"resolvedLangCode()\"\r\n />\r\n </ng-template>\r\n </ejs-gantt>\r\n} @else {\r\n <div class=\"task-schedule-loader\">\r\n <div class=\"task-schedule-loader__spinner\" aria-label=\"Loading\"></div>\r\n </div>\r\n}\r\n", styles: [":host{display:block}:host ::ng-deep .e-headercell .e-headercelldiv{height:auto;display:flex!important}:host ::ng-deep .e-custom-holiday{background-color:#0a0f32}:host ::ng-deep .e-gantt .e-gantt-chart .e-baseline-bar{height:7px!important;border-radius:3px}:host ::ng-deep .e-gantt .e-gantt-chart .e-gantt-child-taskbar-inner-div{height:17px!important}:host ::ng-deep .e-row{cursor:pointer!important}.task-schedule-loader{display:grid;place-items:center;min-height:18rem}.task-schedule-loader__spinner{width:2.25rem;height:2.25rem;border-radius:9999px;border:3px solid rgba(148,163,184,.3);border-top-color:#334155;animation:task-schedule-spin .8s linear infinite}@keyframes task-schedule-spin{to{transform:rotate(360deg)}}\n"] }]
|
|
3912
4124
|
}], propDecorators: { ganttObj: [{
|
|
3913
4125
|
type: ViewChild,
|
|
3914
4126
|
args: ['ganttObj']
|