@masterteam/task-schedule 0.0.1 → 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
- const treeRouteParams = this.buildTreeRouteParams(context, treeRouteTemplate);
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,16 +167,231 @@ 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.');
159
385
  }
160
- const endpoint = this.resolveTaskMutationEndpoint(context, 'createTask', 'tasks/{levelId}/create', 'tasks/{schemaId}/{levelId}/create');
386
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'createTask', 'levels/{levelId}/{levelDataId}/schedule', 'tasks/{levelId}/create', 'tasks/{schemaId}/{levelId}/create');
161
387
  if (!endpoint) {
162
388
  return this.backendError('Task create endpoint requires a valid levelId.');
163
389
  }
390
+ const requestBody = endpoint.mode === 'runtime'
391
+ ? this.mapRuntimeMutationPayload(payload)
392
+ : payload;
164
393
  return this.http
165
- .post(endpoint, payload, {
394
+ .post(endpoint.url, requestBody, {
166
395
  headers: this.readHeaders(context, 'task-create'),
167
396
  })
168
397
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to create task.')));
@@ -171,12 +400,15 @@ class TaskScheduleBackendAdapter {
171
400
  if (!this.http) {
172
401
  return this.backendError('Task update requires HttpClient.');
173
402
  }
174
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateTask', 'tasks/{levelId}/update/{taskId}', 'tasks/{schemaId}/{levelId}/update/{taskId}', { taskId: this.readId(taskId) ?? '' });
403
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateTask', 'levels/{levelId}/{levelDataId}/schedule/{taskId}', 'tasks/{levelId}/update/{taskId}', 'tasks/{schemaId}/{levelId}/update/{taskId}', { taskId: this.readId(taskId) ?? '' });
175
404
  if (!endpoint) {
176
405
  return this.backendError('Task update endpoint requires a valid levelId.');
177
406
  }
407
+ const requestBody = endpoint.mode === 'runtime'
408
+ ? this.mapRuntimeMutationPayload(payload)
409
+ : payload;
178
410
  return this.http
179
- .put(endpoint, payload, {
411
+ .put(endpoint.url, requestBody, {
180
412
  headers: this.readHeaders(context, 'task-update'),
181
413
  })
182
414
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task.')));
@@ -185,12 +417,12 @@ class TaskScheduleBackendAdapter {
185
417
  if (!this.http) {
186
418
  return this.backendError('Task delete requires HttpClient.');
187
419
  }
188
- const endpoint = this.resolveTaskMutationEndpoint(context, 'deleteTask', 'tasks/{levelId}/delete/{taskId}', 'tasks/{schemaId}/{levelId}/delete/{taskId}', { taskId: this.readId(taskId) ?? '' });
420
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'deleteTask', 'levels/{levelId}/{levelDataId}/schedule/{taskId}', 'tasks/{levelId}/delete/{taskId}', 'tasks/{schemaId}/{levelId}/delete/{taskId}', { taskId: this.readId(taskId) ?? '' });
189
421
  if (!endpoint) {
190
422
  return this.backendError('Task delete endpoint requires a valid levelId.');
191
423
  }
192
424
  return this.http
193
- .delete(endpoint, {
425
+ .delete(endpoint.url, {
194
426
  headers: this.readHeaders(context, 'task-delete'),
195
427
  })
196
428
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to delete task.')));
@@ -199,12 +431,15 @@ class TaskScheduleBackendAdapter {
199
431
  if (!this.http) {
200
432
  return this.backendError('Task bulk update requires HttpClient.');
201
433
  }
202
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateBulkTasks', 'tasks/{levelId}/bulkUpdate', 'tasks/{schemaId}/{levelId}/bulkUpdate');
434
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateBulkTasks', 'levels/{levelId}/{levelDataId}/schedule/bulk-update', 'tasks/{levelId}/bulkUpdate', 'tasks/{schemaId}/{levelId}/bulkUpdate');
203
435
  if (!endpoint) {
204
436
  return this.backendError('Task bulk update endpoint requires a valid levelId.');
205
437
  }
438
+ const requestBody = endpoint.mode === 'runtime'
439
+ ? this.mapRuntimeBulkUpdatePayload(payload)
440
+ : { data: payload };
206
441
  return this.http
207
- .put(endpoint, { data: payload }, {
442
+ .put(endpoint.url, requestBody, {
208
443
  headers: this.readHeaders(context, 'task-bulk-update'),
209
444
  })
210
445
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update linked tasks.')));
@@ -213,12 +448,12 @@ class TaskScheduleBackendAdapter {
213
448
  if (!this.http) {
214
449
  return this.backendError('Task parent update requires HttpClient.');
215
450
  }
216
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateParent', 'tasks/{levelId}/updateParent/{taskId}', 'tasks/{schemaId}/{levelId}/updateParent/{taskId}', { taskId: this.readId(taskId) ?? '' });
451
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateParent', 'levels/{levelId}/{levelDataId}/schedule/{taskId}', 'tasks/{levelId}/updateParent/{taskId}', 'tasks/{schemaId}/{levelId}/updateParent/{taskId}', { taskId: this.readId(taskId) ?? '' });
217
452
  if (!endpoint) {
218
453
  return this.backendError('Task parent update endpoint requires a valid levelId.');
219
454
  }
220
455
  return this.http
221
- .put(endpoint, { parentId }, {
456
+ .put(endpoint.url, { parentId }, {
222
457
  headers: this.readHeaders(context, 'task-update-parent'),
223
458
  })
224
459
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task parent.')));
@@ -227,12 +462,15 @@ class TaskScheduleBackendAdapter {
227
462
  if (!this.http) {
228
463
  return this.backendError('Task reorder requires HttpClient.');
229
464
  }
230
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateOrder', 'tasks/{levelId}/reorder', 'tasks/{schemaId}/{levelId}/reorder');
465
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateOrder', 'levels/{levelId}/{levelDataId}/schedule/reorder', 'tasks/{levelId}/reorder', 'tasks/{schemaId}/{levelId}/reorder');
231
466
  if (!endpoint) {
232
467
  return this.backendError('Task reorder endpoint requires a valid levelId.');
233
468
  }
469
+ const requestBody = endpoint.mode === 'runtime'
470
+ ? this.mapRuntimeOrderUpdatePayload(payload)
471
+ : { data: payload };
234
472
  return this.http
235
- .put(endpoint, { data: payload }, {
473
+ .put(endpoint.url, requestBody, {
236
474
  headers: this.readHeaders(context, 'task-update-order'),
237
475
  })
238
476
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task order.')));
@@ -241,16 +479,19 @@ class TaskScheduleBackendAdapter {
241
479
  if (!this.http) {
242
480
  return this.backendError('Task progress update requires HttpClient.');
243
481
  }
244
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateProgress', 'tasks/{levelId}/updatePlanningModuleProgress', 'tasks/{schemaId}/{levelId}/updatePlanningModuleProgress');
482
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateProgress', 'levels/{levelId}/{levelDataId}/schedule/{taskId}/progress', 'tasks/{levelId}/updatePlanningModuleProgress', 'tasks/{schemaId}/{levelId}/updatePlanningModuleProgress', { taskId: this.readId(taskId) ?? '' });
245
483
  if (!endpoint) {
246
484
  return this.backendError('Task progress update endpoint requires a valid levelId.');
247
485
  }
486
+ const requestBody = endpoint.mode === 'runtime'
487
+ ? { progress: this.toNullableNumber(payload.progress) ?? 0 }
488
+ : {
489
+ ...payload,
490
+ id: taskId,
491
+ ModuleType: payload.type ?? 'Task',
492
+ };
248
493
  return this.http
249
- .put(endpoint, {
250
- ...payload,
251
- id: taskId,
252
- ModuleType: payload.type ?? 'Task',
253
- }, {
494
+ .put(endpoint.url, requestBody, {
254
495
  headers: this.readHeaders(context, 'task-update-progress'),
255
496
  })
256
497
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task progress.')));
@@ -263,14 +504,21 @@ class TaskScheduleBackendAdapter {
263
504
  if (!levelId) {
264
505
  return this.backendError('Task import endpoint requires a valid levelId.');
265
506
  }
507
+ const levelDataId = this.readId(context.levelDataId);
266
508
  const schemaId = this.readId(context.schemaId);
267
- const endpoint = this.resolveApiUrl(context, this.readEndpoint(context.endpoints, 'importTasks') ?? 'tasks/mmp/import', {
509
+ const customTemplate = this.readEndpoint(context.endpoints, 'importTasks');
510
+ const template = customTemplate ?? 'tasks/mmp/import';
511
+ const endpoint = this.resolveApiUrl(context, template, {
268
512
  levelId,
513
+ ...(levelDataId ? { levelDataId } : {}),
269
514
  ...(schemaId ? { schemaId } : {}),
270
515
  });
271
516
  const formData = new FormData();
272
517
  formData.append('file', file, file.name);
273
518
  formData.append('levelId', levelId);
519
+ if (levelDataId) {
520
+ formData.append('levelDataId', levelDataId);
521
+ }
274
522
  return this.http
275
523
  .post(endpoint, formData, {
276
524
  headers: this.readHeaders(context, 'task-import'),
@@ -280,7 +528,9 @@ class TaskScheduleBackendAdapter {
280
528
  const tasks = rows
281
529
  .map((item, index) => this.mapRuntimeTask(item, index + 1))
282
530
  .filter((item) => !!item);
283
- const payload = raw && typeof raw === 'object' ? raw : {};
531
+ const payload = raw && typeof raw === 'object'
532
+ ? raw
533
+ : {};
284
534
  return {
285
535
  fileName: this.toNullableString(payload['fileName']) ??
286
536
  this.toNullableString(payload['name']) ??
@@ -312,13 +562,19 @@ class TaskScheduleBackendAdapter {
312
562
  if (!levelId) {
313
563
  return this.backendError('Set baseline endpoint requires a valid levelId.');
314
564
  }
565
+ const levelDataId = this.readId(context.levelDataId);
315
566
  const schemaId = this.readId(context.schemaId);
316
- const template = this.readEndpoint(context.endpoints, 'setBaseline') ??
317
- (schemaId
318
- ? 'levels/{schemaId}/{levelId}/tasks/setBaseline'
319
- : 'levels/{levelId}/tasks/setBaseline');
567
+ const customTemplate = this.readEndpoint(context.endpoints, 'setBaseline');
568
+ const template = customTemplate
569
+ ? customTemplate
570
+ : levelDataId
571
+ ? 'levels/{levelId}/{levelDataId}/schedule/baselines'
572
+ : schemaId
573
+ ? 'levels/{schemaId}/{levelId}/tasks/setBaseline'
574
+ : 'levels/{levelId}/tasks/setBaseline';
320
575
  const endpoint = this.resolveApiUrl(context, template, {
321
576
  levelId,
577
+ ...(levelDataId ? { levelDataId } : {}),
322
578
  ...(schemaId ? { schemaId } : {}),
323
579
  });
324
580
  return this.http
@@ -335,10 +591,17 @@ class TaskScheduleBackendAdapter {
335
591
  if (!levelId) {
336
592
  return this.backendError('Task export endpoint requires a valid levelId.');
337
593
  }
594
+ const levelDataId = this.readId(context.levelDataId);
338
595
  const schemaId = this.readId(context.schemaId);
339
- const endpoint = this.resolveApiUrl(context, this.readEndpoint(context.endpoints, 'exportTasks') ??
340
- 'tasks/levels/{levelId}/export', {
596
+ const customTemplate = this.readEndpoint(context.endpoints, 'exportTasks');
597
+ const template = customTemplate
598
+ ? customTemplate
599
+ : levelDataId
600
+ ? 'levels/{levelId}/{levelDataId}/schedule/mpp'
601
+ : 'tasks/levels/{levelId}/export';
602
+ const endpoint = this.resolveApiUrl(context, template, {
341
603
  levelId,
604
+ ...(levelDataId ? { levelDataId } : {}),
342
605
  ...(schemaId ? { schemaId } : {}),
343
606
  });
344
607
  return this.http.get(endpoint, {
@@ -346,6 +609,60 @@ class TaskScheduleBackendAdapter {
346
609
  responseType: 'blob',
347
610
  });
348
611
  }
612
+ mapRuntimeMutationPayload(payload) {
613
+ const mapped = { ...payload };
614
+ if (payload.startDate !== undefined) {
615
+ mapped['plannedStart'] = payload.startDate;
616
+ }
617
+ if (payload.finishDate !== undefined) {
618
+ mapped['plannedFinish'] = payload.finishDate;
619
+ }
620
+ return mapped;
621
+ }
622
+ mapRuntimeBulkUpdatePayload(payload) {
623
+ const items = payload.map((item) => {
624
+ const mapped = this.mapRuntimeMutationPayload(item);
625
+ const id = this.toTaskId(item['id']);
626
+ if (id !== null) {
627
+ mapped['id'] = id;
628
+ }
629
+ return mapped;
630
+ });
631
+ const type = this.resolveRuntimeScheduleItemType(payload[0]?.['type']);
632
+ return {
633
+ ...(type === null ? {} : { type }),
634
+ items,
635
+ };
636
+ }
637
+ mapRuntimeOrderUpdatePayload(payload) {
638
+ return {
639
+ items: payload.map((item) => ({
640
+ id: item.taskId,
641
+ order: item.order,
642
+ })),
643
+ };
644
+ }
645
+ resolveRuntimeScheduleItemType(value) {
646
+ if (typeof value === 'number' && Number.isFinite(value)) {
647
+ return value;
648
+ }
649
+ const normalized = String(value ?? '')
650
+ .trim()
651
+ .toLowerCase();
652
+ if (!normalized) {
653
+ return null;
654
+ }
655
+ if (normalized === 'task') {
656
+ return 0;
657
+ }
658
+ if (normalized === 'milestone') {
659
+ return 1;
660
+ }
661
+ if (normalized === 'deliverable') {
662
+ return 2;
663
+ }
664
+ return null;
665
+ }
349
666
  loadCustomColumns(context) {
350
667
  if (Array.isArray(context.customColumns)) {
351
668
  return of(context.customColumns);
@@ -380,7 +697,8 @@ class TaskScheduleBackendAdapter {
380
697
  })
381
698
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to load schedule views.')));
382
699
  if (scheduleViewKey) {
383
- return views$.pipe(map((views) => views.find((view) => String(view.key ?? '').toLowerCase() === scheduleViewKey.toLowerCase())), map((view) => this.mapScheduleColumns(view?.columns ?? [], context.langCode ?? 'en')));
700
+ return views$.pipe(map((views) => views.find((view) => String(view.key ?? '').toLowerCase() ===
701
+ scheduleViewKey.toLowerCase())), map((view) => this.mapScheduleColumns(view?.columns ?? [], context.langCode ?? 'en')));
384
702
  }
385
703
  const settingsEndpoint = this.resolveScheduleManagerEndpoint(context, 'scheduleSettingsByLevel', '{scheduleManagerBase}/{levelId}/settings', { levelId });
386
704
  return this.http
@@ -398,38 +716,16 @@ class TaskScheduleBackendAdapter {
398
716
  null);
399
717
  }))), map((view) => this.mapScheduleColumns(view?.columns ?? [], context.langCode ?? 'en')));
400
718
  }
401
- resolveTreeRouteTemplate(context, modelType) {
402
- const modeEndpointKeyByModel = {
403
- default: 'scheduleTreeDefault',
404
- edit: 'scheduleTreeEdit',
405
- baseline: 'scheduleTreeBaseline',
406
- criticalPath: 'scheduleTreeCriticalPath',
407
- resources: 'scheduleTreeResources',
408
- unscheduled: 'scheduleTreeUnscheduled',
409
- phaseGate: 'scheduleTreePhaseGate',
410
- custom: 'scheduleTreeCustom',
411
- };
412
- const modeSpecificRoute = this.readEndpoint(context.endpoints, modeEndpointKeyByModel[modelType]);
413
- if (modeSpecificRoute) {
414
- return modeSpecificRoute;
719
+ resolveTreeRouteTemplate(context, _modelType) {
720
+ const phaseGateRoute = this.readEndpoint(context.endpoints, 'scheduleTreePhaseGate');
721
+ if (phaseGateRoute) {
722
+ return phaseGateRoute;
415
723
  }
416
724
  const customTreeRoute = this.readEndpoint(context.endpoints, 'scheduleTree');
417
725
  if (customTreeRoute) {
418
726
  return customTreeRoute;
419
727
  }
420
- if (this.readId(context.schemaId)) {
421
- if (modelType === 'baseline') {
422
- return 'tasks/{levelId}/GetAllBaseLine';
423
- }
424
- if (modelType === 'unscheduled') {
425
- return 'tasks/{levelId}/unscheduled';
426
- }
427
- if (modelType === 'phaseGate') {
428
- return 'tasks/{levelId}/GetAll?RenderMode=PhaseGate';
429
- }
430
- return 'tasks/{levelId}/GetAll';
431
- }
432
- return 'levels/{levelId}/{levelDataId}/schedule/tree';
728
+ return 'levels/{levelId}/{levelDataId}/schedule/tree?renderMode=PhaseGate';
433
729
  }
434
730
  buildTreeRouteParams(context, treeRouteTemplate) {
435
731
  const levelId = this.readId(context.levelId);
@@ -453,19 +749,40 @@ class TaskScheduleBackendAdapter {
453
749
  }
454
750
  return params;
455
751
  }
456
- resolveTaskMutationEndpoint(context, endpointKey, fallbackTemplate, legacyTemplateWithSchema, extraParams) {
752
+ resolveTaskMutationEndpoint(context, endpointKey, runtimeTemplate, legacyTemplate, legacyTemplateWithSchema, extraParams) {
457
753
  const levelId = this.readId(context.levelId);
458
754
  if (!levelId) {
459
755
  return null;
460
756
  }
757
+ const levelDataId = this.readId(context.levelDataId);
461
758
  const schemaId = this.readId(context.schemaId);
462
- const template = this.readEndpoint(context.endpoints, endpointKey) ??
463
- (schemaId ? legacyTemplateWithSchema : fallbackTemplate);
464
- return this.resolveApiUrl(context, template, {
759
+ const customTemplate = this.readEndpoint(context.endpoints, endpointKey);
760
+ const params = {
465
761
  levelId,
762
+ ...(levelDataId ? { levelDataId } : {}),
466
763
  ...(schemaId ? { schemaId } : {}),
467
764
  ...extraParams,
468
- });
765
+ };
766
+ if (customTemplate) {
767
+ const normalizedTemplate = customTemplate.replace(/\\/g, '/');
768
+ const isRuntimeTemplate = customTemplate.includes('{levelDataId}') ||
769
+ (levelDataId !== null &&
770
+ /levels\/\{levelId\}\/.+\/(schedule|tasks|milestones|deliverables)/i.test(normalizedTemplate));
771
+ return {
772
+ url: this.resolveApiUrl(context, customTemplate, params),
773
+ mode: isRuntimeTemplate ? 'runtime' : 'legacy',
774
+ };
775
+ }
776
+ if (levelDataId) {
777
+ return {
778
+ url: this.resolveApiUrl(context, runtimeTemplate, params),
779
+ mode: 'runtime',
780
+ };
781
+ }
782
+ return {
783
+ url: this.resolveApiUrl(context, schemaId ? legacyTemplateWithSchema : legacyTemplate, params),
784
+ mode: 'legacy',
785
+ };
469
786
  }
470
787
  resolveApplyImportedTasksEndpoint(context) {
471
788
  const levelId = this.readId(context.levelId);
@@ -474,14 +791,18 @@ class TaskScheduleBackendAdapter {
474
791
  }
475
792
  const custom = this.readEndpoint(context.endpoints, 'applyImportedTasks');
476
793
  if (custom) {
794
+ const levelDataId = this.readId(context.levelDataId);
477
795
  const schemaId = this.readId(context.schemaId);
478
796
  return this.resolveApiUrl(context, custom, {
479
797
  levelId,
798
+ ...(levelDataId ? { levelDataId } : {}),
480
799
  ...(schemaId ? { schemaId } : {}),
481
800
  });
482
801
  }
483
802
  const schemaId = this.readId(context.schemaId);
484
- const template = schemaId ? 'tasks/{schemaId}/{levelId}' : 'tasks/{levelId}/import';
803
+ const template = schemaId
804
+ ? 'tasks/{schemaId}/{levelId}'
805
+ : 'tasks/{levelId}/import';
485
806
  return this.resolveApiUrl(context, template, {
486
807
  levelId,
487
808
  ...(schemaId ? { schemaId } : {}),
@@ -535,7 +856,8 @@ class TaskScheduleBackendAdapter {
535
856
  return headers;
536
857
  }
537
858
  buildIdempotencyKey(seed) {
538
- if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
859
+ if (typeof crypto !== 'undefined' &&
860
+ typeof crypto.randomUUID === 'function') {
539
861
  return `${seed}-${crypto.randomUUID()}`;
540
862
  }
541
863
  return `${seed}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
@@ -555,7 +877,7 @@ class TaskScheduleBackendAdapter {
555
877
  }
556
878
  extractTaskArray(payload) {
557
879
  if (Array.isArray(payload)) {
558
- return payload;
880
+ return this.normalizeTaskRows(payload);
559
881
  }
560
882
  if (!payload || typeof payload !== 'object') {
561
883
  return [];
@@ -571,7 +893,7 @@ class TaskScheduleBackendAdapter {
571
893
  ];
572
894
  for (const candidate of candidates) {
573
895
  if (Array.isArray(candidate)) {
574
- return candidate;
896
+ return this.normalizeTaskRows(candidate);
575
897
  }
576
898
  }
577
899
  if (source['id'] !== undefined || source['Id'] !== undefined) {
@@ -579,6 +901,145 @@ class TaskScheduleBackendAdapter {
579
901
  }
580
902
  return [];
581
903
  }
904
+ normalizeTaskRows(rows) {
905
+ const resourceRows = this.flattenResourceGroups(rows);
906
+ return resourceRows ?? rows;
907
+ }
908
+ flattenResourceGroups(rows) {
909
+ const mergedById = new Map();
910
+ const unmatchedRows = [];
911
+ let hasResourceGroups = false;
912
+ rows.forEach((row) => {
913
+ if (!row || typeof row !== 'object') {
914
+ return;
915
+ }
916
+ const group = row;
917
+ const groupItems = this.firstDefined(group, ['items', 'Items']);
918
+ if (!Array.isArray(groupItems)) {
919
+ return;
920
+ }
921
+ const isResourceGroup = group['userId'] !== undefined ||
922
+ group['UserId'] !== undefined ||
923
+ group['displayName'] !== undefined ||
924
+ group['DisplayName'] !== undefined;
925
+ if (!isResourceGroup) {
926
+ return;
927
+ }
928
+ hasResourceGroups = true;
929
+ const groupUserId = this.toTaskId(this.firstDefined(group, ['userId', 'UserId']));
930
+ const groupDisplayName = this.toNullableString(this.firstDefined(group, [
931
+ 'displayName',
932
+ 'DisplayName',
933
+ 'name',
934
+ 'Name',
935
+ ]));
936
+ groupItems.forEach((item) => {
937
+ if (!item || typeof item !== 'object') {
938
+ return;
939
+ }
940
+ const taskRow = { ...item };
941
+ this.attachGroupResource(taskRow, groupUserId, groupDisplayName);
942
+ const id = this.toTaskId(this.firstDefined(taskRow, ['id', 'Id', 'taskId', 'TaskId']));
943
+ if (id === null) {
944
+ unmatchedRows.push(taskRow);
945
+ return;
946
+ }
947
+ const key = String(id);
948
+ const existing = mergedById.get(key);
949
+ if (!existing) {
950
+ mergedById.set(key, taskRow);
951
+ return;
952
+ }
953
+ this.mergeTaskResources(existing, taskRow);
954
+ if (existing['assignedTo'] === undefined &&
955
+ taskRow['assignedTo'] !== undefined) {
956
+ existing['assignedTo'] = taskRow['assignedTo'];
957
+ }
958
+ if (existing['AssignedTo'] === undefined &&
959
+ taskRow['AssignedTo'] !== undefined) {
960
+ existing['AssignedTo'] = taskRow['AssignedTo'];
961
+ }
962
+ });
963
+ });
964
+ if (!hasResourceGroups) {
965
+ return null;
966
+ }
967
+ return [...mergedById.values(), ...unmatchedRows];
968
+ }
969
+ attachGroupResource(taskRow, groupUserId, groupDisplayName) {
970
+ if (groupUserId === null) {
971
+ return;
972
+ }
973
+ const existingResourcesCandidate = this.firstDefined(taskRow, [
974
+ 'resources',
975
+ 'Resources',
976
+ ]);
977
+ const existingResources = Array.isArray(existingResourcesCandidate)
978
+ ? [...existingResourcesCandidate]
979
+ : [];
980
+ const hasResource = existingResources.some((resource) => this.resolveResourceIdentity(resource) === String(groupUserId));
981
+ if (!hasResource) {
982
+ existingResources.push({
983
+ resourceId: groupUserId,
984
+ resourceName: groupDisplayName ?? String(groupUserId),
985
+ });
986
+ }
987
+ taskRow['resources'] = existingResources;
988
+ if (taskRow['assignedTo'] === undefined &&
989
+ taskRow['AssignedTo'] === undefined) {
990
+ taskRow['assignedTo'] = groupUserId;
991
+ }
992
+ }
993
+ mergeTaskResources(target, source) {
994
+ const targetResourcesCandidate = this.firstDefined(target, [
995
+ 'resources',
996
+ 'Resources',
997
+ ]);
998
+ const sourceResourcesCandidate = this.firstDefined(source, [
999
+ 'resources',
1000
+ 'Resources',
1001
+ ]);
1002
+ const targetResources = Array.isArray(targetResourcesCandidate)
1003
+ ? [...targetResourcesCandidate]
1004
+ : [];
1005
+ const sourceResources = Array.isArray(sourceResourcesCandidate)
1006
+ ? sourceResourcesCandidate
1007
+ : [];
1008
+ sourceResources.forEach((resource) => {
1009
+ const sourceId = this.resolveResourceIdentity(resource);
1010
+ if (!sourceId) {
1011
+ return;
1012
+ }
1013
+ const exists = targetResources.some((targetResource) => this.resolveResourceIdentity(targetResource) === sourceId);
1014
+ if (!exists) {
1015
+ targetResources.push(resource);
1016
+ }
1017
+ });
1018
+ if (targetResources.length) {
1019
+ target['resources'] = targetResources;
1020
+ }
1021
+ }
1022
+ resolveResourceIdentity(resource) {
1023
+ if (resource === null || resource === undefined) {
1024
+ return null;
1025
+ }
1026
+ if (typeof resource === 'string' || typeof resource === 'number') {
1027
+ return String(resource);
1028
+ }
1029
+ if (typeof resource !== 'object') {
1030
+ return null;
1031
+ }
1032
+ const row = resource;
1033
+ const id = this.toTaskId(this.firstDefined(row, [
1034
+ 'resourceId',
1035
+ 'ResourceId',
1036
+ 'userId',
1037
+ 'UserId',
1038
+ 'id',
1039
+ 'Id',
1040
+ ]));
1041
+ return id === null ? null : String(id);
1042
+ }
582
1043
  mapRuntimeTask(payload, fallbackOrder) {
583
1044
  if (!payload || typeof payload !== 'object') {
584
1045
  return null;
@@ -588,9 +1049,20 @@ class TaskScheduleBackendAdapter {
588
1049
  if (id === null) {
589
1050
  return null;
590
1051
  }
591
- const type = String(this.firstDefined(source, ['type', 'Type', 'typeLable', 'TypeLable', 'typeLabel', 'TypeLabel']) ??
592
- 'Task');
593
- const assignee = this.extractAssignee(this.firstDefined(source, ['assignedTo', 'AssignedTo', 'createdBy', 'CreatedBy']));
1052
+ const type = String(this.firstDefined(source, [
1053
+ 'type',
1054
+ 'Type',
1055
+ 'typeLable',
1056
+ 'TypeLable',
1057
+ 'typeLabel',
1058
+ 'TypeLabel',
1059
+ ]) ?? 'Task');
1060
+ const assignee = this.extractAssignee(this.firstDefined(source, [
1061
+ 'assignedTo',
1062
+ 'AssignedTo',
1063
+ 'createdBy',
1064
+ 'CreatedBy',
1065
+ ]));
594
1066
  const resources = this.extractTaskResources(this.firstDefined(source, ['resources', 'Resources']), assignee);
595
1067
  const subtasksRaw = this.firstDefined(source, [
596
1068
  'subtasks',
@@ -645,9 +1117,24 @@ class TaskScheduleBackendAdapter {
645
1117
  'baselineFinish',
646
1118
  'BaselineFinish',
647
1119
  ])),
648
- actualStartDate: this.extractDate(this.firstDefined(source, ['actualStartDate', 'ActualStartDate', 'actualStart', 'ActualStart'])),
649
- actualFinishDate: this.extractDate(this.firstDefined(source, ['actualFinishDate', 'ActualFinishDate', 'actualFinish', 'ActualFinish'])),
650
- predecessor: this.toNullableString(this.firstDefined(source, ['predecessor', 'Predecessor', 'predecessors', 'Predecessors'])),
1120
+ actualStartDate: this.extractDate(this.firstDefined(source, [
1121
+ 'actualStartDate',
1122
+ 'ActualStartDate',
1123
+ 'actualStart',
1124
+ 'ActualStart',
1125
+ ])),
1126
+ actualFinishDate: this.extractDate(this.firstDefined(source, [
1127
+ 'actualFinishDate',
1128
+ 'ActualFinishDate',
1129
+ 'actualFinish',
1130
+ 'ActualFinish',
1131
+ ])),
1132
+ predecessor: this.toNullableString(this.firstDefined(source, [
1133
+ 'predecessor',
1134
+ 'Predecessor',
1135
+ 'predecessors',
1136
+ 'Predecessors',
1137
+ ])),
651
1138
  duration: this.toNullableNumber(this.firstDefined(source, ['duration', 'Duration'])),
652
1139
  progress: this.extractProgress(this.firstDefined(source, ['progress', 'Progress'])),
653
1140
  details: this.toNullableString(this.firstDefined(source, ['details', 'Details', 'description'])),
@@ -801,8 +1288,7 @@ class TaskScheduleBackendAdapter {
801
1288
  id: typeof id === 'number' || typeof id === 'string' ? id : String(id),
802
1289
  key,
803
1290
  name: this.toNullableString(row['name'] ?? row['displayName'] ?? row['Name']) ?? key,
804
- viewType: this.toNullableString(row['viewType'] ?? row['type'] ?? row['ViewType']) ??
805
- 'Text',
1291
+ viewType: this.toNullableString(row['viewType'] ?? row['type'] ?? row['ViewType']) ?? 'Text',
806
1292
  normalizedKey: this.toNullableString(row['normalizedKey'] ?? row['NormalizedKey']) ??
807
1293
  undefined,
808
1294
  isRequired: Boolean(row['isRequired'] ?? row['required']),
@@ -824,11 +1310,7 @@ class TaskScheduleBackendAdapter {
824
1310
  return;
825
1311
  }
826
1312
  const row = item;
827
- const optionValue = row['value'] ??
828
- row['id'] ??
829
- row['key'] ??
830
- row['name'] ??
831
- row['text'];
1313
+ const optionValue = row['value'] ?? row['id'] ?? row['key'] ?? row['name'] ?? row['text'];
832
1314
  const optionText = this.toNullableString(row['text'] ?? row['name'] ?? row['displayName'] ?? row['label']);
833
1315
  if (optionValue === undefined || optionValue === null || !optionText) {
834
1316
  return;
@@ -902,7 +1384,10 @@ class TaskScheduleBackendAdapter {
902
1384
  }
903
1385
  if (value && typeof value === 'object') {
904
1386
  const row = value;
905
- return this.toNullableString(row['displayName'] ?? row['resourceName'] ?? row['userName'] ?? row['name']);
1387
+ return this.toNullableString(row['displayName'] ??
1388
+ row['resourceName'] ??
1389
+ row['userName'] ??
1390
+ row['name']);
906
1391
  }
907
1392
  return null;
908
1393
  };
@@ -922,10 +1407,7 @@ class TaskScheduleBackendAdapter {
922
1407
  return;
923
1408
  }
924
1409
  const obj = resource;
925
- const id = obj['resourceId'] ??
926
- obj['id'] ??
927
- obj['userId'] ??
928
- obj['value'];
1410
+ const id = obj['resourceId'] ?? obj['id'] ?? obj['userId'] ?? obj['value'];
929
1411
  if (id === undefined || id === null) {
930
1412
  return;
931
1413
  }
@@ -1018,7 +1500,8 @@ class TaskScheduleBackendAdapter {
1018
1500
  }
1019
1501
  return {
1020
1502
  resourceId,
1021
- unit: this.toNullableNumber(row['unit'] ?? row['resourceUnit']) ?? undefined,
1503
+ unit: this.toNullableNumber(row['unit'] ?? row['resourceUnit']) ??
1504
+ undefined,
1022
1505
  };
1023
1506
  })
1024
1507
  .filter((item) => item !== null);
@@ -1872,11 +2355,11 @@ class TaskScheduleTaskbarTemplate {
1872
2355
  data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
1873
2356
  langCode = input('en', ...(ngDevMode ? [{ debugName: "langCode" }] : []));
1874
2357
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleTaskbarTemplate, deps: [], target: i0.ɵɵFactoryTarget.Component });
1875
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleTaskbarTemplate, isStandalone: true, selector: "mt-task-schedule-taskbar-template", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\n <div\n class=\"e-gantt-child-taskbar-inner-div e-gantt-child-taskbar gantt-child-taskbar\"\n [style.width.px]=\"data().ganttProperties?.width\"\n tabindex=\"-1\"\n >\n <div\n class=\"e-gantt-child-progressbar-inner-div e-gantt-child-progressbar gantt-child-progressbar\"\n [style.width.px]=\"data().ganttProperties?.progressWidth\"\n >\n <span class=\"e-task-label gantt-task-label\"></span>\n </div>\n </div>\n\n @if (data().taskData?.type === 'Milestone') {\n <div\n class=\"e-gantt-milestone gantt-milestone\"\n [class.diamond-left]=\"langCode() === 'en'\"\n [class.diamond-right]=\"langCode() === 'ar'\"\n tabindex=\"-1\"\n ></div>\n }\n</div>", styles: [".gantt-child-taskbar{height:22px!important;margin-top:-1px!important}.gantt-child-progressbar{border-style:solid!important;height:100%!important;border-top-right-radius:0;border-bottom-right-radius:0}.gantt-task-label{line-height:21px!important;text-align:left;display:inline-block;width:122px!important;height:22px!important}.gantt-milestone{width:16px!important;height:16px!important;position:absolute!important;transform:rotate(45deg)}.diamond-left{left:calc(100% + .5rem)}.diamond-right{right:calc(100% + .5rem)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
2358
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleTaskbarTemplate, isStandalone: true, selector: "mt-task-schedule-taskbar-template", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div>\r\n <div\r\n class=\"e-gantt-child-taskbar-inner-div e-gantt-child-taskbar gantt-child-taskbar\"\r\n [style.width.px]=\"data().ganttProperties?.width\"\r\n tabindex=\"-1\"\r\n >\r\n <div\r\n class=\"e-gantt-child-progressbar-inner-div e-gantt-child-progressbar gantt-child-progressbar\"\r\n [style.width.px]=\"data().ganttProperties?.progressWidth\"\r\n >\r\n <span class=\"e-task-label gantt-task-label\"></span>\r\n </div>\r\n </div>\r\n\r\n @if (data().taskData?.type === 'Milestone') {\r\n <div\r\n class=\"e-gantt-milestone gantt-milestone\"\r\n [class.diamond-left]=\"langCode() === 'en'\"\r\n [class.diamond-right]=\"langCode() === 'ar'\"\r\n tabindex=\"-1\"\r\n ></div>\r\n }\r\n</div>", styles: [".gantt-child-taskbar{height:22px!important;margin-top:-1px!important}.gantt-child-progressbar{border-style:solid!important;height:100%!important;border-top-right-radius:0;border-bottom-right-radius:0}.gantt-task-label{line-height:21px!important;text-align:left;display:inline-block;width:122px!important;height:22px!important}.gantt-milestone{width:16px!important;height:16px!important;position:absolute!important;transform:rotate(45deg)}.diamond-left{left:calc(100% + .5rem)}.diamond-right{right:calc(100% + .5rem)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
1876
2359
  }
1877
2360
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleTaskbarTemplate, decorators: [{
1878
2361
  type: Component,
1879
- args: [{ selector: 'mt-task-schedule-taskbar-template', standalone: true, imports: [CommonModule], template: "<div>\n <div\n class=\"e-gantt-child-taskbar-inner-div e-gantt-child-taskbar gantt-child-taskbar\"\n [style.width.px]=\"data().ganttProperties?.width\"\n tabindex=\"-1\"\n >\n <div\n class=\"e-gantt-child-progressbar-inner-div e-gantt-child-progressbar gantt-child-progressbar\"\n [style.width.px]=\"data().ganttProperties?.progressWidth\"\n >\n <span class=\"e-task-label gantt-task-label\"></span>\n </div>\n </div>\n\n @if (data().taskData?.type === 'Milestone') {\n <div\n class=\"e-gantt-milestone gantt-milestone\"\n [class.diamond-left]=\"langCode() === 'en'\"\n [class.diamond-right]=\"langCode() === 'ar'\"\n tabindex=\"-1\"\n ></div>\n }\n</div>", styles: [".gantt-child-taskbar{height:22px!important;margin-top:-1px!important}.gantt-child-progressbar{border-style:solid!important;height:100%!important;border-top-right-radius:0;border-bottom-right-radius:0}.gantt-task-label{line-height:21px!important;text-align:left;display:inline-block;width:122px!important;height:22px!important}.gantt-milestone{width:16px!important;height:16px!important;position:absolute!important;transform:rotate(45deg)}.diamond-left{left:calc(100% + .5rem)}.diamond-right{right:calc(100% + .5rem)}\n"] }]
2362
+ args: [{ selector: 'mt-task-schedule-taskbar-template', standalone: true, imports: [CommonModule], template: "<div>\r\n <div\r\n class=\"e-gantt-child-taskbar-inner-div e-gantt-child-taskbar gantt-child-taskbar\"\r\n [style.width.px]=\"data().ganttProperties?.width\"\r\n tabindex=\"-1\"\r\n >\r\n <div\r\n class=\"e-gantt-child-progressbar-inner-div e-gantt-child-progressbar gantt-child-progressbar\"\r\n [style.width.px]=\"data().ganttProperties?.progressWidth\"\r\n >\r\n <span class=\"e-task-label gantt-task-label\"></span>\r\n </div>\r\n </div>\r\n\r\n @if (data().taskData?.type === 'Milestone') {\r\n <div\r\n class=\"e-gantt-milestone gantt-milestone\"\r\n [class.diamond-left]=\"langCode() === 'en'\"\r\n [class.diamond-right]=\"langCode() === 'ar'\"\r\n tabindex=\"-1\"\r\n ></div>\r\n }\r\n</div>", styles: [".gantt-child-taskbar{height:22px!important;margin-top:-1px!important}.gantt-child-progressbar{border-style:solid!important;height:100%!important;border-top-right-radius:0;border-bottom-right-radius:0}.gantt-task-label{line-height:21px!important;text-align:left;display:inline-block;width:122px!important;height:22px!important}.gantt-milestone{width:16px!important;height:16px!important;position:absolute!important;transform:rotate(45deg)}.diamond-left{left:calc(100% + .5rem)}.diamond-right{right:calc(100% + .5rem)}\n"] }]
1880
2363
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], langCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "langCode", required: false }] }] } });
1881
2364
 
1882
2365
  const EMPTY_RESULT = { tasks: [] };
@@ -1907,14 +2390,7 @@ class TaskSchedule {
1907
2390
  operationSub = new Subscription();
1908
2391
  contextAddTask = signal('', ...(ngDevMode ? [{ debugName: "contextAddTask" }] : []));
1909
2392
  customProperties = signal([], ...(ngDevMode ? [{ debugName: "customProperties" }] : []));
1910
- modelType = input('default', ...(ngDevMode ? [{ debugName: "modelType" }] : []));
1911
2393
  context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : []));
1912
- dateFormat = input('dd/MM/yyyy', ...(ngDevMode ? [{ debugName: "dateFormat" }] : []));
1913
- height = input('760px', ...(ngDevMode ? [{ debugName: "height" }] : []));
1914
- langCode = input(null, ...(ngDevMode ? [{ debugName: "langCode" }] : []));
1915
- pdfFontData = input(null, ...(ngDevMode ? [{ debugName: "pdfFontData" }] : []));
1916
- pdfRtlFontData = input(null, ...(ngDevMode ? [{ debugName: "pdfRtlFontData" }] : []));
1917
- pdfFontSize = input(11, ...(ngDevMode ? [{ debugName: "pdfFontSize" }] : []));
1918
2394
  toolbarAction = output();
1919
2395
  actionBegin = output();
1920
2396
  actionCompleted = output();
@@ -1925,8 +2401,11 @@ class TaskSchedule {
1925
2401
  dataSource = signal([], ...(ngDevMode ? [{ debugName: "dataSource" }] : []));
1926
2402
  ganttConfig = signal(createGanttConfig('default', EMPTY_RESULT, 'dd/MM/yyyy', 'en'), ...(ngDevMode ? [{ debugName: "ganttConfig" }] : []));
1927
2403
  ganttId = `mtTaskScheduleGantt-${Math.random().toString(36).slice(2, 10)}`;
1928
- resolvedModelType = computed(() => normalizeTaskScheduleModelType(this.modelType()), ...(ngDevMode ? [{ debugName: "resolvedModelType" }] : []));
1929
- resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.langCode(), this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
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" }] : []));
1930
2409
  isEditMode = computed(() => this.resolvedModelType() === 'edit', ...(ngDevMode ? [{ debugName: "isEditMode" }] : []));
1931
2410
  editTaskTypes = computed(() => resolveEditTaskTypes(this.resolvedLangCode()), ...(ngDevMode ? [{ debugName: "editTaskTypes" }] : []));
1932
2411
  enableRtl = computed(() => this.resolvedLangCode() === 'ar' ||
@@ -1954,7 +2433,7 @@ class TaskSchedule {
1954
2433
  return;
1955
2434
  }
1956
2435
  const langCode = this.resolvedLangCode();
1957
- this.loadSchedule(this.modelType(), context, this.dateFormat(), langCode);
2436
+ this.loadSchedule(this.resolvedModelTypeInput(), context, this.resolvedDateFormat(), langCode);
1958
2437
  }, { ...(ngDevMode ? { debugName: "loadEffect" } : {}), injector: this.injector });
1959
2438
  const refreshSub = this.queueService.refreshTasks$.subscribe(() => {
1960
2439
  this.reloadSchedule();
@@ -2038,7 +2517,7 @@ class TaskSchedule {
2038
2517
  onActionComplete(args) {
2039
2518
  const context = this.context();
2040
2519
  if (context) {
2041
- this.queueService.reorderColumn(args, this.modelType(), context);
2520
+ this.queueService.reorderColumn(args, this.resolvedModelTypeInput(), context);
2042
2521
  }
2043
2522
  if (this.isEditMode()) {
2044
2523
  if (args?.requestType === 'openEditDialog' ||
@@ -2142,7 +2621,7 @@ class TaskSchedule {
2142
2621
  dependsOn: property.dependsOn,
2143
2622
  };
2144
2623
  if (property.viewType === 'Date') {
2145
- column['format'] = { type: 'date', format: this.dateFormat() };
2624
+ column['format'] = { type: 'date', format: this.resolvedDateFormat() };
2146
2625
  column['type'] = 'date';
2147
2626
  }
2148
2627
  if (property.viewType === 'Lookup') {
@@ -2413,7 +2892,7 @@ class TaskSchedule {
2413
2892
  if (!context) {
2414
2893
  return;
2415
2894
  }
2416
- this.loadSchedule(this.modelType(), context, this.dateFormat(), this.resolvedLangCode());
2895
+ this.loadSchedule(this.resolvedModelTypeInput(), context, this.resolvedDateFormat(), this.resolvedLangCode());
2417
2896
  }
2418
2897
  normalizeTasks(tasks, customProps) {
2419
2898
  return [...tasks]
@@ -2740,15 +3219,10 @@ class TaskSchedule {
2740
3219
  resolvePdfExportFont() {
2741
3220
  const contextFonts = this.context()?.pdfFonts;
2742
3221
  const fontData = (this.enableRtl()
2743
- ? this.pdfRtlFontData() ??
2744
- contextFonts?.arabic ??
2745
- this.pdfFontData() ??
2746
- contextFonts?.regular
2747
- : this.pdfFontData() ??
2748
- contextFonts?.regular ??
2749
- this.pdfRtlFontData() ??
2750
- contextFonts?.arabic) ?? TASK_SCHEDULE_DEFAULT_PDF_FONT;
2751
- 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);
2752
3226
  }
2753
3227
  createEmbeddedPdfFont(base64FontData, size) {
2754
3228
  try {
@@ -2885,7 +3359,7 @@ class TaskSchedule {
2885
3359
  }).format(date);
2886
3360
  }
2887
3361
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskSchedule, deps: [], target: i0.ɵɵFactoryTarget.Component });
2888
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskSchedule, isStandalone: true, selector: "mt-task-schedule", inputs: { modelType: { classPropertyName: "modelType", publicName: "modelType", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, pdfFontData: { classPropertyName: "pdfFontData", publicName: "pdfFontData", isSignal: true, isRequired: false, transformFunction: null }, pdfRtlFontData: { classPropertyName: "pdfRtlFontData", publicName: "pdfRtlFontData", isSignal: true, isRequired: false, transformFunction: null }, pdfFontSize: { classPropertyName: "pdfFontSize", publicName: "pdfFontSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { toolbarAction: "toolbarAction", actionBegin: "actionBegin", actionCompleted: "actionCompleted", loaded: "loaded", loadError: "loadError" }, host: { classAttribute: "block" }, providers: [
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: [
2889
3363
  DayMarkersService,
2890
3364
  EditService,
2891
3365
  ExcelExportService,
@@ -2897,7 +3371,7 @@ class TaskSchedule {
2897
3371
  ToolbarService,
2898
3372
  ContextMenuService,
2899
3373
  ResizeService,
2900
- ], viewQueries: [{ propertyName: "ganttObj", first: true, predicate: ["ganttObj"], descendants: true }], ngImport: i0, template: "@if (!loading()) {\n <ejs-gantt\n #ganttObj\n [id]=\"ganttId\"\n [enableVirtualization]=\"true\"\n [enableTimelineVirtualization]=\"true\"\n [enableVirtualMaskRow]=\"false\"\n [allowResizing]=\"true\"\n [enableRtl]=\"enableRtl()\"\n [locale]=\"locale()\"\n [height]=\"height()\"\n [dataSource]=\"dataSource()\"\n [taskFields]=\"ganttConfig().taskFields\"\n [columns]=\"ganttConfig().columns\"\n [renderBaseline]=\"ganttConfig().renderBaseline\"\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\n [allowSelection]=\"true\"\n [labelSettings]=\"ganttConfig().labelSettings\"\n [treeColumnIndex]=\"1\"\n [workWeek]=\"ganttConfig().workWeek\"\n [highlightWeekends]=\"true\"\n [enablePredecessorValidation]=\"true\"\n [splitterSettings]=\"ganttConfig().splitterSettings\"\n [gridLines]=\"ganttConfig().gridLines\"\n [toolbar]=\"ganttConfig().toolbar\"\n [allowExcelExport]=\"ganttConfig().allowExcelExport\"\n [allowPdfExport]=\"ganttConfig().allowPdfExport\"\n [enableContextMenu]=\"ganttConfig().enableContextMenu\"\n [contextMenuItems]=\"ganttConfig().contextMenuItems\"\n [timelineSettings]=\"ganttConfig().timelineSettings\"\n [editSettings]=\"ganttConfig().editSettings\"\n [addDialogFields]=\"ganttConfig().addDialogFields\"\n [editDialogFields]=\"ganttConfig().editDialogFields\"\n [resourceFields]=\"ganttConfig().resourceFields\"\n [resources]=\"ganttConfig().resources\"\n [viewType]=\"ganttConfig().viewType\"\n [showOverAllocation]=\"ganttConfig().showOverAllocation\"\n [allowUnscheduledTasks]=\"ganttConfig().allowUnscheduledTasks\"\n [eventMarkers]=\"ganttConfig().eventMarkers\"\n [projectStartDate]=\"ganttConfig().projectStartDate\"\n [projectEndDate]=\"ganttConfig().projectEndDate\"\n [autoCalculateDateScheduling]=\"false\"\n [dateFormat]=\"dateFormat()\"\n [allowSorting]=\"true\"\n [holidays]=\"ganttConfig().holidays\"\n [enableWBS]=\"true\"\n [enableAutoWbsUpdate]=\"true\"\n [allowReordering]=\"true\"\n (toolbarClick)=\"onToolbarClick($event)\"\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\n (contextMenuClick)=\"onContextMenuClick($event)\"\n (actionBegin)=\"onActionBegin($event)\"\n (actionComplete)=\"onActionComplete($event)\"\n (cellEdit)=\"onCellEdit($event)\"\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\n (dataBound)=\"onDataBound()\"\n >\n <ng-template #tooltipSettingsTaskbar let-data>\n <div class=\"px-2 py-1 text-xs\">\n <div class=\"font-medium\">{{ data?.title ?? '-' }}</div>\n <div>\n {{ tooltipTranslations().startsOn }}:\n {{ formatDateValue(data?.startDate) }}\n </div>\n <div>\n {{ tooltipTranslations().endsOn }}:\n {{ formatDateValue(data?.finishDate) }}\n </div>\n @if (data?.baselineStartDate) {\n <div>\n {{ tooltipTranslations().plannedStart }}:\n {{ formatDateValue(data?.baselineStartDate) }}\n </div>\n }\n @if (data?.baselineEndDate) {\n <div>\n {{ tooltipTranslations().plannedEnd }}:\n {{ formatDateValue(data?.baselineEndDate) }}\n </div>\n }\n <div>{{ tooltipTranslations().progress }}: {{ data?.progress ?? 0 }}</div>\n </div>\n </ng-template>\n\n <ng-template #taskbarTemplate let-data>\n <mt-task-schedule-taskbar-template [data]=\"data\" [langCode]=\"resolvedLangCode()\" />\n </ng-template>\n </ejs-gantt>\n} @else {\n <div class=\"task-schedule-loader\">\n <div class=\"task-schedule-loader__spinner\" aria-label=\"Loading\"></div>\n </div>\n}\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"] }] });
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"] }] });
2901
3375
  }
2902
3376
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskSchedule, decorators: [{
2903
3377
  type: Component,
@@ -2913,18 +3387,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2913
3387
  ToolbarService,
2914
3388
  ContextMenuService,
2915
3389
  ResizeService,
2916
- ], template: "@if (!loading()) {\n <ejs-gantt\n #ganttObj\n [id]=\"ganttId\"\n [enableVirtualization]=\"true\"\n [enableTimelineVirtualization]=\"true\"\n [enableVirtualMaskRow]=\"false\"\n [allowResizing]=\"true\"\n [enableRtl]=\"enableRtl()\"\n [locale]=\"locale()\"\n [height]=\"height()\"\n [dataSource]=\"dataSource()\"\n [taskFields]=\"ganttConfig().taskFields\"\n [columns]=\"ganttConfig().columns\"\n [renderBaseline]=\"ganttConfig().renderBaseline\"\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\n [allowSelection]=\"true\"\n [labelSettings]=\"ganttConfig().labelSettings\"\n [treeColumnIndex]=\"1\"\n [workWeek]=\"ganttConfig().workWeek\"\n [highlightWeekends]=\"true\"\n [enablePredecessorValidation]=\"true\"\n [splitterSettings]=\"ganttConfig().splitterSettings\"\n [gridLines]=\"ganttConfig().gridLines\"\n [toolbar]=\"ganttConfig().toolbar\"\n [allowExcelExport]=\"ganttConfig().allowExcelExport\"\n [allowPdfExport]=\"ganttConfig().allowPdfExport\"\n [enableContextMenu]=\"ganttConfig().enableContextMenu\"\n [contextMenuItems]=\"ganttConfig().contextMenuItems\"\n [timelineSettings]=\"ganttConfig().timelineSettings\"\n [editSettings]=\"ganttConfig().editSettings\"\n [addDialogFields]=\"ganttConfig().addDialogFields\"\n [editDialogFields]=\"ganttConfig().editDialogFields\"\n [resourceFields]=\"ganttConfig().resourceFields\"\n [resources]=\"ganttConfig().resources\"\n [viewType]=\"ganttConfig().viewType\"\n [showOverAllocation]=\"ganttConfig().showOverAllocation\"\n [allowUnscheduledTasks]=\"ganttConfig().allowUnscheduledTasks\"\n [eventMarkers]=\"ganttConfig().eventMarkers\"\n [projectStartDate]=\"ganttConfig().projectStartDate\"\n [projectEndDate]=\"ganttConfig().projectEndDate\"\n [autoCalculateDateScheduling]=\"false\"\n [dateFormat]=\"dateFormat()\"\n [allowSorting]=\"true\"\n [holidays]=\"ganttConfig().holidays\"\n [enableWBS]=\"true\"\n [enableAutoWbsUpdate]=\"true\"\n [allowReordering]=\"true\"\n (toolbarClick)=\"onToolbarClick($event)\"\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\n (contextMenuClick)=\"onContextMenuClick($event)\"\n (actionBegin)=\"onActionBegin($event)\"\n (actionComplete)=\"onActionComplete($event)\"\n (cellEdit)=\"onCellEdit($event)\"\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\n (dataBound)=\"onDataBound()\"\n >\n <ng-template #tooltipSettingsTaskbar let-data>\n <div class=\"px-2 py-1 text-xs\">\n <div class=\"font-medium\">{{ data?.title ?? '-' }}</div>\n <div>\n {{ tooltipTranslations().startsOn }}:\n {{ formatDateValue(data?.startDate) }}\n </div>\n <div>\n {{ tooltipTranslations().endsOn }}:\n {{ formatDateValue(data?.finishDate) }}\n </div>\n @if (data?.baselineStartDate) {\n <div>\n {{ tooltipTranslations().plannedStart }}:\n {{ formatDateValue(data?.baselineStartDate) }}\n </div>\n }\n @if (data?.baselineEndDate) {\n <div>\n {{ tooltipTranslations().plannedEnd }}:\n {{ formatDateValue(data?.baselineEndDate) }}\n </div>\n }\n <div>{{ tooltipTranslations().progress }}: {{ data?.progress ?? 0 }}</div>\n </div>\n </ng-template>\n\n <ng-template #taskbarTemplate let-data>\n <mt-task-schedule-taskbar-template [data]=\"data\" [langCode]=\"resolvedLangCode()\" />\n </ng-template>\n </ejs-gantt>\n} @else {\n <div class=\"task-schedule-loader\">\n <div class=\"task-schedule-loader__spinner\" aria-label=\"Loading\"></div>\n </div>\n}\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"] }]
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"] }]
2917
3391
  }], propDecorators: { ganttObj: [{
2918
3392
  type: ViewChild,
2919
3393
  args: ['ganttObj']
2920
- }], modelType: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelType", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], langCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "langCode", required: false }] }], pdfFontData: [{ type: i0.Input, args: [{ isSignal: true, alias: "pdfFontData", required: false }] }], pdfRtlFontData: [{ type: i0.Input, args: [{ isSignal: true, alias: "pdfRtlFontData", required: false }] }], pdfFontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "pdfFontSize", 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"] }] } });
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"] }] } });
2921
3395
 
2922
3396
  class TaskScheduleImportModal {
2923
3397
  adapter = inject(TASK_SCHEDULE_DATA_ADAPTER, { optional: true }) ??
2924
3398
  inject(TaskScheduleBackendAdapter);
2925
3399
  visible = input(true, ...(ngDevMode ? [{ debugName: "visible" }] : []));
2926
3400
  context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : []));
2927
- langCode = input(null, ...(ngDevMode ? [{ debugName: "langCode" }] : []));
2928
3401
  title = input(null, ...(ngDevMode ? [{ debugName: "title" }] : []));
2929
3402
  maxRows = input(400, ...(ngDevMode ? [{ debugName: "maxRows" }] : []));
2930
3403
  closed = output();
@@ -2936,7 +3409,7 @@ class TaskScheduleImportModal {
2936
3409
  loadingApply = signal(false, ...(ngDevMode ? [{ debugName: "loadingApply" }] : []));
2937
3410
  importResult = signal(null, ...(ngDevMode ? [{ debugName: "importResult" }] : []));
2938
3411
  selectedTaskKeys = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedTaskKeys" }] : []));
2939
- resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.langCode(), this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
3412
+ resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
2940
3413
  isRtl = computed(() => this.resolvedLangCode() === 'ar', ...(ngDevMode ? [{ debugName: "isRtl" }] : []));
2941
3414
  labels = computed(() => this.resolvedLangCode() === 'ar'
2942
3415
  ? {
@@ -3501,12 +3974,12 @@ class TaskScheduleImportModal {
3501
3974
  this.failed.emit(message);
3502
3975
  }
3503
3976
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleImportModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
3504
- 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()) {\n <div class=\"fixed inset-0 z-[1000] grid place-items-center bg-slate-900/40 p-4\">\n <section\n class=\"w-full max-w-6xl overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-200\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n >\n <header class=\"flex items-center justify-between border-b border-slate-200 px-5 py-4\">\n <h2 class=\"text-base font-semibold text-slate-900\">\n {{ title() || labels().title }}\n </h2>\n\n <mt-button\n [label]=\"labels().cancel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"close()\"\n />\n </header>\n\n <div class=\"space-y-4 p-5\">\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 p-4\">\n <div class=\"flex flex-wrap items-center gap-3\">\n <label\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\"\n >\n <span>{{ labels().selectFile }}</span>\n <input\n class=\"hidden\"\n type=\"file\"\n accept=\".mpp,.xer\"\n (change)=\"onFileChanged($event)\"\n />\n </label>\n\n <span class=\"max-w-[22rem] truncate text-sm text-slate-500\">\n {{ selectedFile()?.name || '-' }}\n </span>\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 (importResult(); as result) {\n @if (!previewRows().length) {\n <div class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\">\n {{ labels().noTasks }}\n </div>\n } @else {\n <div class=\"overflow-hidden rounded-xl border border-slate-200\">\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\">\n <label class=\"inline-flex items-center justify-center\">\n <input\n type=\"checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"selectAllRows($any($event.target).checked)\"\n />\n </label>\n <div>{{ labels().task }}</div>\n <div>{{ labels().startDate }}</div>\n <div>{{ labels().finishDate }}</div>\n <div>{{ labels().actualStartDate }}</div>\n <div>{{ labels().actualFinishDate }}</div>\n <div>{{ labels().assignedTo }}</div>\n <div>{{ labels().progress }}</div>\n </div>\n\n <div class=\"max-h-[28rem] overflow-auto\">\n @for (row of previewRows(); track trackByRow($index, row)) {\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\">\n <label class=\"inline-flex items-center justify-center\">\n <input\n type=\"checkbox\"\n [checked]=\"selectedTaskKeys().has(row.key)\"\n (change)=\"toggleRowSelection(row.key, $any($event.target).checked)\"\n />\n </label>\n\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\n <input\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\"\n type=\"text\"\n [value]=\"row.task.title || row.task.name || ''\"\n (input)=\"onTaskTitleChanged(row.key, $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.startDate)\"\n (change)=\"onTaskDateChanged(row.key, 'startDate', $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.finishDate)\"\n (change)=\"onTaskDateChanged(row.key, 'finishDate', $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.actualStartDate || row.task.actualStart)\"\n (change)=\"onTaskDateChanged(row.key, 'actualStartDate', $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.actualFinishDate || row.task.actualFinish)\"\n (change)=\"onTaskDateChanged(row.key, 'actualFinishDate', $any($event.target).value)\"\n />\n </div>\n\n <div class=\"min-w-0\">\n @if (resourceOptions().length) {\n <div class=\"space-y-1\">\n <select\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\"\n [value]=\"resolveAssignedValue(row.task)\"\n (change)=\"onTaskAssignedToChanged(row.key, $any($event.target).value)\"\n >\n <option value=\"\">-</option>\n @for (option of resourceOptions(); track option.id) {\n <option [value]=\"option.id\">{{ option.label }}</option>\n }\n </select>\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\n <div>\n <div class=\"space-y-1\">\n <input\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\"\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"normalizeProgress(row.task.progress)\"\n (input)=\"onTaskProgressChanged(row.key, $any($event.target).value)\"\n />\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n @if (isTruncated()) {\n <p class=\"text-xs text-slate-500\">{{ labels().rowsLimited }}</p>\n }\n }\n }\n </div>\n\n <footer class=\"flex flex-wrap items-center justify-end gap-2 border-t border-slate-200 px-5 py-4\">\n <mt-button\n [label]=\"labels().cancel\"\n severity=\"secondary\"\n [outlined]=\"true\"\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 </footer>\n </section>\n </div>\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"] }] });
3505
3978
  }
3506
3979
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleImportModal, decorators: [{
3507
3980
  type: Component,
3508
- args: [{ selector: 'mt-task-schedule-import-modal', standalone: true, imports: [CommonModule, Button, EntityPreview], template: "@if (visible()) {\n <div class=\"fixed inset-0 z-[1000] grid place-items-center bg-slate-900/40 p-4\">\n <section\n class=\"w-full max-w-6xl overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-200\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n >\n <header class=\"flex items-center justify-between border-b border-slate-200 px-5 py-4\">\n <h2 class=\"text-base font-semibold text-slate-900\">\n {{ title() || labels().title }}\n </h2>\n\n <mt-button\n [label]=\"labels().cancel\"\n severity=\"secondary\"\n [text]=\"true\"\n (onClick)=\"close()\"\n />\n </header>\n\n <div class=\"space-y-4 p-5\">\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 p-4\">\n <div class=\"flex flex-wrap items-center gap-3\">\n <label\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\"\n >\n <span>{{ labels().selectFile }}</span>\n <input\n class=\"hidden\"\n type=\"file\"\n accept=\".mpp,.xer\"\n (change)=\"onFileChanged($event)\"\n />\n </label>\n\n <span class=\"max-w-[22rem] truncate text-sm text-slate-500\">\n {{ selectedFile()?.name || '-' }}\n </span>\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 (importResult(); as result) {\n @if (!previewRows().length) {\n <div class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\">\n {{ labels().noTasks }}\n </div>\n } @else {\n <div class=\"overflow-hidden rounded-xl border border-slate-200\">\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\">\n <label class=\"inline-flex items-center justify-center\">\n <input\n type=\"checkbox\"\n [checked]=\"allSelected()\"\n (change)=\"selectAllRows($any($event.target).checked)\"\n />\n </label>\n <div>{{ labels().task }}</div>\n <div>{{ labels().startDate }}</div>\n <div>{{ labels().finishDate }}</div>\n <div>{{ labels().actualStartDate }}</div>\n <div>{{ labels().actualFinishDate }}</div>\n <div>{{ labels().assignedTo }}</div>\n <div>{{ labels().progress }}</div>\n </div>\n\n <div class=\"max-h-[28rem] overflow-auto\">\n @for (row of previewRows(); track trackByRow($index, row)) {\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\">\n <label class=\"inline-flex items-center justify-center\">\n <input\n type=\"checkbox\"\n [checked]=\"selectedTaskKeys().has(row.key)\"\n (change)=\"toggleRowSelection(row.key, $any($event.target).checked)\"\n />\n </label>\n\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\n <input\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\"\n type=\"text\"\n [value]=\"row.task.title || row.task.name || ''\"\n (input)=\"onTaskTitleChanged(row.key, $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.startDate)\"\n (change)=\"onTaskDateChanged(row.key, 'startDate', $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.finishDate)\"\n (change)=\"onTaskDateChanged(row.key, 'finishDate', $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.actualStartDate || row.task.actualStart)\"\n (change)=\"onTaskDateChanged(row.key, 'actualStartDate', $any($event.target).value)\"\n />\n </div>\n\n <div>\n <input\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\"\n type=\"date\"\n [value]=\"toDateInputValue(row.task.actualFinishDate || row.task.actualFinish)\"\n (change)=\"onTaskDateChanged(row.key, 'actualFinishDate', $any($event.target).value)\"\n />\n </div>\n\n <div class=\"min-w-0\">\n @if (resourceOptions().length) {\n <div class=\"space-y-1\">\n <select\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\"\n [value]=\"resolveAssignedValue(row.task)\"\n (change)=\"onTaskAssignedToChanged(row.key, $any($event.target).value)\"\n >\n <option value=\"\">-</option>\n @for (option of resourceOptions(); track option.id) {\n <option [value]=\"option.id\">{{ option.label }}</option>\n }\n </select>\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\n <div>\n <div class=\"space-y-1\">\n <input\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\"\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"normalizeProgress(row.task.progress)\"\n (input)=\"onTaskProgressChanged(row.key, $any($event.target).value)\"\n />\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n\n @if (isTruncated()) {\n <p class=\"text-xs text-slate-500\">{{ labels().rowsLimited }}</p>\n }\n }\n }\n </div>\n\n <footer class=\"flex flex-wrap items-center justify-end gap-2 border-t border-slate-200 px-5 py-4\">\n <mt-button\n [label]=\"labels().cancel\"\n severity=\"secondary\"\n [outlined]=\"true\"\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 </footer>\n </section>\n </div>\n}\r\n", styles: [":host{display:block}\n"] }]
3509
- }], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], langCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "langCode", 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"] }] } });
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"] }]
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"] }] } });
3510
3983
 
3511
3984
  const DEFAULT_MODES = [
3512
3985
  { value: 'default' },
@@ -3522,16 +3995,6 @@ class TaskScheduleShell {
3522
3995
  inject(TaskScheduleBackendAdapter);
3523
3996
  queueService = inject(TaskScheduleQueueService);
3524
3997
  context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : []));
3525
- langCode = input(null, ...(ngDevMode ? [{ debugName: "langCode" }] : []));
3526
- dateFormat = input('dd/MM/yyyy', ...(ngDevMode ? [{ debugName: "dateFormat" }] : []));
3527
- height = input('760px', ...(ngDevMode ? [{ debugName: "height" }] : []));
3528
- modelType = input('default', ...(ngDevMode ? [{ debugName: "modelType" }] : []));
3529
- modeOptions = input(null, ...(ngDevMode ? [{ debugName: "modeOptions" }] : []));
3530
- allowEditMode = input(true, ...(ngDevMode ? [{ debugName: "allowEditMode" }] : []));
3531
- allowImport = input(true, ...(ngDevMode ? [{ debugName: "allowImport" }] : []));
3532
- allowSetBaseline = input(true, ...(ngDevMode ? [{ debugName: "allowSetBaseline" }] : []));
3533
- hasTasks = input(true, ...(ngDevMode ? [{ debugName: "hasTasks" }] : []));
3534
- baselinePending = input(false, ...(ngDevMode ? [{ debugName: "baselinePending" }] : []));
3535
3998
  modeChanged = output();
3536
3999
  baselineSet = output();
3537
4000
  tasksExported = output();
@@ -3540,7 +4003,17 @@ class TaskScheduleShell {
3540
4003
  showImportModal = signal(false, ...(ngDevMode ? [{ debugName: "showImportModal" }] : []));
3541
4004
  settingBaseline = signal(false, ...(ngDevMode ? [{ debugName: "settingBaseline" }] : []));
3542
4005
  exportingTasks = signal(false, ...(ngDevMode ? [{ debugName: "exportingTasks" }] : []));
3543
- resolvedLangCode = computed(() => resolveTaskScheduleLanguage(this.langCode(), this.context()?.langCode), ...(ngDevMode ? [{ debugName: "resolvedLangCode" }] : []));
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" }] : []));
3544
4017
  labels = computed(() => this.resolvedLangCode() === 'ar'
3545
4018
  ? {
3546
4019
  mode: 'الوضع',
@@ -3568,29 +4041,30 @@ class TaskScheduleShell {
3568
4041
  }, ...(ngDevMode ? [{ debugName: "labels" }] : []));
3569
4042
  currentModelKey = computed(() => normalizeTaskScheduleModelType(this.currentModelType()), ...(ngDevMode ? [{ debugName: "currentModelKey" }] : []));
3570
4043
  resolvedModes = computed(() => {
3571
- const modes = this.modeOptions();
4044
+ const modes = this.context()?.modeOptions;
3572
4045
  const source = modes?.length ? modes : DEFAULT_MODES;
3573
4046
  return source
3574
- .filter((item) => this.allowEditMode() || normalizeTaskScheduleModelType(item.value) !== 'edit')
4047
+ .filter((item) => (this.context()?.allowEditMode ?? true) ||
4048
+ normalizeTaskScheduleModelType(item.value) !== 'edit')
3575
4049
  .map((item) => ({
3576
4050
  value: item.value,
3577
4051
  label: item.label || this.resolveModeLabel(item.value),
3578
4052
  }));
3579
4053
  }, ...(ngDevMode ? [{ debugName: "resolvedModes" }] : []));
3580
- showSetBaselineAction = computed(() => this.allowSetBaseline() &&
4054
+ showSetBaselineAction = computed(() => (this.context()?.allowSetBaseline ?? true) &&
3581
4055
  (this.currentModelKey() === 'default' || this.currentModelKey() === 'edit'), ...(ngDevMode ? [{ debugName: "showSetBaselineAction" }] : []));
3582
4056
  canSetBaselineAction = computed(() => this.showSetBaselineAction() &&
3583
4057
  !!this.context() &&
3584
4058
  !!this.adapter.setBaseline &&
3585
4059
  !this.settingBaseline() &&
3586
- !this.baselinePending() &&
3587
- this.hasTasks(), ...(ngDevMode ? [{ debugName: "canSetBaselineAction" }] : []));
3588
- showImportAction = computed(() => this.allowImport() && this.currentModelKey() === 'edit', ...(ngDevMode ? [{ debugName: "showImportAction" }] : []));
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" }] : []));
3589
4063
  canOpenImport = computed(() => this.showImportAction() && !!this.context(), ...(ngDevMode ? [{ debugName: "canOpenImport" }] : []));
3590
4064
  canExportTasks = computed(() => !!this.context() && !!this.adapter.exportTasks && !this.exportingTasks(), ...(ngDevMode ? [{ debugName: "canExportTasks" }] : []));
3591
4065
  constructor() {
3592
4066
  effect(() => {
3593
- this.currentModelType.set(this.modelType());
4067
+ this.currentModelType.set(this.context()?.modelType ?? 'default');
3594
4068
  });
3595
4069
  }
3596
4070
  onModeChange(nextValue) {
@@ -3717,12 +4191,12 @@ class TaskScheduleShell {
3717
4191
  this.actionError.emit(message);
3718
4192
  }
3719
4193
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleShell, deps: [], target: i0.ɵɵFactoryTarget.Component });
3720
- 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 }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, dateFormat: { classPropertyName: "dateFormat", publicName: "dateFormat", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, modelType: { classPropertyName: "modelType", publicName: "modelType", isSignal: true, isRequired: false, transformFunction: null }, modeOptions: { classPropertyName: "modeOptions", publicName: "modeOptions", isSignal: true, isRequired: false, transformFunction: null }, allowEditMode: { classPropertyName: "allowEditMode", publicName: "allowEditMode", isSignal: true, isRequired: false, transformFunction: null }, allowImport: { classPropertyName: "allowImport", publicName: "allowImport", isSignal: true, isRequired: false, transformFunction: null }, allowSetBaseline: { classPropertyName: "allowSetBaseline", publicName: "allowSetBaseline", isSignal: true, isRequired: false, transformFunction: null }, hasTasks: { classPropertyName: "hasTasks", publicName: "hasTasks", isSignal: true, isRequired: false, transformFunction: null }, baselinePending: { classPropertyName: "baselinePending", publicName: "baselinePending", 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'\">\n <header class=\"task-schedule-shell__header\">\n <div class=\"task-schedule-shell__mode\">\n <label class=\"task-schedule-shell__label\">{{ labels().mode }}</label>\n <select\n class=\"task-schedule-shell__select\"\n [value]=\"currentModelType()\"\n (change)=\"onModeChange($any($event.target).value)\"\n >\n @for (mode of resolvedModes(); track mode.value) {\n <option [value]=\"mode.value\">{{ mode.label }}</option>\n }\n </select>\n </div>\n\n <div class=\"task-schedule-shell__actions\">\n @if (showSetBaselineAction()) {\n <button\n type=\"button\"\n class=\"task-schedule-shell__btn\"\n [disabled]=\"!canSetBaselineAction()\"\n (click)=\"setBaseline()\"\n >\n {{ baselinePending() ? labels().pending : labels().setBaseline }}\n </button>\n }\n\n @if (showImportAction()) {\n <button\n type=\"button\"\n class=\"task-schedule-shell__btn\"\n [disabled]=\"!canOpenImport()\"\n (click)=\"openImportModal()\"\n >\n {{ labels().import }}\n </button>\n }\n\n <button\n type=\"button\"\n class=\"task-schedule-shell__btn\"\n [disabled]=\"!canExportTasks()\"\n (click)=\"exportTasks()\"\n >\n {{ labels().export }}\n </button>\n </div>\n </header>\n\n <mt-task-schedule\n [modelType]=\"currentModelType()\"\n [context]=\"context()\"\n [langCode]=\"resolvedLangCode()\"\n [dateFormat]=\"dateFormat()\"\n [height]=\"height()\"\n (loadError)=\"onActionError($event)\"\n />\n\n @if (showImportModal()) {\n <mt-task-schedule-import-modal\n [visible]=\"showImportModal()\"\n [context]=\"context()\"\n [langCode]=\"resolvedLangCode()\"\n (closed)=\"closeImportModal()\"\n (failed)=\"onActionError($event)\"\n (applied)=\"onImportedTasksApplied()\"\n />\n }\n</div>\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: ["modelType", "context", "dateFormat", "height", "langCode", "pdfFontData", "pdfRtlFontData", "pdfFontSize"], outputs: ["toolbarAction", "actionBegin", "actionCompleted", "loaded", "loadError"] }, { kind: "component", type: TaskScheduleImportModal, selector: "mt-task-schedule-import-modal", inputs: ["visible", "context", "langCode", "title", "maxRows"], outputs: ["closed", "imported", "applied", "failed"] }] });
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"] }] });
3721
4195
  }
3722
4196
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleShell, decorators: [{
3723
4197
  type: Component,
3724
- args: [{ selector: 'mt-task-schedule-shell', standalone: true, imports: [CommonModule, TaskSchedule, TaskScheduleImportModal], template: "<div class=\"task-schedule-shell\" [attr.dir]=\"resolvedLangCode() === 'ar' ? 'rtl' : 'ltr'\">\n <header class=\"task-schedule-shell__header\">\n <div class=\"task-schedule-shell__mode\">\n <label class=\"task-schedule-shell__label\">{{ labels().mode }}</label>\n <select\n class=\"task-schedule-shell__select\"\n [value]=\"currentModelType()\"\n (change)=\"onModeChange($any($event.target).value)\"\n >\n @for (mode of resolvedModes(); track mode.value) {\n <option [value]=\"mode.value\">{{ mode.label }}</option>\n }\n </select>\n </div>\n\n <div class=\"task-schedule-shell__actions\">\n @if (showSetBaselineAction()) {\n <button\n type=\"button\"\n class=\"task-schedule-shell__btn\"\n [disabled]=\"!canSetBaselineAction()\"\n (click)=\"setBaseline()\"\n >\n {{ baselinePending() ? labels().pending : labels().setBaseline }}\n </button>\n }\n\n @if (showImportAction()) {\n <button\n type=\"button\"\n class=\"task-schedule-shell__btn\"\n [disabled]=\"!canOpenImport()\"\n (click)=\"openImportModal()\"\n >\n {{ labels().import }}\n </button>\n }\n\n <button\n type=\"button\"\n class=\"task-schedule-shell__btn\"\n [disabled]=\"!canExportTasks()\"\n (click)=\"exportTasks()\"\n >\n {{ labels().export }}\n </button>\n </div>\n </header>\n\n <mt-task-schedule\n [modelType]=\"currentModelType()\"\n [context]=\"context()\"\n [langCode]=\"resolvedLangCode()\"\n [dateFormat]=\"dateFormat()\"\n [height]=\"height()\"\n (loadError)=\"onActionError($event)\"\n />\n\n @if (showImportModal()) {\n <mt-task-schedule-import-modal\n [visible]=\"showImportModal()\"\n [context]=\"context()\"\n [langCode]=\"resolvedLangCode()\"\n (closed)=\"closeImportModal()\"\n (failed)=\"onActionError($event)\"\n (applied)=\"onImportedTasksApplied()\"\n />\n }\n</div>\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"] }]
3725
- }], ctorParameters: () => [], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], langCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "langCode", required: false }] }], dateFormat: [{ type: i0.Input, args: [{ isSignal: true, alias: "dateFormat", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], modelType: [{ type: i0.Input, args: [{ isSignal: true, alias: "modelType", required: false }] }], modeOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "modeOptions", required: false }] }], allowEditMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowEditMode", required: false }] }], allowImport: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowImport", required: false }] }], allowSetBaseline: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowSetBaseline", required: false }] }], hasTasks: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasTasks", required: false }] }], baselinePending: [{ type: i0.Input, args: [{ isSignal: true, alias: "baselinePending", 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"] }] } });
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"] }] } });
3726
4200
 
3727
4201
  /**
3728
4202
  * Generated bundle index. Do not edit.