@masterteam/task-schedule 0.0.2 → 0.0.3
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.
|
@@ -74,6 +74,30 @@ function normalizeTaskScheduleModelType(modelType) {
|
|
|
74
74
|
|
|
75
75
|
const TASK_SCHEDULE_DATA_ADAPTER = new InjectionToken('TASK_SCHEDULE_DATA_ADAPTER');
|
|
76
76
|
const DEFAULT_CUSTOM_PROPERTIES = [];
|
|
77
|
+
const SCHEDULE_NATIVE_KEYS = new Set([
|
|
78
|
+
'name',
|
|
79
|
+
'status',
|
|
80
|
+
'plannedStart',
|
|
81
|
+
'plannedFinish',
|
|
82
|
+
'actualStart',
|
|
83
|
+
'actualFinish',
|
|
84
|
+
'baselineStart',
|
|
85
|
+
'baselineFinish',
|
|
86
|
+
'duration',
|
|
87
|
+
'progress',
|
|
88
|
+
'predecessor',
|
|
89
|
+
'predecessors',
|
|
90
|
+
'assignedTo',
|
|
91
|
+
'resources',
|
|
92
|
+
'order',
|
|
93
|
+
'parentId',
|
|
94
|
+
'phaseGate',
|
|
95
|
+
'criticalPath',
|
|
96
|
+
'type',
|
|
97
|
+
'details',
|
|
98
|
+
'id',
|
|
99
|
+
'levelDataId',
|
|
100
|
+
]);
|
|
77
101
|
class TaskScheduleBackendAdapter {
|
|
78
102
|
http = inject(HttpClient, { optional: true });
|
|
79
103
|
load(modelType, context) {
|
|
@@ -81,21 +105,11 @@ class TaskScheduleBackendAdapter {
|
|
|
81
105
|
return this.backendError('TaskScheduleBackendAdapter requires HttpClient. Configure provideHttpClient() in the host app.');
|
|
82
106
|
}
|
|
83
107
|
const normalizedModel = normalizeTaskScheduleModelType(modelType);
|
|
84
|
-
const treeRouteTemplate = this.resolveTreeRouteTemplate(context, normalizedModel);
|
|
85
108
|
const levelId = this.readId(context.levelId);
|
|
86
109
|
if (!levelId) {
|
|
87
110
|
return this.backendError('TaskSchedule context requires levelId for backend calls.');
|
|
88
111
|
}
|
|
89
|
-
|
|
90
|
-
if (!treeRouteParams) {
|
|
91
|
-
return this.backendError('TaskSchedule context is missing required identifiers for the selected schedule endpoint.');
|
|
92
|
-
}
|
|
93
|
-
const treeUrl = this.resolveApiUrl(context, treeRouteTemplate, treeRouteParams);
|
|
94
|
-
return this.http
|
|
95
|
-
.get(treeUrl, {
|
|
96
|
-
headers: this.readHeaders(context),
|
|
97
|
-
})
|
|
98
|
-
.pipe(map((response) => this.unwrapResponse(response, 'Failed to load schedule tree.')), map((payload) => ({
|
|
112
|
+
return this.resolveReadPayload(context, normalizedModel).pipe(map((payload) => ({
|
|
99
113
|
payload,
|
|
100
114
|
rows: this.extractTaskArray(payload),
|
|
101
115
|
})), map(({ payload, rows }) => ({
|
|
@@ -153,6 +167,218 @@ class TaskScheduleBackendAdapter {
|
|
|
153
167
|
}));
|
|
154
168
|
}));
|
|
155
169
|
}
|
|
170
|
+
resolveReadPayload(context, modelType) {
|
|
171
|
+
if (modelType === 'phaseGate') {
|
|
172
|
+
return this.loadLegacyPhaseGatePayload(context);
|
|
173
|
+
}
|
|
174
|
+
if (modelType === 'resources') {
|
|
175
|
+
return this.loadScheduleUtilityPayload(context, 'levels/{levelId}/{levelDataId}/schedule/by-resource', 'Failed to load schedule resources.');
|
|
176
|
+
}
|
|
177
|
+
if (modelType === 'unscheduled') {
|
|
178
|
+
return this.loadScheduleUtilityPayload(context, 'levels/{levelId}/{levelDataId}/schedule/unscheduled', 'Failed to load unscheduled schedule items.');
|
|
179
|
+
}
|
|
180
|
+
if (modelType === 'baseline') {
|
|
181
|
+
return this.loadScheduleUtilityPayload(context, 'levels/{levelId}/{levelDataId}/schedule/baselines/latest', 'Failed to load schedule baseline.');
|
|
182
|
+
}
|
|
183
|
+
return this.loadScheduleQueryPayload(context);
|
|
184
|
+
}
|
|
185
|
+
loadScheduleQueryPayload(context) {
|
|
186
|
+
if (!this.http) {
|
|
187
|
+
return this.backendError('Task schedule query loading requires HttpClient.');
|
|
188
|
+
}
|
|
189
|
+
const levelId = this.readId(context.levelId);
|
|
190
|
+
const levelDataId = this.readId(context.levelDataId);
|
|
191
|
+
if (!levelId || !levelDataId) {
|
|
192
|
+
return this.backendError('TaskSchedule context requires levelId and levelDataId for schedule reads.');
|
|
193
|
+
}
|
|
194
|
+
const endpoint = this.resolveApiUrl(context, 'levels/{levelId}/{levelDataId}/schedule/query', {
|
|
195
|
+
levelId,
|
|
196
|
+
levelDataId,
|
|
197
|
+
});
|
|
198
|
+
return this.http
|
|
199
|
+
.post(endpoint, {
|
|
200
|
+
projection: 'Tree',
|
|
201
|
+
}, {
|
|
202
|
+
headers: this.readHeaders(context),
|
|
203
|
+
})
|
|
204
|
+
.pipe(map((response) => this.unwrapResponse(response, 'Failed to load schedule records.')), map((data) => this.composeFetchPayload(data)));
|
|
205
|
+
}
|
|
206
|
+
loadScheduleUtilityPayload(context, template, fallbackMessage) {
|
|
207
|
+
if (!this.http) {
|
|
208
|
+
return this.backendError(fallbackMessage);
|
|
209
|
+
}
|
|
210
|
+
const levelId = this.readId(context.levelId);
|
|
211
|
+
const levelDataId = this.readId(context.levelDataId);
|
|
212
|
+
if (!levelId || !levelDataId) {
|
|
213
|
+
return this.backendError('TaskSchedule context requires levelId and levelDataId for schedule utility reads.');
|
|
214
|
+
}
|
|
215
|
+
const url = this.resolveApiUrl(context, template, {
|
|
216
|
+
levelId,
|
|
217
|
+
levelDataId,
|
|
218
|
+
});
|
|
219
|
+
return this.http
|
|
220
|
+
.get(url, {
|
|
221
|
+
headers: this.readHeaders(context),
|
|
222
|
+
})
|
|
223
|
+
.pipe(map((response) => this.unwrapResponse(response, fallbackMessage)));
|
|
224
|
+
}
|
|
225
|
+
loadLegacyPhaseGatePayload(context) {
|
|
226
|
+
if (!this.http) {
|
|
227
|
+
return this.backendError('Failed to load phase gate schedule tree.');
|
|
228
|
+
}
|
|
229
|
+
const treeRouteTemplate = this.resolveTreeRouteTemplate(context, 'phaseGate');
|
|
230
|
+
const treeRouteParams = this.buildTreeRouteParams(context, treeRouteTemplate);
|
|
231
|
+
if (!treeRouteParams) {
|
|
232
|
+
return this.backendError('TaskSchedule context is missing required identifiers for phase gate mode.');
|
|
233
|
+
}
|
|
234
|
+
const treeUrl = this.resolveApiUrl(context, treeRouteTemplate, treeRouteParams);
|
|
235
|
+
return this.http
|
|
236
|
+
.get(treeUrl, {
|
|
237
|
+
headers: this.readHeaders(context),
|
|
238
|
+
})
|
|
239
|
+
.pipe(map((response) => this.unwrapResponse(response, 'Failed to load phase gate schedule tree.')));
|
|
240
|
+
}
|
|
241
|
+
composeFetchPayload(data) {
|
|
242
|
+
const schemaMap = this.toFetchSchemaMap(data.schemas ?? []);
|
|
243
|
+
const tasks = this.mapFetchRecords(this.resolveFetchRootRecords(data.records ?? [], data.projectionMeta?.rootIds ?? []), schemaMap);
|
|
244
|
+
const customProperties = this.mergeFetchCustomProperties(this.mapFetchCustomProperties(data.catalog?.properties ?? []));
|
|
245
|
+
return {
|
|
246
|
+
tasks,
|
|
247
|
+
customProperties,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
resolveFetchRootRecords(records, rootIds) {
|
|
251
|
+
if (!rootIds.length) {
|
|
252
|
+
return records;
|
|
253
|
+
}
|
|
254
|
+
const byId = new Map(records.map((record) => [String(record.id), record]));
|
|
255
|
+
return rootIds
|
|
256
|
+
.map((id) => byId.get(String(id)))
|
|
257
|
+
.filter((record) => record != null);
|
|
258
|
+
}
|
|
259
|
+
toFetchSchemaMap(schemas) {
|
|
260
|
+
return new Map(schemas
|
|
261
|
+
.filter((schema) => this.readId(schema.id) != null)
|
|
262
|
+
.map((schema) => [String(schema.id), schema]));
|
|
263
|
+
}
|
|
264
|
+
mapFetchRecords(records, schemaMap) {
|
|
265
|
+
return records.map((record, index) => this.mapFetchRecord(record, index + 1, schemaMap));
|
|
266
|
+
}
|
|
267
|
+
mapFetchRecord(record, fallbackOrder, schemaMap) {
|
|
268
|
+
const values = record.values ?? {};
|
|
269
|
+
const schema = this.readId(record.schemaId)
|
|
270
|
+
? schemaMap.get(String(record.schemaId))
|
|
271
|
+
: undefined;
|
|
272
|
+
const type = this.readFetchCellDisplay(values['type']) ??
|
|
273
|
+
this.toNullableString(this.readFetchCellValue(values['type'])) ??
|
|
274
|
+
this.toNullableString(schema?.key) ??
|
|
275
|
+
'Task';
|
|
276
|
+
const subtasks = (record.children ?? []).map((child, index) => this.mapFetchRecord(child, index + 1, schemaMap));
|
|
277
|
+
return {
|
|
278
|
+
id: record.id,
|
|
279
|
+
title: record.name ??
|
|
280
|
+
this.readFetchCellDisplay(values['name']) ??
|
|
281
|
+
`Task ${String(record.id)}`,
|
|
282
|
+
name: record.name ??
|
|
283
|
+
this.readFetchCellDisplay(values['name']) ??
|
|
284
|
+
`Task ${String(record.id)}`,
|
|
285
|
+
startDate: this.readFetchCellValue(values['plannedStart']),
|
|
286
|
+
finishDate: this.readFetchCellValue(values['plannedFinish']),
|
|
287
|
+
baselineStartDate: this.readFetchCellValue(values['baselineStart']),
|
|
288
|
+
baselineEndDate: this.readFetchCellValue(values['baselineFinish']),
|
|
289
|
+
actualStartDate: this.readFetchCellValue(values['actualStart']),
|
|
290
|
+
actualFinishDate: this.readFetchCellValue(values['actualFinish']),
|
|
291
|
+
predecessor: this.readFetchCellDisplay(values['predecessor']) ??
|
|
292
|
+
this.readFetchCellDisplay(values['predecessors']) ??
|
|
293
|
+
this.toNullableString(this.readFetchCellValue(values['predecessor'])) ??
|
|
294
|
+
this.toNullableString(this.readFetchCellValue(values['predecessors'])),
|
|
295
|
+
duration: this.readFetchCellValue(values['duration']),
|
|
296
|
+
progress: this.readFetchCellValue(values['progress']),
|
|
297
|
+
details: this.readFetchCellDisplay(values['details']) ??
|
|
298
|
+
this.toNullableString(this.readFetchCellValue(values['details'])),
|
|
299
|
+
status: this.readFetchCellValue(values['status']),
|
|
300
|
+
type,
|
|
301
|
+
typeLabel: this.toNullableString(schema?.name) ?? type,
|
|
302
|
+
typeLable: this.toNullableString(schema?.name) ?? type,
|
|
303
|
+
assignedTo: this.readFetchCellValue(values['assignedTo']),
|
|
304
|
+
resources: this.readFetchCellValue(values['resources']),
|
|
305
|
+
phaseGate: this.readFetchCellDisplay(values['phaseGate']) ??
|
|
306
|
+
this.toNullableString(this.readFetchCellValue(values['phaseGate'])),
|
|
307
|
+
criticalPath: Boolean(this.readFetchCellValue(values['criticalPath'])),
|
|
308
|
+
order: this.readFetchOrder(values['order']) ?? fallbackOrder,
|
|
309
|
+
props: this.readFetchCustomProps(values),
|
|
310
|
+
subtasks,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
readFetchCustomProps(values) {
|
|
314
|
+
return Object.entries(values)
|
|
315
|
+
.filter(([key]) => !SCHEDULE_NATIVE_KEYS.has(key))
|
|
316
|
+
.map(([key, cell]) => ({
|
|
317
|
+
id: 0,
|
|
318
|
+
key,
|
|
319
|
+
rawValue: this.readFetchCellRaw(cell),
|
|
320
|
+
value: this.readFetchCellValue(cell),
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
323
|
+
mapFetchCustomProperties(properties) {
|
|
324
|
+
return properties
|
|
325
|
+
.filter((property) => !SCHEDULE_NATIVE_KEYS.has(property.normalizedKey))
|
|
326
|
+
.sort((left, right) => (left.order ?? 0) - (right.order ?? 0))
|
|
327
|
+
.map((property) => ({
|
|
328
|
+
id: property.id,
|
|
329
|
+
key: property.normalizedKey,
|
|
330
|
+
name: property.label,
|
|
331
|
+
viewType: property.viewType,
|
|
332
|
+
normalizedKey: property.normalizedKey,
|
|
333
|
+
isRequired: !!property.isRequired,
|
|
334
|
+
isCalculated: !!property.isCalculated,
|
|
335
|
+
configuration: property.configuration ?? null,
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
mergeFetchCustomProperties(properties) {
|
|
339
|
+
const byKey = new Map();
|
|
340
|
+
properties.forEach((property) => {
|
|
341
|
+
if (!byKey.has(property.key)) {
|
|
342
|
+
byKey.set(property.key, property);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
return Array.from(byKey.values());
|
|
346
|
+
}
|
|
347
|
+
readFetchCellRaw(cell) {
|
|
348
|
+
if (!cell || typeof cell !== 'object') {
|
|
349
|
+
return cell;
|
|
350
|
+
}
|
|
351
|
+
const row = cell;
|
|
352
|
+
if ('raw' in row || 'value' in row || 'display' in row) {
|
|
353
|
+
return row['raw'] ?? row['value'] ?? row['display'] ?? null;
|
|
354
|
+
}
|
|
355
|
+
return cell;
|
|
356
|
+
}
|
|
357
|
+
readFetchCellValue(cell) {
|
|
358
|
+
if (!cell || typeof cell !== 'object') {
|
|
359
|
+
return cell;
|
|
360
|
+
}
|
|
361
|
+
const row = cell;
|
|
362
|
+
if ('raw' in row || 'value' in row || 'display' in row) {
|
|
363
|
+
return row['value'] ?? row['raw'] ?? row['display'] ?? null;
|
|
364
|
+
}
|
|
365
|
+
return cell;
|
|
366
|
+
}
|
|
367
|
+
readFetchCellDisplay(cell) {
|
|
368
|
+
if (!cell || typeof cell !== 'object') {
|
|
369
|
+
return this.toNullableString(cell);
|
|
370
|
+
}
|
|
371
|
+
const row = cell;
|
|
372
|
+
if ('display' in row || 'value' in row || 'raw' in row) {
|
|
373
|
+
return (this.toNullableString(row['display']) ??
|
|
374
|
+
this.toNullableString(row['value']) ??
|
|
375
|
+
this.toNullableString(row['raw']));
|
|
376
|
+
}
|
|
377
|
+
return this.toNullableString(cell);
|
|
378
|
+
}
|
|
379
|
+
readFetchOrder(cell) {
|
|
380
|
+
return this.toNullableNumber(this.readFetchCellValue(cell));
|
|
381
|
+
}
|
|
156
382
|
createTask(context, payload) {
|
|
157
383
|
if (!this.http) {
|
|
158
384
|
return this.backendError('Task create requires HttpClient.');
|
|
@@ -490,60 +716,16 @@ class TaskScheduleBackendAdapter {
|
|
|
490
716
|
null);
|
|
491
717
|
}))), map((view) => this.mapScheduleColumns(view?.columns ?? [], context.langCode ?? 'en')));
|
|
492
718
|
}
|
|
493
|
-
resolveTreeRouteTemplate(context,
|
|
494
|
-
const
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
baseline: 'scheduleTreeBaseline',
|
|
498
|
-
criticalPath: 'scheduleTreeCriticalPath',
|
|
499
|
-
resources: 'scheduleTreeResources',
|
|
500
|
-
unscheduled: 'scheduleTreeUnscheduled',
|
|
501
|
-
phaseGate: 'scheduleTreePhaseGate',
|
|
502
|
-
custom: 'scheduleTreeCustom',
|
|
503
|
-
};
|
|
504
|
-
const modeSpecificRoute = this.readEndpoint(context.endpoints, modeEndpointKeyByModel[modelType]);
|
|
505
|
-
if (modeSpecificRoute) {
|
|
506
|
-
return modeSpecificRoute;
|
|
719
|
+
resolveTreeRouteTemplate(context, _modelType) {
|
|
720
|
+
const phaseGateRoute = this.readEndpoint(context.endpoints, 'scheduleTreePhaseGate');
|
|
721
|
+
if (phaseGateRoute) {
|
|
722
|
+
return phaseGateRoute;
|
|
507
723
|
}
|
|
508
724
|
const customTreeRoute = this.readEndpoint(context.endpoints, 'scheduleTree');
|
|
509
725
|
if (customTreeRoute) {
|
|
510
726
|
return customTreeRoute;
|
|
511
727
|
}
|
|
512
|
-
|
|
513
|
-
if (levelDataId) {
|
|
514
|
-
if (modelType === 'unscheduled') {
|
|
515
|
-
return 'levels/{levelId}/{levelDataId}/schedule/unscheduled';
|
|
516
|
-
}
|
|
517
|
-
if (modelType === 'phaseGate') {
|
|
518
|
-
return 'levels/{levelId}/{levelDataId}/schedule/tree?renderMode=PhaseGate';
|
|
519
|
-
}
|
|
520
|
-
if (modelType === 'resources') {
|
|
521
|
-
return 'levels/{levelId}/{levelDataId}/schedule/by-resource';
|
|
522
|
-
}
|
|
523
|
-
return 'levels/{levelId}/{levelDataId}/schedule/tree';
|
|
524
|
-
}
|
|
525
|
-
if (this.readId(context.schemaId)) {
|
|
526
|
-
if (modelType === 'baseline') {
|
|
527
|
-
return 'tasks/{levelId}/GetAllBaseLine';
|
|
528
|
-
}
|
|
529
|
-
if (modelType === 'unscheduled') {
|
|
530
|
-
return 'tasks/{levelId}/unscheduled';
|
|
531
|
-
}
|
|
532
|
-
if (modelType === 'phaseGate') {
|
|
533
|
-
return 'tasks/{levelId}/GetAll?RenderMode=PhaseGate';
|
|
534
|
-
}
|
|
535
|
-
return 'tasks/{levelId}/GetAll';
|
|
536
|
-
}
|
|
537
|
-
if (modelType === 'baseline') {
|
|
538
|
-
return 'tasks/{levelId}/GetAllBaseLine';
|
|
539
|
-
}
|
|
540
|
-
if (modelType === 'unscheduled') {
|
|
541
|
-
return 'tasks/{levelId}/unscheduled';
|
|
542
|
-
}
|
|
543
|
-
if (modelType === 'phaseGate') {
|
|
544
|
-
return 'tasks/{levelId}/GetAll?RenderMode=PhaseGate';
|
|
545
|
-
}
|
|
546
|
-
return 'tasks/{levelId}/GetAll';
|
|
728
|
+
return 'levels/{levelId}/{levelDataId}/schedule/tree?renderMode=PhaseGate';
|
|
547
729
|
}
|
|
548
730
|
buildTreeRouteParams(context, treeRouteTemplate) {
|
|
549
731
|
const levelId = this.readId(context.levelId);
|
|
@@ -2208,14 +2390,7 @@ class TaskSchedule {
|
|
|
2208
2390
|
operationSub = new Subscription();
|
|
2209
2391
|
contextAddTask = signal('', ...(ngDevMode ? [{ debugName: "contextAddTask" }] : []));
|
|
2210
2392
|
customProperties = signal([], ...(ngDevMode ? [{ debugName: "customProperties" }] : []));
|
|
2211
|
-
modelType = input('default', ...(ngDevMode ? [{ debugName: "modelType" }] : []));
|
|
2212
2393
|
context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
2213
|
-
dateFormat = input('dd/MM/yyyy', ...(ngDevMode ? [{ debugName: "dateFormat" }] : []));
|
|
2214
|
-
height = input('760px', ...(ngDevMode ? [{ debugName: "height" }] : []));
|
|
2215
|
-
langCode = input(null, ...(ngDevMode ? [{ debugName: "langCode" }] : []));
|
|
2216
|
-
pdfFontData = input(null, ...(ngDevMode ? [{ debugName: "pdfFontData" }] : []));
|
|
2217
|
-
pdfRtlFontData = input(null, ...(ngDevMode ? [{ debugName: "pdfRtlFontData" }] : []));
|
|
2218
|
-
pdfFontSize = input(11, ...(ngDevMode ? [{ debugName: "pdfFontSize" }] : []));
|
|
2219
2394
|
toolbarAction = output();
|
|
2220
2395
|
actionBegin = output();
|
|
2221
2396
|
actionCompleted = output();
|
|
@@ -2226,8 +2401,11 @@ class TaskSchedule {
|
|
|
2226
2401
|
dataSource = signal([], ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
|
|
2227
2402
|
ganttConfig = signal(createGanttConfig('default', EMPTY_RESULT, 'dd/MM/yyyy', 'en'), ...(ngDevMode ? [{ debugName: "ganttConfig" }] : []));
|
|
2228
2403
|
ganttId = `mtTaskScheduleGantt-${Math.random().toString(36).slice(2, 10)}`;
|
|
2229
|
-
|
|
2230
|
-
|
|
2404
|
+
resolvedModelTypeInput = computed(() => this.context()?.modelType ?? 'default', ...(ngDevMode ? [{ debugName: "resolvedModelTypeInput" }] : []));
|
|
2405
|
+
resolvedDateFormat = computed(() => this.context()?.dateFormat ?? 'dd/MM/yyyy', ...(ngDevMode ? [{ debugName: "resolvedDateFormat" }] : []));
|
|
2406
|
+
resolvedHeight = computed(() => this.context()?.height ?? '760px', ...(ngDevMode ? [{ debugName: "resolvedHeight" }] : []));
|
|
2407
|
+
resolvedModelType = computed(() => normalizeTaskScheduleModelType(this.resolvedModelTypeInput()), ...(ngDevMode ? [{ debugName: "resolvedModelType" }] : []));
|
|
2408
|
+
resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
|
|
2231
2409
|
isEditMode = computed(() => this.resolvedModelType() === 'edit', ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
|
|
2232
2410
|
editTaskTypes = computed(() => resolveEditTaskTypes(this.resolvedLangCode()), ...(ngDevMode ? [{ debugName: "editTaskTypes" }] : []));
|
|
2233
2411
|
enableRtl = computed(() => this.resolvedLangCode() === 'ar' ||
|
|
@@ -2255,7 +2433,7 @@ class TaskSchedule {
|
|
|
2255
2433
|
return;
|
|
2256
2434
|
}
|
|
2257
2435
|
const langCode = this.resolvedLangCode();
|
|
2258
|
-
this.loadSchedule(this.
|
|
2436
|
+
this.loadSchedule(this.resolvedModelTypeInput(), context, this.resolvedDateFormat(), langCode);
|
|
2259
2437
|
}, { ...(ngDevMode ? { debugName: "loadEffect" } : {}), injector: this.injector });
|
|
2260
2438
|
const refreshSub = this.queueService.refreshTasks$.subscribe(() => {
|
|
2261
2439
|
this.reloadSchedule();
|
|
@@ -2339,7 +2517,7 @@ class TaskSchedule {
|
|
|
2339
2517
|
onActionComplete(args) {
|
|
2340
2518
|
const context = this.context();
|
|
2341
2519
|
if (context) {
|
|
2342
|
-
this.queueService.reorderColumn(args, this.
|
|
2520
|
+
this.queueService.reorderColumn(args, this.resolvedModelTypeInput(), context);
|
|
2343
2521
|
}
|
|
2344
2522
|
if (this.isEditMode()) {
|
|
2345
2523
|
if (args?.requestType === 'openEditDialog' ||
|
|
@@ -2443,7 +2621,7 @@ class TaskSchedule {
|
|
|
2443
2621
|
dependsOn: property.dependsOn,
|
|
2444
2622
|
};
|
|
2445
2623
|
if (property.viewType === 'Date') {
|
|
2446
|
-
column['format'] = { type: 'date', format: this.
|
|
2624
|
+
column['format'] = { type: 'date', format: this.resolvedDateFormat() };
|
|
2447
2625
|
column['type'] = 'date';
|
|
2448
2626
|
}
|
|
2449
2627
|
if (property.viewType === 'Lookup') {
|
|
@@ -2714,7 +2892,7 @@ class TaskSchedule {
|
|
|
2714
2892
|
if (!context) {
|
|
2715
2893
|
return;
|
|
2716
2894
|
}
|
|
2717
|
-
this.loadSchedule(this.
|
|
2895
|
+
this.loadSchedule(this.resolvedModelTypeInput(), context, this.resolvedDateFormat(), this.resolvedLangCode());
|
|
2718
2896
|
}
|
|
2719
2897
|
normalizeTasks(tasks, customProps) {
|
|
2720
2898
|
return [...tasks]
|
|
@@ -3041,15 +3219,10 @@ class TaskSchedule {
|
|
|
3041
3219
|
resolvePdfExportFont() {
|
|
3042
3220
|
const contextFonts = this.context()?.pdfFonts;
|
|
3043
3221
|
const fontData = (this.enableRtl()
|
|
3044
|
-
?
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
: this.pdfFontData() ??
|
|
3049
|
-
contextFonts?.regular ??
|
|
3050
|
-
this.pdfRtlFontData() ??
|
|
3051
|
-
contextFonts?.arabic) ?? TASK_SCHEDULE_DEFAULT_PDF_FONT;
|
|
3052
|
-
return this.createEmbeddedPdfFont(fontData, contextFonts?.size ?? this.pdfFontSize());
|
|
3222
|
+
? contextFonts?.arabic ?? contextFonts?.regular
|
|
3223
|
+
: contextFonts?.regular ?? contextFonts?.arabic) ??
|
|
3224
|
+
TASK_SCHEDULE_DEFAULT_PDF_FONT;
|
|
3225
|
+
return this.createEmbeddedPdfFont(fontData, contextFonts?.size ?? 11);
|
|
3053
3226
|
}
|
|
3054
3227
|
createEmbeddedPdfFont(base64FontData, size) {
|
|
3055
3228
|
try {
|
|
@@ -3186,7 +3359,7 @@ class TaskSchedule {
|
|
|
3186
3359
|
}).format(date);
|
|
3187
3360
|
}
|
|
3188
3361
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskSchedule, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3189
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskSchedule, isStandalone: true, selector: "mt-task-schedule", inputs: {
|
|
3362
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskSchedule, isStandalone: true, selector: "mt-task-schedule", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toolbarAction: "toolbarAction", actionBegin: "actionBegin", actionCompleted: "actionCompleted", loaded: "loaded", loadError: "loadError" }, host: { classAttribute: "block" }, providers: [
|
|
3190
3363
|
DayMarkersService,
|
|
3191
3364
|
EditService,
|
|
3192
3365
|
ExcelExportService,
|
|
@@ -3198,7 +3371,7 @@ class TaskSchedule {
|
|
|
3198
3371
|
ToolbarService,
|
|
3199
3372
|
ContextMenuService,
|
|
3200
3373
|
ResizeService,
|
|
3201
|
-
], 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\"\
|
|
3374
|
+
], 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\"\n [allowResizing]=\"true\"\n [enableRtl]=\"enableRtl()\"\n [locale]=\"locale()\"\n [height]=\"resolvedHeight()\"\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]=\"1\"\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 [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()\"\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 {{ formatDateValue(data?.startDate) }}\r\n </div>\r\n <div>\r\n {{ tooltipTranslations().endsOn }}:\r\n {{ formatDateValue(data?.finishDate) }}\r\n </div>\r\n @if (data?.baselineStartDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedStart }}:\r\n {{ formatDateValue(data?.baselineStartDate) }}\r\n </div>\r\n }\r\n @if (data?.baselineEndDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedEnd }}:\r\n {{ formatDateValue(data?.baselineEndDate) }}\r\n </div>\r\n }\r\n <div>{{ tooltipTranslations().progress }}: {{ data?.progress ?? 0 }}</div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #taskbarTemplate let-data>\r\n <mt-task-schedule-taskbar-template [data]=\"data\" [langCode]=\"resolvedLangCode()\" />\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.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"] }] });
|
|
3202
3375
|
}
|
|
3203
3376
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskSchedule, decorators: [{
|
|
3204
3377
|
type: Component,
|
|
@@ -3214,18 +3387,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
|
|
|
3214
3387
|
ToolbarService,
|
|
3215
3388
|
ContextMenuService,
|
|
3216
3389
|
ResizeService,
|
|
3217
|
-
], 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\"\
|
|
3390
|
+
], 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\"\n [allowResizing]=\"true\"\n [enableRtl]=\"enableRtl()\"\n [locale]=\"locale()\"\n [height]=\"resolvedHeight()\"\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]=\"1\"\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 [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()\"\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 {{ formatDateValue(data?.startDate) }}\r\n </div>\r\n <div>\r\n {{ tooltipTranslations().endsOn }}:\r\n {{ formatDateValue(data?.finishDate) }}\r\n </div>\r\n @if (data?.baselineStartDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedStart }}:\r\n {{ formatDateValue(data?.baselineStartDate) }}\r\n </div>\r\n }\r\n @if (data?.baselineEndDate) {\r\n <div>\r\n {{ tooltipTranslations().plannedEnd }}:\r\n {{ formatDateValue(data?.baselineEndDate) }}\r\n </div>\r\n }\r\n <div>{{ tooltipTranslations().progress }}: {{ data?.progress ?? 0 }}</div>\r\n </div>\r\n </ng-template>\r\n\r\n <ng-template #taskbarTemplate let-data>\r\n <mt-task-schedule-taskbar-template [data]=\"data\" [langCode]=\"resolvedLangCode()\" />\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"] }]
|
|
3218
3391
|
}], propDecorators: { ganttObj: [{
|
|
3219
3392
|
type: ViewChild,
|
|
3220
3393
|
args: ['ganttObj']
|
|
3221
|
-
}],
|
|
3394
|
+
}], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], toolbarAction: [{ type: i0.Output, args: ["toolbarAction"] }], actionBegin: [{ type: i0.Output, args: ["actionBegin"] }], actionCompleted: [{ type: i0.Output, args: ["actionCompleted"] }], loaded: [{ type: i0.Output, args: ["loaded"] }], loadError: [{ type: i0.Output, args: ["loadError"] }] } });
|
|
3222
3395
|
|
|
3223
3396
|
class TaskScheduleImportModal {
|
|
3224
3397
|
adapter = inject(TASK_SCHEDULE_DATA_ADAPTER, { optional: true }) ??
|
|
3225
3398
|
inject(TaskScheduleBackendAdapter);
|
|
3226
3399
|
visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : []));
|
|
3227
3400
|
context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
3228
|
-
langCode = input(null, ...(ngDevMode ? [{ debugName: "langCode" }] : []));
|
|
3229
3401
|
title = input(null, ...(ngDevMode ? [{ debugName: "title" }] : []));
|
|
3230
3402
|
maxRows = input(400, ...(ngDevMode ? [{ debugName: "maxRows" }] : []));
|
|
3231
3403
|
closed = output();
|
|
@@ -3237,7 +3409,7 @@ class TaskScheduleImportModal {
|
|
|
3237
3409
|
loadingApply = signal(false, ...(ngDevMode ? [{ debugName: "loadingApply" }] : []));
|
|
3238
3410
|
importResult = signal(null, ...(ngDevMode ? [{ debugName: "importResult" }] : []));
|
|
3239
3411
|
selectedTaskKeys = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedTaskKeys" }] : []));
|
|
3240
|
-
resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.
|
|
3412
|
+
resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
|
|
3241
3413
|
isRtl = computed(() => this.resolvedLangCode() === 'ar', ...(ngDevMode ? [{ debugName: "isRtl" }] : []));
|
|
3242
3414
|
labels = computed(() => this.resolvedLangCode() === 'ar'
|
|
3243
3415
|
? {
|
|
@@ -3802,12 +3974,12 @@ class TaskScheduleImportModal {
|
|
|
3802
3974
|
this.failed.emit(message);
|
|
3803
3975
|
}
|
|
3804
3976
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleImportModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3805
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleImportModal, isStandalone: true, selector: "mt-task-schedule-import-modal", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", imported: "imported", applied: "applied", failed: "failed" }, ngImport: i0, template: "@if (visible()) {\r\n <div class=\"fixed inset-0 z-[1000] grid place-items-center bg-slate-900/40 p-4\">\r\n <section\r\n class=\"w-full max-w-6xl overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-200\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n >\r\n <header class=\"flex items-center justify-between border-b border-slate-200 px-5 py-4\">\r\n <h2 class=\"text-base font-semibold text-slate-900\">\r\n {{ title() || labels().title }}\r\n </h2>\r\n\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </header>\r\n\r\n <div class=\"space-y-4 p-5\">\r\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 p-4\">\r\n <div class=\"flex flex-wrap items-center gap-3\">\r\n <label\r\n class=\"inline-flex cursor-pointer items-center rounded-lg border border-dashed border-slate-300 bg-white px-4 py-2 text-sm text-slate-700 hover:border-slate-400\"\r\n >\r\n <span>{{ labels().selectFile }}</span>\r\n <input\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n </label>\r\n\r\n <span class=\"max-w-[22rem] truncate text-sm text-slate-500\">\r\n {{ selectedFile()?.name || '-' }}\r\n </span>\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 (importResult(); as result) {\r\n @if (!previewRows().length) {\r\n <div class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\">\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"overflow-hidden rounded-xl border border-slate-200\">\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] border-b border-slate-200 bg-slate-100 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-slate-600\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"allSelected()\"\r\n (change)=\"selectAllRows($any($event.target).checked)\"\r\n />\r\n </label>\r\n <div>{{ labels().task }}</div>\r\n <div>{{ labels().startDate }}</div>\r\n <div>{{ labels().finishDate }}</div>\r\n <div>{{ labels().actualStartDate }}</div>\r\n <div>{{ labels().actualFinishDate }}</div>\r\n <div>{{ labels().assignedTo }}</div>\r\n <div>{{ labels().progress }}</div>\r\n </div>\r\n\r\n <div class=\"max-h-[28rem] overflow-auto\">\r\n @for (row of previewRows(); track trackByRow($index, row)) {\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] items-center gap-x-2 border-b border-slate-100 px-3 py-2 text-sm\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"selectedTaskKeys().has(row.key)\"\r\n (change)=\"toggleRowSelection(row.key, $any($event.target).checked)\"\r\n />\r\n </label>\r\n\r\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"text\"\r\n [value]=\"row.task.title || row.task.name || ''\"\r\n (input)=\"onTaskTitleChanged(row.key, $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.startDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'startDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.finishDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'finishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualStartDate || row.task.actualStart)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualStartDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualFinishDate || row.task.actualFinish)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualFinishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-w-0\">\r\n @if (resourceOptions().length) {\r\n <div class=\"space-y-1\">\r\n <select\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n [value]=\"resolveAssignedValue(row.task)\"\r\n (change)=\"onTaskAssignedToChanged(row.key, $any($event.target).value)\"\r\n >\r\n <option value=\"\">-</option>\r\n @for (option of resourceOptions(); track option.id) {\r\n <option [value]=\"option.id\">{{ option.label }}</option>\r\n }\r\n </select>\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\r\n <div>\r\n <div class=\"space-y-1\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"100\"\r\n [value]=\"normalizeProgress(row.task.progress)\"\r\n (input)=\"onTaskProgressChanged(row.key, $any($event.target).value)\"\r\n />\r\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-slate-500\">{{ labels().rowsLimited }}</p>\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <footer class=\"flex flex-wrap items-center justify-end gap-2 border-t border-slate-200 px-5 py-4\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [outlined]=\"true\"\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 </footer>\r\n </section>\r\n </div>\r\n}\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data"] }] });
|
|
3977
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleImportModal, isStandalone: true, selector: "mt-task-schedule-import-modal", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", imported: "imported", applied: "applied", failed: "failed" }, ngImport: i0, template: "@if (visible()) {\r\n <div class=\"fixed inset-0 z-[1000] grid place-items-center bg-slate-900/40 p-4\">\r\n <section\r\n class=\"w-full max-w-6xl overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-200\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n >\r\n <header class=\"flex items-center justify-between border-b border-slate-200 px-5 py-4\">\r\n <h2 class=\"text-base font-semibold text-slate-900\">\r\n {{ title() || labels().title }}\r\n </h2>\r\n\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </header>\r\n\r\n <div class=\"space-y-4 p-5\">\r\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 p-4\">\r\n <div class=\"flex flex-wrap items-center gap-3\">\r\n <label\r\n class=\"inline-flex cursor-pointer items-center rounded-lg border border-dashed border-slate-300 bg-white px-4 py-2 text-sm text-slate-700 hover:border-slate-400\"\r\n >\r\n <span>{{ labels().selectFile }}</span>\r\n <input\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n </label>\r\n\r\n <span class=\"max-w-[22rem] truncate text-sm text-slate-500\">\r\n {{ selectedFile()?.name || '-' }}\r\n </span>\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 (importResult(); as result) {\r\n @if (!previewRows().length) {\r\n <div class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\">\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"overflow-hidden rounded-xl border border-slate-200\">\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] border-b border-slate-200 bg-slate-100 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-slate-600\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"allSelected()\"\r\n (change)=\"selectAllRows($any($event.target).checked)\"\r\n />\r\n </label>\r\n <div>{{ labels().task }}</div>\r\n <div>{{ labels().startDate }}</div>\r\n <div>{{ labels().finishDate }}</div>\r\n <div>{{ labels().actualStartDate }}</div>\r\n <div>{{ labels().actualFinishDate }}</div>\r\n <div>{{ labels().assignedTo }}</div>\r\n <div>{{ labels().progress }}</div>\r\n </div>\r\n\r\n <div class=\"max-h-[28rem] overflow-auto\">\r\n @for (row of previewRows(); track trackByRow($index, row)) {\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] items-center gap-x-2 border-b border-slate-100 px-3 py-2 text-sm\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"selectedTaskKeys().has(row.key)\"\r\n (change)=\"toggleRowSelection(row.key, $any($event.target).checked)\"\r\n />\r\n </label>\r\n\r\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"text\"\r\n [value]=\"row.task.title || row.task.name || ''\"\r\n (input)=\"onTaskTitleChanged(row.key, $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.startDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'startDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.finishDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'finishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualStartDate || row.task.actualStart)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualStartDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualFinishDate || row.task.actualFinish)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualFinishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-w-0\">\r\n @if (resourceOptions().length) {\r\n <div class=\"space-y-1\">\r\n <select\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n [value]=\"resolveAssignedValue(row.task)\"\r\n (change)=\"onTaskAssignedToChanged(row.key, $any($event.target).value)\"\r\n >\r\n <option value=\"\">-</option>\r\n @for (option of resourceOptions(); track option.id) {\r\n <option [value]=\"option.id\">{{ option.label }}</option>\r\n }\r\n </select>\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\r\n <div>\r\n <div class=\"space-y-1\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"100\"\r\n [value]=\"normalizeProgress(row.task.progress)\"\r\n (input)=\"onTaskProgressChanged(row.key, $any($event.target).value)\"\r\n />\r\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-slate-500\">{{ labels().rowsLimited }}</p>\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <footer class=\"flex flex-wrap items-center justify-end gap-2 border-t border-slate-200 px-5 py-4\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [outlined]=\"true\"\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 </footer>\r\n </section>\r\n </div>\r\n}\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data"] }] });
|
|
3806
3978
|
}
|
|
3807
3979
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleImportModal, decorators: [{
|
|
3808
3980
|
type: Component,
|
|
3809
3981
|
args: [{ selector: 'mt-task-schedule-import-modal', standalone: true, imports: [CommonModule, Button, EntityPreview], template: "@if (visible()) {\r\n <div class=\"fixed inset-0 z-[1000] grid place-items-center bg-slate-900/40 p-4\">\r\n <section\r\n class=\"w-full max-w-6xl overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-200\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n >\r\n <header class=\"flex items-center justify-between border-b border-slate-200 px-5 py-4\">\r\n <h2 class=\"text-base font-semibold text-slate-900\">\r\n {{ title() || labels().title }}\r\n </h2>\r\n\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </header>\r\n\r\n <div class=\"space-y-4 p-5\">\r\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 p-4\">\r\n <div class=\"flex flex-wrap items-center gap-3\">\r\n <label\r\n class=\"inline-flex cursor-pointer items-center rounded-lg border border-dashed border-slate-300 bg-white px-4 py-2 text-sm text-slate-700 hover:border-slate-400\"\r\n >\r\n <span>{{ labels().selectFile }}</span>\r\n <input\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n </label>\r\n\r\n <span class=\"max-w-[22rem] truncate text-sm text-slate-500\">\r\n {{ selectedFile()?.name || '-' }}\r\n </span>\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 (importResult(); as result) {\r\n @if (!previewRows().length) {\r\n <div class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\">\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"overflow-hidden rounded-xl border border-slate-200\">\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] border-b border-slate-200 bg-slate-100 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-slate-600\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"allSelected()\"\r\n (change)=\"selectAllRows($any($event.target).checked)\"\r\n />\r\n </label>\r\n <div>{{ labels().task }}</div>\r\n <div>{{ labels().startDate }}</div>\r\n <div>{{ labels().finishDate }}</div>\r\n <div>{{ labels().actualStartDate }}</div>\r\n <div>{{ labels().actualFinishDate }}</div>\r\n <div>{{ labels().assignedTo }}</div>\r\n <div>{{ labels().progress }}</div>\r\n </div>\r\n\r\n <div class=\"max-h-[28rem] overflow-auto\">\r\n @for (row of previewRows(); track trackByRow($index, row)) {\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] items-center gap-x-2 border-b border-slate-100 px-3 py-2 text-sm\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"selectedTaskKeys().has(row.key)\"\r\n (change)=\"toggleRowSelection(row.key, $any($event.target).checked)\"\r\n />\r\n </label>\r\n\r\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"text\"\r\n [value]=\"row.task.title || row.task.name || ''\"\r\n (input)=\"onTaskTitleChanged(row.key, $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.startDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'startDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.finishDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'finishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualStartDate || row.task.actualStart)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualStartDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualFinishDate || row.task.actualFinish)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualFinishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-w-0\">\r\n @if (resourceOptions().length) {\r\n <div class=\"space-y-1\">\r\n <select\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n [value]=\"resolveAssignedValue(row.task)\"\r\n (change)=\"onTaskAssignedToChanged(row.key, $any($event.target).value)\"\r\n >\r\n <option value=\"\">-</option>\r\n @for (option of resourceOptions(); track option.id) {\r\n <option [value]=\"option.id\">{{ option.label }}</option>\r\n }\r\n </select>\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\r\n <div>\r\n <div class=\"space-y-1\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"100\"\r\n [value]=\"normalizeProgress(row.task.progress)\"\r\n (input)=\"onTaskProgressChanged(row.key, $any($event.target).value)\"\r\n />\r\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-slate-500\">{{ labels().rowsLimited }}</p>\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <footer class=\"flex flex-wrap items-center justify-end gap-2 border-t border-slate-200 px-5 py-4\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [outlined]=\"true\"\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 </footer>\r\n </section>\r\n </div>\r\n}\r\n", styles: [":host{display:block}\n"] }]
|
|
3810
|
-
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }],
|
|
3982
|
+
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], imported: [{ type: i0.Output, args: ["imported"] }], applied: [{ type: i0.Output, args: ["applied"] }], failed: [{ type: i0.Output, args: ["failed"] }] } });
|
|
3811
3983
|
|
|
3812
3984
|
const DEFAULT_MODES = [
|
|
3813
3985
|
{ value: 'default' },
|
|
@@ -3823,16 +3995,6 @@ class TaskScheduleShell {
|
|
|
3823
3995
|
inject(TaskScheduleBackendAdapter);
|
|
3824
3996
|
queueService = inject(TaskScheduleQueueService);
|
|
3825
3997
|
context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : []));
|
|
3826
|
-
langCode = input(null, ...(ngDevMode ? [{ debugName: "langCode" }] : []));
|
|
3827
|
-
dateFormat = input('dd/MM/yyyy', ...(ngDevMode ? [{ debugName: "dateFormat" }] : []));
|
|
3828
|
-
height = input('760px', ...(ngDevMode ? [{ debugName: "height" }] : []));
|
|
3829
|
-
modelType = input('default', ...(ngDevMode ? [{ debugName: "modelType" }] : []));
|
|
3830
|
-
modeOptions = input(null, ...(ngDevMode ? [{ debugName: "modeOptions" }] : []));
|
|
3831
|
-
allowEditMode = input(true, ...(ngDevMode ? [{ debugName: "allowEditMode" }] : []));
|
|
3832
|
-
allowImport = input(true, ...(ngDevMode ? [{ debugName: "allowImport" }] : []));
|
|
3833
|
-
allowSetBaseline = input(true, ...(ngDevMode ? [{ debugName: "allowSetBaseline" }] : []));
|
|
3834
|
-
hasTasks = input(true, ...(ngDevMode ? [{ debugName: "hasTasks" }] : []));
|
|
3835
|
-
baselinePending = input(false, ...(ngDevMode ? [{ debugName: "baselinePending" }] : []));
|
|
3836
3998
|
modeChanged = output();
|
|
3837
3999
|
baselineSet = output();
|
|
3838
4000
|
tasksExported = output();
|
|
@@ -3841,7 +4003,17 @@ class TaskScheduleShell {
|
|
|
3841
4003
|
showImportModal = signal(false, ...(ngDevMode ? [{ debugName: "showImportModal" }] : []));
|
|
3842
4004
|
settingBaseline = signal(false, ...(ngDevMode ? [{ debugName: "settingBaseline" }] : []));
|
|
3843
4005
|
exportingTasks = signal(false, ...(ngDevMode ? [{ debugName: "exportingTasks" }] : []));
|
|
3844
|
-
resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.
|
|
4006
|
+
resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
|
|
4007
|
+
resolvedContext = computed(() => {
|
|
4008
|
+
const context = this.context();
|
|
4009
|
+
if (!context) {
|
|
4010
|
+
return null;
|
|
4011
|
+
}
|
|
4012
|
+
return {
|
|
4013
|
+
...context,
|
|
4014
|
+
modelType: this.currentModelType(),
|
|
4015
|
+
};
|
|
4016
|
+
}, ...(ngDevMode ? [{ debugName: "resolvedContext" }] : []));
|
|
3845
4017
|
labels = computed(() => this.resolvedLangCode() === 'ar'
|
|
3846
4018
|
? {
|
|
3847
4019
|
mode: 'الوضع',
|
|
@@ -3869,29 +4041,30 @@ class TaskScheduleShell {
|
|
|
3869
4041
|
}, ...(ngDevMode ? [{ debugName: "labels" }] : []));
|
|
3870
4042
|
currentModelKey = computed(() => normalizeTaskScheduleModelType(this.currentModelType()), ...(ngDevMode ? [{ debugName: "currentModelKey" }] : []));
|
|
3871
4043
|
resolvedModes = computed(() => {
|
|
3872
|
-
const modes = this.
|
|
4044
|
+
const modes = this.context()?.modeOptions;
|
|
3873
4045
|
const source = modes?.length ? modes : DEFAULT_MODES;
|
|
3874
4046
|
return source
|
|
3875
|
-
.filter((item) => this.
|
|
4047
|
+
.filter((item) => (this.context()?.allowEditMode ?? true) ||
|
|
4048
|
+
normalizeTaskScheduleModelType(item.value) !== 'edit')
|
|
3876
4049
|
.map((item) => ({
|
|
3877
4050
|
value: item.value,
|
|
3878
4051
|
label: item.label || this.resolveModeLabel(item.value),
|
|
3879
4052
|
}));
|
|
3880
4053
|
}, ...(ngDevMode ? [{ debugName: "resolvedModes" }] : []));
|
|
3881
|
-
showSetBaselineAction = computed(() => this.
|
|
4054
|
+
showSetBaselineAction = computed(() => (this.context()?.allowSetBaseline ?? true) &&
|
|
3882
4055
|
(this.currentModelKey() === 'default' || this.currentModelKey() === 'edit'), ...(ngDevMode ? [{ debugName: "showSetBaselineAction" }] : []));
|
|
3883
4056
|
canSetBaselineAction = computed(() => this.showSetBaselineAction() &&
|
|
3884
4057
|
!!this.context() &&
|
|
3885
4058
|
!!this.adapter.setBaseline &&
|
|
3886
4059
|
!this.settingBaseline() &&
|
|
3887
|
-
!this.
|
|
3888
|
-
this.
|
|
3889
|
-
showImportAction = computed(() => this.
|
|
4060
|
+
!(this.context()?.baselinePending ?? false) &&
|
|
4061
|
+
(this.context()?.hasTasks ?? true), ...(ngDevMode ? [{ debugName: "canSetBaselineAction" }] : []));
|
|
4062
|
+
showImportAction = computed(() => (this.context()?.allowImport ?? true) && this.currentModelKey() === 'edit', ...(ngDevMode ? [{ debugName: "showImportAction" }] : []));
|
|
3890
4063
|
canOpenImport = computed(() => this.showImportAction() && !!this.context(), ...(ngDevMode ? [{ debugName: "canOpenImport" }] : []));
|
|
3891
4064
|
canExportTasks = computed(() => !!this.context() && !!this.adapter.exportTasks && !this.exportingTasks(), ...(ngDevMode ? [{ debugName: "canExportTasks" }] : []));
|
|
3892
4065
|
constructor() {
|
|
3893
4066
|
effect(() => {
|
|
3894
|
-
this.currentModelType.set(this.
|
|
4067
|
+
this.currentModelType.set(this.context()?.modelType ?? 'default');
|
|
3895
4068
|
});
|
|
3896
4069
|
}
|
|
3897
4070
|
onModeChange(nextValue) {
|
|
@@ -4018,12 +4191,12 @@ class TaskScheduleShell {
|
|
|
4018
4191
|
this.actionError.emit(message);
|
|
4019
4192
|
}
|
|
4020
4193
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4021
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleShell, isStandalone: true, selector: "mt-task-schedule-shell", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }
|
|
4194
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleShell, isStandalone: true, selector: "mt-task-schedule-shell", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { modeChanged: "modeChanged", baselineSet: "baselineSet", tasksExported: "tasksExported", actionError: "actionError" }, ngImport: i0, template: "<div class=\"task-schedule-shell\" [attr.dir]=\"resolvedLangCode() === 'ar' ? 'rtl' : 'ltr'\">\r\n <header class=\"task-schedule-shell__header\">\r\n <div class=\"task-schedule-shell__mode\">\r\n <label class=\"task-schedule-shell__label\">{{ labels().mode }}</label>\r\n <select\r\n class=\"task-schedule-shell__select\"\r\n [value]=\"currentModelType()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (mode of resolvedModes(); track mode.value) {\r\n <option [value]=\"mode.value\">{{ mode.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n <div class=\"task-schedule-shell__actions\">\r\n @if (showSetBaselineAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canSetBaselineAction()\"\r\n (click)=\"setBaseline()\"\r\n >\r\n {{ baselinePending() ? labels().pending : labels().setBaseline }}\r\n </button>\r\n }\r\n\r\n @if (showImportAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canOpenImport()\"\r\n (click)=\"openImportModal()\"\r\n >\r\n {{ labels().import }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canExportTasks()\"\r\n (click)=\"exportTasks()\"\r\n >\r\n {{ labels().export }}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n <mt-task-schedule\n [context]=\"resolvedContext()\"\n (loadError)=\"onActionError($event)\"\n />\n\n @if (showImportModal()) {\n <mt-task-schedule-import-modal\n [visible]=\"showImportModal()\"\n [context]=\"resolvedContext()\"\n (closed)=\"closeImportModal()\"\n (failed)=\"onActionError($event)\"\n (applied)=\"onImportedTasksApplied()\"\n />\r\n }\r\n</div>\r\n", styles: [":host{display:block}.task-schedule-shell{display:flex;flex-direction:column;gap:12px}.task-schedule-shell__header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px}.task-schedule-shell__mode{display:flex;align-items:center;gap:8px}.task-schedule-shell__label{color:#334155;font-size:13px;font-weight:600}.task-schedule-shell__select{border:1px solid #cbd5e1;border-radius:8px;height:36px;padding:0 10px;min-width:180px;background-color:#fff}.task-schedule-shell__actions{display:flex;flex-wrap:wrap;gap:8px}.task-schedule-shell__btn{border:1px solid #14b8a6;background:#14b8a6;color:#fff;border-radius:999px;padding:7px 14px;font-size:13px;font-weight:600;cursor:pointer}.task-schedule-shell__btn:disabled{opacity:.55;cursor:not-allowed}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TaskSchedule, selector: "mt-task-schedule", inputs: ["context"], outputs: ["toolbarAction", "actionBegin", "actionCompleted", "loaded", "loadError"] }, { kind: "component", type: TaskScheduleImportModal, selector: "mt-task-schedule-import-modal", inputs: ["visible", "context", "title", "maxRows"], outputs: ["closed", "imported", "applied", "failed"] }] });
|
|
4022
4195
|
}
|
|
4023
4196
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleShell, decorators: [{
|
|
4024
4197
|
type: Component,
|
|
4025
|
-
args: [{ selector: 'mt-task-schedule-shell', standalone: true, imports: [CommonModule, TaskSchedule, TaskScheduleImportModal], template: "<div class=\"task-schedule-shell\" [attr.dir]=\"resolvedLangCode() === 'ar' ? 'rtl' : 'ltr'\">\r\n <header class=\"task-schedule-shell__header\">\r\n <div class=\"task-schedule-shell__mode\">\r\n <label class=\"task-schedule-shell__label\">{{ labels().mode }}</label>\r\n <select\r\n class=\"task-schedule-shell__select\"\r\n [value]=\"currentModelType()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (mode of resolvedModes(); track mode.value) {\r\n <option [value]=\"mode.value\">{{ mode.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n <div class=\"task-schedule-shell__actions\">\r\n @if (showSetBaselineAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canSetBaselineAction()\"\r\n (click)=\"setBaseline()\"\r\n >\r\n {{ baselinePending() ? labels().pending : labels().setBaseline }}\r\n </button>\r\n }\r\n\r\n @if (showImportAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canOpenImport()\"\r\n (click)=\"openImportModal()\"\r\n >\r\n {{ labels().import }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canExportTasks()\"\r\n (click)=\"exportTasks()\"\r\n >\r\n {{ labels().export }}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n <mt-task-schedule\
|
|
4026
|
-
}], ctorParameters: () => [], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }],
|
|
4198
|
+
args: [{ selector: 'mt-task-schedule-shell', standalone: true, imports: [CommonModule, TaskSchedule, TaskScheduleImportModal], template: "<div class=\"task-schedule-shell\" [attr.dir]=\"resolvedLangCode() === 'ar' ? 'rtl' : 'ltr'\">\r\n <header class=\"task-schedule-shell__header\">\r\n <div class=\"task-schedule-shell__mode\">\r\n <label class=\"task-schedule-shell__label\">{{ labels().mode }}</label>\r\n <select\r\n class=\"task-schedule-shell__select\"\r\n [value]=\"currentModelType()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (mode of resolvedModes(); track mode.value) {\r\n <option [value]=\"mode.value\">{{ mode.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n <div class=\"task-schedule-shell__actions\">\r\n @if (showSetBaselineAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canSetBaselineAction()\"\r\n (click)=\"setBaseline()\"\r\n >\r\n {{ baselinePending() ? labels().pending : labels().setBaseline }}\r\n </button>\r\n }\r\n\r\n @if (showImportAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canOpenImport()\"\r\n (click)=\"openImportModal()\"\r\n >\r\n {{ labels().import }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canExportTasks()\"\r\n (click)=\"exportTasks()\"\r\n >\r\n {{ labels().export }}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n <mt-task-schedule\n [context]=\"resolvedContext()\"\n (loadError)=\"onActionError($event)\"\n />\n\n @if (showImportModal()) {\n <mt-task-schedule-import-modal\n [visible]=\"showImportModal()\"\n [context]=\"resolvedContext()\"\n (closed)=\"closeImportModal()\"\n (failed)=\"onActionError($event)\"\n (applied)=\"onImportedTasksApplied()\"\n />\r\n }\r\n</div>\r\n", styles: [":host{display:block}.task-schedule-shell{display:flex;flex-direction:column;gap:12px}.task-schedule-shell__header{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px}.task-schedule-shell__mode{display:flex;align-items:center;gap:8px}.task-schedule-shell__label{color:#334155;font-size:13px;font-weight:600}.task-schedule-shell__select{border:1px solid #cbd5e1;border-radius:8px;height:36px;padding:0 10px;min-width:180px;background-color:#fff}.task-schedule-shell__actions{display:flex;flex-wrap:wrap;gap:8px}.task-schedule-shell__btn{border:1px solid #14b8a6;background:#14b8a6;color:#fff;border-radius:999px;padding:7px 14px;font-size:13px;font-weight:600;cursor:pointer}.task-schedule-shell__btn:disabled{opacity:.55;cursor:not-allowed}\n"] }]
|
|
4199
|
+
}], ctorParameters: () => [], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], modeChanged: [{ type: i0.Output, args: ["modeChanged"] }], baselineSet: [{ type: i0.Output, args: ["baselineSet"] }], tasksExported: [{ type: i0.Output, args: ["tasksExported"] }], actionError: [{ type: i0.Output, args: ["actionError"] }] } });
|
|
4027
4200
|
|
|
4028
4201
|
/**
|
|
4029
4202
|
* Generated bundle index. Do not edit.
|