@masterteam/task-schedule 0.0.1 → 0.0.2

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.
@@ -157,12 +157,15 @@ class TaskScheduleBackendAdapter {
157
157
  if (!this.http) {
158
158
  return this.backendError('Task create requires HttpClient.');
159
159
  }
160
- const endpoint = this.resolveTaskMutationEndpoint(context, 'createTask', 'tasks/{levelId}/create', 'tasks/{schemaId}/{levelId}/create');
160
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'createTask', 'levels/{levelId}/{levelDataId}/schedule', 'tasks/{levelId}/create', 'tasks/{schemaId}/{levelId}/create');
161
161
  if (!endpoint) {
162
162
  return this.backendError('Task create endpoint requires a valid levelId.');
163
163
  }
164
+ const requestBody = endpoint.mode === 'runtime'
165
+ ? this.mapRuntimeMutationPayload(payload)
166
+ : payload;
164
167
  return this.http
165
- .post(endpoint, payload, {
168
+ .post(endpoint.url, requestBody, {
166
169
  headers: this.readHeaders(context, 'task-create'),
167
170
  })
168
171
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to create task.')));
@@ -171,12 +174,15 @@ class TaskScheduleBackendAdapter {
171
174
  if (!this.http) {
172
175
  return this.backendError('Task update requires HttpClient.');
173
176
  }
174
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateTask', 'tasks/{levelId}/update/{taskId}', 'tasks/{schemaId}/{levelId}/update/{taskId}', { taskId: this.readId(taskId) ?? '' });
177
+ 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
178
  if (!endpoint) {
176
179
  return this.backendError('Task update endpoint requires a valid levelId.');
177
180
  }
181
+ const requestBody = endpoint.mode === 'runtime'
182
+ ? this.mapRuntimeMutationPayload(payload)
183
+ : payload;
178
184
  return this.http
179
- .put(endpoint, payload, {
185
+ .put(endpoint.url, requestBody, {
180
186
  headers: this.readHeaders(context, 'task-update'),
181
187
  })
182
188
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task.')));
@@ -185,12 +191,12 @@ class TaskScheduleBackendAdapter {
185
191
  if (!this.http) {
186
192
  return this.backendError('Task delete requires HttpClient.');
187
193
  }
188
- const endpoint = this.resolveTaskMutationEndpoint(context, 'deleteTask', 'tasks/{levelId}/delete/{taskId}', 'tasks/{schemaId}/{levelId}/delete/{taskId}', { taskId: this.readId(taskId) ?? '' });
194
+ 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
195
  if (!endpoint) {
190
196
  return this.backendError('Task delete endpoint requires a valid levelId.');
191
197
  }
192
198
  return this.http
193
- .delete(endpoint, {
199
+ .delete(endpoint.url, {
194
200
  headers: this.readHeaders(context, 'task-delete'),
195
201
  })
196
202
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to delete task.')));
@@ -199,12 +205,15 @@ class TaskScheduleBackendAdapter {
199
205
  if (!this.http) {
200
206
  return this.backendError('Task bulk update requires HttpClient.');
201
207
  }
202
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateBulkTasks', 'tasks/{levelId}/bulkUpdate', 'tasks/{schemaId}/{levelId}/bulkUpdate');
208
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateBulkTasks', 'levels/{levelId}/{levelDataId}/schedule/bulk-update', 'tasks/{levelId}/bulkUpdate', 'tasks/{schemaId}/{levelId}/bulkUpdate');
203
209
  if (!endpoint) {
204
210
  return this.backendError('Task bulk update endpoint requires a valid levelId.');
205
211
  }
212
+ const requestBody = endpoint.mode === 'runtime'
213
+ ? this.mapRuntimeBulkUpdatePayload(payload)
214
+ : { data: payload };
206
215
  return this.http
207
- .put(endpoint, { data: payload }, {
216
+ .put(endpoint.url, requestBody, {
208
217
  headers: this.readHeaders(context, 'task-bulk-update'),
209
218
  })
210
219
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update linked tasks.')));
@@ -213,12 +222,12 @@ class TaskScheduleBackendAdapter {
213
222
  if (!this.http) {
214
223
  return this.backendError('Task parent update requires HttpClient.');
215
224
  }
216
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateParent', 'tasks/{levelId}/updateParent/{taskId}', 'tasks/{schemaId}/{levelId}/updateParent/{taskId}', { taskId: this.readId(taskId) ?? '' });
225
+ 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
226
  if (!endpoint) {
218
227
  return this.backendError('Task parent update endpoint requires a valid levelId.');
219
228
  }
220
229
  return this.http
221
- .put(endpoint, { parentId }, {
230
+ .put(endpoint.url, { parentId }, {
222
231
  headers: this.readHeaders(context, 'task-update-parent'),
223
232
  })
224
233
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task parent.')));
@@ -227,12 +236,15 @@ class TaskScheduleBackendAdapter {
227
236
  if (!this.http) {
228
237
  return this.backendError('Task reorder requires HttpClient.');
229
238
  }
230
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateOrder', 'tasks/{levelId}/reorder', 'tasks/{schemaId}/{levelId}/reorder');
239
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateOrder', 'levels/{levelId}/{levelDataId}/schedule/reorder', 'tasks/{levelId}/reorder', 'tasks/{schemaId}/{levelId}/reorder');
231
240
  if (!endpoint) {
232
241
  return this.backendError('Task reorder endpoint requires a valid levelId.');
233
242
  }
243
+ const requestBody = endpoint.mode === 'runtime'
244
+ ? this.mapRuntimeOrderUpdatePayload(payload)
245
+ : { data: payload };
234
246
  return this.http
235
- .put(endpoint, { data: payload }, {
247
+ .put(endpoint.url, requestBody, {
236
248
  headers: this.readHeaders(context, 'task-update-order'),
237
249
  })
238
250
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task order.')));
@@ -241,16 +253,19 @@ class TaskScheduleBackendAdapter {
241
253
  if (!this.http) {
242
254
  return this.backendError('Task progress update requires HttpClient.');
243
255
  }
244
- const endpoint = this.resolveTaskMutationEndpoint(context, 'updateProgress', 'tasks/{levelId}/updatePlanningModuleProgress', 'tasks/{schemaId}/{levelId}/updatePlanningModuleProgress');
256
+ const endpoint = this.resolveTaskMutationEndpoint(context, 'updateProgress', 'levels/{levelId}/{levelDataId}/schedule/{taskId}/progress', 'tasks/{levelId}/updatePlanningModuleProgress', 'tasks/{schemaId}/{levelId}/updatePlanningModuleProgress', { taskId: this.readId(taskId) ?? '' });
245
257
  if (!endpoint) {
246
258
  return this.backendError('Task progress update endpoint requires a valid levelId.');
247
259
  }
260
+ const requestBody = endpoint.mode === 'runtime'
261
+ ? { progress: this.toNullableNumber(payload.progress) ?? 0 }
262
+ : {
263
+ ...payload,
264
+ id: taskId,
265
+ ModuleType: payload.type ?? 'Task',
266
+ };
248
267
  return this.http
249
- .put(endpoint, {
250
- ...payload,
251
- id: taskId,
252
- ModuleType: payload.type ?? 'Task',
253
- }, {
268
+ .put(endpoint.url, requestBody, {
254
269
  headers: this.readHeaders(context, 'task-update-progress'),
255
270
  })
256
271
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to update task progress.')));
@@ -263,14 +278,21 @@ class TaskScheduleBackendAdapter {
263
278
  if (!levelId) {
264
279
  return this.backendError('Task import endpoint requires a valid levelId.');
265
280
  }
281
+ const levelDataId = this.readId(context.levelDataId);
266
282
  const schemaId = this.readId(context.schemaId);
267
- const endpoint = this.resolveApiUrl(context, this.readEndpoint(context.endpoints, 'importTasks') ?? 'tasks/mmp/import', {
283
+ const customTemplate = this.readEndpoint(context.endpoints, 'importTasks');
284
+ const template = customTemplate ?? 'tasks/mmp/import';
285
+ const endpoint = this.resolveApiUrl(context, template, {
268
286
  levelId,
287
+ ...(levelDataId ? { levelDataId } : {}),
269
288
  ...(schemaId ? { schemaId } : {}),
270
289
  });
271
290
  const formData = new FormData();
272
291
  formData.append('file', file, file.name);
273
292
  formData.append('levelId', levelId);
293
+ if (levelDataId) {
294
+ formData.append('levelDataId', levelDataId);
295
+ }
274
296
  return this.http
275
297
  .post(endpoint, formData, {
276
298
  headers: this.readHeaders(context, 'task-import'),
@@ -280,7 +302,9 @@ class TaskScheduleBackendAdapter {
280
302
  const tasks = rows
281
303
  .map((item, index) => this.mapRuntimeTask(item, index + 1))
282
304
  .filter((item) => !!item);
283
- const payload = raw && typeof raw === 'object' ? raw : {};
305
+ const payload = raw && typeof raw === 'object'
306
+ ? raw
307
+ : {};
284
308
  return {
285
309
  fileName: this.toNullableString(payload['fileName']) ??
286
310
  this.toNullableString(payload['name']) ??
@@ -312,13 +336,19 @@ class TaskScheduleBackendAdapter {
312
336
  if (!levelId) {
313
337
  return this.backendError('Set baseline endpoint requires a valid levelId.');
314
338
  }
339
+ const levelDataId = this.readId(context.levelDataId);
315
340
  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');
341
+ const customTemplate = this.readEndpoint(context.endpoints, 'setBaseline');
342
+ const template = customTemplate
343
+ ? customTemplate
344
+ : levelDataId
345
+ ? 'levels/{levelId}/{levelDataId}/schedule/baselines'
346
+ : schemaId
347
+ ? 'levels/{schemaId}/{levelId}/tasks/setBaseline'
348
+ : 'levels/{levelId}/tasks/setBaseline';
320
349
  const endpoint = this.resolveApiUrl(context, template, {
321
350
  levelId,
351
+ ...(levelDataId ? { levelDataId } : {}),
322
352
  ...(schemaId ? { schemaId } : {}),
323
353
  });
324
354
  return this.http
@@ -335,10 +365,17 @@ class TaskScheduleBackendAdapter {
335
365
  if (!levelId) {
336
366
  return this.backendError('Task export endpoint requires a valid levelId.');
337
367
  }
368
+ const levelDataId = this.readId(context.levelDataId);
338
369
  const schemaId = this.readId(context.schemaId);
339
- const endpoint = this.resolveApiUrl(context, this.readEndpoint(context.endpoints, 'exportTasks') ??
340
- 'tasks/levels/{levelId}/export', {
370
+ const customTemplate = this.readEndpoint(context.endpoints, 'exportTasks');
371
+ const template = customTemplate
372
+ ? customTemplate
373
+ : levelDataId
374
+ ? 'levels/{levelId}/{levelDataId}/schedule/mpp'
375
+ : 'tasks/levels/{levelId}/export';
376
+ const endpoint = this.resolveApiUrl(context, template, {
341
377
  levelId,
378
+ ...(levelDataId ? { levelDataId } : {}),
342
379
  ...(schemaId ? { schemaId } : {}),
343
380
  });
344
381
  return this.http.get(endpoint, {
@@ -346,6 +383,60 @@ class TaskScheduleBackendAdapter {
346
383
  responseType: 'blob',
347
384
  });
348
385
  }
386
+ mapRuntimeMutationPayload(payload) {
387
+ const mapped = { ...payload };
388
+ if (payload.startDate !== undefined) {
389
+ mapped['plannedStart'] = payload.startDate;
390
+ }
391
+ if (payload.finishDate !== undefined) {
392
+ mapped['plannedFinish'] = payload.finishDate;
393
+ }
394
+ return mapped;
395
+ }
396
+ mapRuntimeBulkUpdatePayload(payload) {
397
+ const items = payload.map((item) => {
398
+ const mapped = this.mapRuntimeMutationPayload(item);
399
+ const id = this.toTaskId(item['id']);
400
+ if (id !== null) {
401
+ mapped['id'] = id;
402
+ }
403
+ return mapped;
404
+ });
405
+ const type = this.resolveRuntimeScheduleItemType(payload[0]?.['type']);
406
+ return {
407
+ ...(type === null ? {} : { type }),
408
+ items,
409
+ };
410
+ }
411
+ mapRuntimeOrderUpdatePayload(payload) {
412
+ return {
413
+ items: payload.map((item) => ({
414
+ id: item.taskId,
415
+ order: item.order,
416
+ })),
417
+ };
418
+ }
419
+ resolveRuntimeScheduleItemType(value) {
420
+ if (typeof value === 'number' && Number.isFinite(value)) {
421
+ return value;
422
+ }
423
+ const normalized = String(value ?? '')
424
+ .trim()
425
+ .toLowerCase();
426
+ if (!normalized) {
427
+ return null;
428
+ }
429
+ if (normalized === 'task') {
430
+ return 0;
431
+ }
432
+ if (normalized === 'milestone') {
433
+ return 1;
434
+ }
435
+ if (normalized === 'deliverable') {
436
+ return 2;
437
+ }
438
+ return null;
439
+ }
349
440
  loadCustomColumns(context) {
350
441
  if (Array.isArray(context.customColumns)) {
351
442
  return of(context.customColumns);
@@ -380,7 +471,8 @@ class TaskScheduleBackendAdapter {
380
471
  })
381
472
  .pipe(map((response) => this.unwrapResponse(response, 'Failed to load schedule views.')));
382
473
  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')));
474
+ return views$.pipe(map((views) => views.find((view) => String(view.key ?? '').toLowerCase() ===
475
+ scheduleViewKey.toLowerCase())), map((view) => this.mapScheduleColumns(view?.columns ?? [], context.langCode ?? 'en')));
384
476
  }
385
477
  const settingsEndpoint = this.resolveScheduleManagerEndpoint(context, 'scheduleSettingsByLevel', '{scheduleManagerBase}/{levelId}/settings', { levelId });
386
478
  return this.http
@@ -417,6 +509,19 @@ class TaskScheduleBackendAdapter {
417
509
  if (customTreeRoute) {
418
510
  return customTreeRoute;
419
511
  }
512
+ const levelDataId = this.readId(context.levelDataId);
513
+ if (levelDataId) {
514
+ if (modelType === 'unscheduled') {
515
+ return 'levels/{levelId}/{levelDataId}/schedule/unscheduled';
516
+ }
517
+ if (modelType === 'phaseGate') {
518
+ return 'levels/{levelId}/{levelDataId}/schedule/tree?renderMode=PhaseGate';
519
+ }
520
+ if (modelType === 'resources') {
521
+ return 'levels/{levelId}/{levelDataId}/schedule/by-resource';
522
+ }
523
+ return 'levels/{levelId}/{levelDataId}/schedule/tree';
524
+ }
420
525
  if (this.readId(context.schemaId)) {
421
526
  if (modelType === 'baseline') {
422
527
  return 'tasks/{levelId}/GetAllBaseLine';
@@ -429,7 +534,16 @@ class TaskScheduleBackendAdapter {
429
534
  }
430
535
  return 'tasks/{levelId}/GetAll';
431
536
  }
432
- return 'levels/{levelId}/{levelDataId}/schedule/tree';
537
+ if (modelType === 'baseline') {
538
+ return 'tasks/{levelId}/GetAllBaseLine';
539
+ }
540
+ if (modelType === 'unscheduled') {
541
+ return 'tasks/{levelId}/unscheduled';
542
+ }
543
+ if (modelType === 'phaseGate') {
544
+ return 'tasks/{levelId}/GetAll?RenderMode=PhaseGate';
545
+ }
546
+ return 'tasks/{levelId}/GetAll';
433
547
  }
434
548
  buildTreeRouteParams(context, treeRouteTemplate) {
435
549
  const levelId = this.readId(context.levelId);
@@ -453,19 +567,40 @@ class TaskScheduleBackendAdapter {
453
567
  }
454
568
  return params;
455
569
  }
456
- resolveTaskMutationEndpoint(context, endpointKey, fallbackTemplate, legacyTemplateWithSchema, extraParams) {
570
+ resolveTaskMutationEndpoint(context, endpointKey, runtimeTemplate, legacyTemplate, legacyTemplateWithSchema, extraParams) {
457
571
  const levelId = this.readId(context.levelId);
458
572
  if (!levelId) {
459
573
  return null;
460
574
  }
575
+ const levelDataId = this.readId(context.levelDataId);
461
576
  const schemaId = this.readId(context.schemaId);
462
- const template = this.readEndpoint(context.endpoints, endpointKey) ??
463
- (schemaId ? legacyTemplateWithSchema : fallbackTemplate);
464
- return this.resolveApiUrl(context, template, {
577
+ const customTemplate = this.readEndpoint(context.endpoints, endpointKey);
578
+ const params = {
465
579
  levelId,
580
+ ...(levelDataId ? { levelDataId } : {}),
466
581
  ...(schemaId ? { schemaId } : {}),
467
582
  ...extraParams,
468
- });
583
+ };
584
+ if (customTemplate) {
585
+ const normalizedTemplate = customTemplate.replace(/\\/g, '/');
586
+ const isRuntimeTemplate = customTemplate.includes('{levelDataId}') ||
587
+ (levelDataId !== null &&
588
+ /levels\/\{levelId\}\/.+\/(schedule|tasks|milestones|deliverables)/i.test(normalizedTemplate));
589
+ return {
590
+ url: this.resolveApiUrl(context, customTemplate, params),
591
+ mode: isRuntimeTemplate ? 'runtime' : 'legacy',
592
+ };
593
+ }
594
+ if (levelDataId) {
595
+ return {
596
+ url: this.resolveApiUrl(context, runtimeTemplate, params),
597
+ mode: 'runtime',
598
+ };
599
+ }
600
+ return {
601
+ url: this.resolveApiUrl(context, schemaId ? legacyTemplateWithSchema : legacyTemplate, params),
602
+ mode: 'legacy',
603
+ };
469
604
  }
470
605
  resolveApplyImportedTasksEndpoint(context) {
471
606
  const levelId = this.readId(context.levelId);
@@ -474,14 +609,18 @@ class TaskScheduleBackendAdapter {
474
609
  }
475
610
  const custom = this.readEndpoint(context.endpoints, 'applyImportedTasks');
476
611
  if (custom) {
612
+ const levelDataId = this.readId(context.levelDataId);
477
613
  const schemaId = this.readId(context.schemaId);
478
614
  return this.resolveApiUrl(context, custom, {
479
615
  levelId,
616
+ ...(levelDataId ? { levelDataId } : {}),
480
617
  ...(schemaId ? { schemaId } : {}),
481
618
  });
482
619
  }
483
620
  const schemaId = this.readId(context.schemaId);
484
- const template = schemaId ? 'tasks/{schemaId}/{levelId}' : 'tasks/{levelId}/import';
621
+ const template = schemaId
622
+ ? 'tasks/{schemaId}/{levelId}'
623
+ : 'tasks/{levelId}/import';
485
624
  return this.resolveApiUrl(context, template, {
486
625
  levelId,
487
626
  ...(schemaId ? { schemaId } : {}),
@@ -535,7 +674,8 @@ class TaskScheduleBackendAdapter {
535
674
  return headers;
536
675
  }
537
676
  buildIdempotencyKey(seed) {
538
- if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
677
+ if (typeof crypto !== 'undefined' &&
678
+ typeof crypto.randomUUID === 'function') {
539
679
  return `${seed}-${crypto.randomUUID()}`;
540
680
  }
541
681
  return `${seed}-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
@@ -555,7 +695,7 @@ class TaskScheduleBackendAdapter {
555
695
  }
556
696
  extractTaskArray(payload) {
557
697
  if (Array.isArray(payload)) {
558
- return payload;
698
+ return this.normalizeTaskRows(payload);
559
699
  }
560
700
  if (!payload || typeof payload !== 'object') {
561
701
  return [];
@@ -571,7 +711,7 @@ class TaskScheduleBackendAdapter {
571
711
  ];
572
712
  for (const candidate of candidates) {
573
713
  if (Array.isArray(candidate)) {
574
- return candidate;
714
+ return this.normalizeTaskRows(candidate);
575
715
  }
576
716
  }
577
717
  if (source['id'] !== undefined || source['Id'] !== undefined) {
@@ -579,6 +719,145 @@ class TaskScheduleBackendAdapter {
579
719
  }
580
720
  return [];
581
721
  }
722
+ normalizeTaskRows(rows) {
723
+ const resourceRows = this.flattenResourceGroups(rows);
724
+ return resourceRows ?? rows;
725
+ }
726
+ flattenResourceGroups(rows) {
727
+ const mergedById = new Map();
728
+ const unmatchedRows = [];
729
+ let hasResourceGroups = false;
730
+ rows.forEach((row) => {
731
+ if (!row || typeof row !== 'object') {
732
+ return;
733
+ }
734
+ const group = row;
735
+ const groupItems = this.firstDefined(group, ['items', 'Items']);
736
+ if (!Array.isArray(groupItems)) {
737
+ return;
738
+ }
739
+ const isResourceGroup = group['userId'] !== undefined ||
740
+ group['UserId'] !== undefined ||
741
+ group['displayName'] !== undefined ||
742
+ group['DisplayName'] !== undefined;
743
+ if (!isResourceGroup) {
744
+ return;
745
+ }
746
+ hasResourceGroups = true;
747
+ const groupUserId = this.toTaskId(this.firstDefined(group, ['userId', 'UserId']));
748
+ const groupDisplayName = this.toNullableString(this.firstDefined(group, [
749
+ 'displayName',
750
+ 'DisplayName',
751
+ 'name',
752
+ 'Name',
753
+ ]));
754
+ groupItems.forEach((item) => {
755
+ if (!item || typeof item !== 'object') {
756
+ return;
757
+ }
758
+ const taskRow = { ...item };
759
+ this.attachGroupResource(taskRow, groupUserId, groupDisplayName);
760
+ const id = this.toTaskId(this.firstDefined(taskRow, ['id', 'Id', 'taskId', 'TaskId']));
761
+ if (id === null) {
762
+ unmatchedRows.push(taskRow);
763
+ return;
764
+ }
765
+ const key = String(id);
766
+ const existing = mergedById.get(key);
767
+ if (!existing) {
768
+ mergedById.set(key, taskRow);
769
+ return;
770
+ }
771
+ this.mergeTaskResources(existing, taskRow);
772
+ if (existing['assignedTo'] === undefined &&
773
+ taskRow['assignedTo'] !== undefined) {
774
+ existing['assignedTo'] = taskRow['assignedTo'];
775
+ }
776
+ if (existing['AssignedTo'] === undefined &&
777
+ taskRow['AssignedTo'] !== undefined) {
778
+ existing['AssignedTo'] = taskRow['AssignedTo'];
779
+ }
780
+ });
781
+ });
782
+ if (!hasResourceGroups) {
783
+ return null;
784
+ }
785
+ return [...mergedById.values(), ...unmatchedRows];
786
+ }
787
+ attachGroupResource(taskRow, groupUserId, groupDisplayName) {
788
+ if (groupUserId === null) {
789
+ return;
790
+ }
791
+ const existingResourcesCandidate = this.firstDefined(taskRow, [
792
+ 'resources',
793
+ 'Resources',
794
+ ]);
795
+ const existingResources = Array.isArray(existingResourcesCandidate)
796
+ ? [...existingResourcesCandidate]
797
+ : [];
798
+ const hasResource = existingResources.some((resource) => this.resolveResourceIdentity(resource) === String(groupUserId));
799
+ if (!hasResource) {
800
+ existingResources.push({
801
+ resourceId: groupUserId,
802
+ resourceName: groupDisplayName ?? String(groupUserId),
803
+ });
804
+ }
805
+ taskRow['resources'] = existingResources;
806
+ if (taskRow['assignedTo'] === undefined &&
807
+ taskRow['AssignedTo'] === undefined) {
808
+ taskRow['assignedTo'] = groupUserId;
809
+ }
810
+ }
811
+ mergeTaskResources(target, source) {
812
+ const targetResourcesCandidate = this.firstDefined(target, [
813
+ 'resources',
814
+ 'Resources',
815
+ ]);
816
+ const sourceResourcesCandidate = this.firstDefined(source, [
817
+ 'resources',
818
+ 'Resources',
819
+ ]);
820
+ const targetResources = Array.isArray(targetResourcesCandidate)
821
+ ? [...targetResourcesCandidate]
822
+ : [];
823
+ const sourceResources = Array.isArray(sourceResourcesCandidate)
824
+ ? sourceResourcesCandidate
825
+ : [];
826
+ sourceResources.forEach((resource) => {
827
+ const sourceId = this.resolveResourceIdentity(resource);
828
+ if (!sourceId) {
829
+ return;
830
+ }
831
+ const exists = targetResources.some((targetResource) => this.resolveResourceIdentity(targetResource) === sourceId);
832
+ if (!exists) {
833
+ targetResources.push(resource);
834
+ }
835
+ });
836
+ if (targetResources.length) {
837
+ target['resources'] = targetResources;
838
+ }
839
+ }
840
+ resolveResourceIdentity(resource) {
841
+ if (resource === null || resource === undefined) {
842
+ return null;
843
+ }
844
+ if (typeof resource === 'string' || typeof resource === 'number') {
845
+ return String(resource);
846
+ }
847
+ if (typeof resource !== 'object') {
848
+ return null;
849
+ }
850
+ const row = resource;
851
+ const id = this.toTaskId(this.firstDefined(row, [
852
+ 'resourceId',
853
+ 'ResourceId',
854
+ 'userId',
855
+ 'UserId',
856
+ 'id',
857
+ 'Id',
858
+ ]));
859
+ return id === null ? null : String(id);
860
+ }
582
861
  mapRuntimeTask(payload, fallbackOrder) {
583
862
  if (!payload || typeof payload !== 'object') {
584
863
  return null;
@@ -588,9 +867,20 @@ class TaskScheduleBackendAdapter {
588
867
  if (id === null) {
589
868
  return null;
590
869
  }
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']));
870
+ const type = String(this.firstDefined(source, [
871
+ 'type',
872
+ 'Type',
873
+ 'typeLable',
874
+ 'TypeLable',
875
+ 'typeLabel',
876
+ 'TypeLabel',
877
+ ]) ?? 'Task');
878
+ const assignee = this.extractAssignee(this.firstDefined(source, [
879
+ 'assignedTo',
880
+ 'AssignedTo',
881
+ 'createdBy',
882
+ 'CreatedBy',
883
+ ]));
594
884
  const resources = this.extractTaskResources(this.firstDefined(source, ['resources', 'Resources']), assignee);
595
885
  const subtasksRaw = this.firstDefined(source, [
596
886
  'subtasks',
@@ -645,9 +935,24 @@ class TaskScheduleBackendAdapter {
645
935
  'baselineFinish',
646
936
  'BaselineFinish',
647
937
  ])),
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'])),
938
+ actualStartDate: this.extractDate(this.firstDefined(source, [
939
+ 'actualStartDate',
940
+ 'ActualStartDate',
941
+ 'actualStart',
942
+ 'ActualStart',
943
+ ])),
944
+ actualFinishDate: this.extractDate(this.firstDefined(source, [
945
+ 'actualFinishDate',
946
+ 'ActualFinishDate',
947
+ 'actualFinish',
948
+ 'ActualFinish',
949
+ ])),
950
+ predecessor: this.toNullableString(this.firstDefined(source, [
951
+ 'predecessor',
952
+ 'Predecessor',
953
+ 'predecessors',
954
+ 'Predecessors',
955
+ ])),
651
956
  duration: this.toNullableNumber(this.firstDefined(source, ['duration', 'Duration'])),
652
957
  progress: this.extractProgress(this.firstDefined(source, ['progress', 'Progress'])),
653
958
  details: this.toNullableString(this.firstDefined(source, ['details', 'Details', 'description'])),
@@ -801,8 +1106,7 @@ class TaskScheduleBackendAdapter {
801
1106
  id: typeof id === 'number' || typeof id === 'string' ? id : String(id),
802
1107
  key,
803
1108
  name: this.toNullableString(row['name'] ?? row['displayName'] ?? row['Name']) ?? key,
804
- viewType: this.toNullableString(row['viewType'] ?? row['type'] ?? row['ViewType']) ??
805
- 'Text',
1109
+ viewType: this.toNullableString(row['viewType'] ?? row['type'] ?? row['ViewType']) ?? 'Text',
806
1110
  normalizedKey: this.toNullableString(row['normalizedKey'] ?? row['NormalizedKey']) ??
807
1111
  undefined,
808
1112
  isRequired: Boolean(row['isRequired'] ?? row['required']),
@@ -824,11 +1128,7 @@ class TaskScheduleBackendAdapter {
824
1128
  return;
825
1129
  }
826
1130
  const row = item;
827
- const optionValue = row['value'] ??
828
- row['id'] ??
829
- row['key'] ??
830
- row['name'] ??
831
- row['text'];
1131
+ const optionValue = row['value'] ?? row['id'] ?? row['key'] ?? row['name'] ?? row['text'];
832
1132
  const optionText = this.toNullableString(row['text'] ?? row['name'] ?? row['displayName'] ?? row['label']);
833
1133
  if (optionValue === undefined || optionValue === null || !optionText) {
834
1134
  return;
@@ -902,7 +1202,10 @@ class TaskScheduleBackendAdapter {
902
1202
  }
903
1203
  if (value && typeof value === 'object') {
904
1204
  const row = value;
905
- return this.toNullableString(row['displayName'] ?? row['resourceName'] ?? row['userName'] ?? row['name']);
1205
+ return this.toNullableString(row['displayName'] ??
1206
+ row['resourceName'] ??
1207
+ row['userName'] ??
1208
+ row['name']);
906
1209
  }
907
1210
  return null;
908
1211
  };
@@ -922,10 +1225,7 @@ class TaskScheduleBackendAdapter {
922
1225
  return;
923
1226
  }
924
1227
  const obj = resource;
925
- const id = obj['resourceId'] ??
926
- obj['id'] ??
927
- obj['userId'] ??
928
- obj['value'];
1228
+ const id = obj['resourceId'] ?? obj['id'] ?? obj['userId'] ?? obj['value'];
929
1229
  if (id === undefined || id === null) {
930
1230
  return;
931
1231
  }
@@ -1018,7 +1318,8 @@ class TaskScheduleBackendAdapter {
1018
1318
  }
1019
1319
  return {
1020
1320
  resourceId,
1021
- unit: this.toNullableNumber(row['unit'] ?? row['resourceUnit']) ?? undefined,
1321
+ unit: this.toNullableNumber(row['unit'] ?? row['resourceUnit']) ??
1322
+ undefined,
1022
1323
  };
1023
1324
  })
1024
1325
  .filter((item) => item !== null);
@@ -1872,11 +2173,11 @@ class TaskScheduleTaskbarTemplate {
1872
2173
  data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
1873
2174
  langCode = input('en', ...(ngDevMode ? [{ debugName: "langCode" }] : []));
1874
2175
  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 }] });
2176
+ 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
2177
  }
1877
2178
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleTaskbarTemplate, decorators: [{
1878
2179
  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"] }]
2180
+ 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
2181
  }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], langCode: [{ type: i0.Input, args: [{ isSignal: true, alias: "langCode", required: false }] }] } });
1881
2182
 
1882
2183
  const EMPTY_RESULT = { tasks: [] };
@@ -2897,7 +3198,7 @@ class TaskSchedule {
2897
3198
  ToolbarService,
2898
3199
  ContextMenuService,
2899
3200
  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"] }] });
3201
+ ], viewQueries: [{ propertyName: "ganttObj", first: true, predicate: ["ganttObj"], descendants: true }], ngImport: i0, template: "@if (!loading()) {\r\n <ejs-gantt\r\n #ganttObj\r\n [id]=\"ganttId\"\r\n [enableVirtualization]=\"true\"\r\n [enableTimelineVirtualization]=\"true\"\r\n [enableVirtualMaskRow]=\"false\"\r\n [allowResizing]=\"true\"\r\n [enableRtl]=\"enableRtl()\"\r\n [locale]=\"locale()\"\r\n [height]=\"height()\"\r\n [dataSource]=\"dataSource()\"\r\n [taskFields]=\"ganttConfig().taskFields\"\r\n [columns]=\"ganttConfig().columns\"\r\n [renderBaseline]=\"ganttConfig().renderBaseline\"\r\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\r\n [allowSelection]=\"true\"\r\n [labelSettings]=\"ganttConfig().labelSettings\"\r\n [treeColumnIndex]=\"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]=\"dateFormat()\"\r\n [allowSorting]=\"true\"\r\n [holidays]=\"ganttConfig().holidays\"\r\n [enableWBS]=\"true\"\r\n [enableAutoWbsUpdate]=\"true\"\r\n [allowReordering]=\"true\"\r\n (toolbarClick)=\"onToolbarClick($event)\"\r\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\r\n (contextMenuClick)=\"onContextMenuClick($event)\"\r\n (actionBegin)=\"onActionBegin($event)\"\r\n (actionComplete)=\"onActionComplete($event)\"\r\n (cellEdit)=\"onCellEdit($event)\"\r\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\r\n (dataBound)=\"onDataBound()\"\r\n >\r\n <ng-template #tooltipSettingsTaskbar let-data>\r\n <div class=\"px-2 py-1 text-xs\">\r\n <div class=\"font-medium\">{{ data?.title ?? '-' }}</div>\r\n <div>\r\n {{ tooltipTranslations().startsOn }}:\r\n {{ 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
3202
  }
2902
3203
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskSchedule, decorators: [{
2903
3204
  type: Component,
@@ -2913,7 +3214,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImpor
2913
3214
  ToolbarService,
2914
3215
  ContextMenuService,
2915
3216
  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"] }]
3217
+ ], template: "@if (!loading()) {\r\n <ejs-gantt\r\n #ganttObj\r\n [id]=\"ganttId\"\r\n [enableVirtualization]=\"true\"\r\n [enableTimelineVirtualization]=\"true\"\r\n [enableVirtualMaskRow]=\"false\"\r\n [allowResizing]=\"true\"\r\n [enableRtl]=\"enableRtl()\"\r\n [locale]=\"locale()\"\r\n [height]=\"height()\"\r\n [dataSource]=\"dataSource()\"\r\n [taskFields]=\"ganttConfig().taskFields\"\r\n [columns]=\"ganttConfig().columns\"\r\n [renderBaseline]=\"ganttConfig().renderBaseline\"\r\n [enableCriticalPath]=\"ganttConfig().enableCriticalPath\"\r\n [allowSelection]=\"true\"\r\n [labelSettings]=\"ganttConfig().labelSettings\"\r\n [treeColumnIndex]=\"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]=\"dateFormat()\"\r\n [allowSorting]=\"true\"\r\n [holidays]=\"ganttConfig().holidays\"\r\n [enableWBS]=\"true\"\r\n [enableAutoWbsUpdate]=\"true\"\r\n [allowReordering]=\"true\"\r\n (toolbarClick)=\"onToolbarClick($event)\"\r\n (contextMenuOpen)=\"onContextMenuOpen($event)\"\r\n (contextMenuClick)=\"onContextMenuClick($event)\"\r\n (actionBegin)=\"onActionBegin($event)\"\r\n (actionComplete)=\"onActionComplete($event)\"\r\n (cellEdit)=\"onCellEdit($event)\"\r\n (queryTaskbarInfo)=\"onQueryTaskbarInfo($event)\"\r\n (dataBound)=\"onDataBound()\"\r\n >\r\n <ng-template #tooltipSettingsTaskbar let-data>\r\n <div class=\"px-2 py-1 text-xs\">\r\n <div class=\"font-medium\">{{ data?.title ?? '-' }}</div>\r\n <div>\r\n {{ tooltipTranslations().startsOn }}:\r\n {{ 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
3218
  }], propDecorators: { ganttObj: [{
2918
3219
  type: ViewChild,
2919
3220
  args: ['ganttObj']
@@ -3501,11 +3802,11 @@ class TaskScheduleImportModal {
3501
3802
  this.failed.emit(message);
3502
3803
  }
3503
3804
  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"] }] });
3805
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleImportModal, isStandalone: true, selector: "mt-task-schedule-import-modal", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", imported: "imported", applied: "applied", failed: "failed" }, ngImport: i0, template: "@if (visible()) {\r\n <div class=\"fixed inset-0 z-[1000] grid place-items-center bg-slate-900/40 p-4\">\r\n <section\r\n class=\"w-full max-w-6xl overflow-hidden rounded-2xl bg-white shadow-2xl ring-1 ring-slate-200\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n >\r\n <header class=\"flex items-center justify-between border-b border-slate-200 px-5 py-4\">\r\n <h2 class=\"text-base font-semibold text-slate-900\">\r\n {{ title() || labels().title }}\r\n </h2>\r\n\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [text]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n </header>\r\n\r\n <div class=\"space-y-4 p-5\">\r\n <div class=\"rounded-xl border border-slate-200 bg-slate-50 p-4\">\r\n <div class=\"flex flex-wrap items-center gap-3\">\r\n <label\r\n class=\"inline-flex cursor-pointer items-center rounded-lg border border-dashed border-slate-300 bg-white px-4 py-2 text-sm text-slate-700 hover:border-slate-400\"\r\n >\r\n <span>{{ labels().selectFile }}</span>\r\n <input\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n </label>\r\n\r\n <span class=\"max-w-[22rem] truncate text-sm text-slate-500\">\r\n {{ selectedFile()?.name || '-' }}\r\n </span>\r\n\r\n <mt-button\r\n [label]=\"labels().startImport\"\r\n [disabled]=\"!canImport()\"\r\n [loading]=\"loadingImport()\"\r\n (onClick)=\"importFile()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (importResult(); as result) {\r\n @if (!previewRows().length) {\r\n <div class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\">\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"overflow-hidden rounded-xl border border-slate-200\">\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] border-b border-slate-200 bg-slate-100 px-3 py-2 text-xs font-semibold uppercase tracking-wide text-slate-600\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"allSelected()\"\r\n (change)=\"selectAllRows($any($event.target).checked)\"\r\n />\r\n </label>\r\n <div>{{ labels().task }}</div>\r\n <div>{{ labels().startDate }}</div>\r\n <div>{{ labels().finishDate }}</div>\r\n <div>{{ labels().actualStartDate }}</div>\r\n <div>{{ labels().actualFinishDate }}</div>\r\n <div>{{ labels().assignedTo }}</div>\r\n <div>{{ labels().progress }}</div>\r\n </div>\r\n\r\n <div class=\"max-h-[28rem] overflow-auto\">\r\n @for (row of previewRows(); track trackByRow($index, row)) {\r\n <div class=\"grid min-w-[1180px] grid-cols-[40px_minmax(220px,2fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(130px,1fr)_minmax(190px,1.1fr)_minmax(120px,0.8fr)] items-center gap-x-2 border-b border-slate-100 px-3 py-2 text-sm\">\r\n <label class=\"inline-flex items-center justify-center\">\r\n <input\r\n type=\"checkbox\"\r\n [checked]=\"selectedTaskKeys().has(row.key)\"\r\n (change)=\"toggleRowSelection(row.key, $any($event.target).checked)\"\r\n />\r\n </label>\r\n\r\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"text\"\r\n [value]=\"row.task.title || row.task.name || ''\"\r\n (input)=\"onTaskTitleChanged(row.key, $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.startDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'startDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.finishDate)\"\r\n (change)=\"onTaskDateChanged(row.key, 'finishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualStartDate || row.task.actualStart)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualStartDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div>\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"date\"\r\n [value]=\"toDateInputValue(row.task.actualFinishDate || row.task.actualFinish)\"\r\n (change)=\"onTaskDateChanged(row.key, 'actualFinishDate', $any($event.target).value)\"\r\n />\r\n </div>\r\n\r\n <div class=\"min-w-0\">\r\n @if (resourceOptions().length) {\r\n <div class=\"space-y-1\">\r\n <select\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n [value]=\"resolveAssignedValue(row.task)\"\r\n (change)=\"onTaskAssignedToChanged(row.key, $any($event.target).value)\"\r\n >\r\n <option value=\"\">-</option>\r\n @for (option of resourceOptions(); track option.id) {\r\n <option [value]=\"option.id\">{{ option.label }}</option>\r\n }\r\n </select>\r\n @if (row.task.assignedTo) {\r\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\r\n }\r\n </div>\r\n } @else if (row.task.assignedTo) {\r\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\r\n } @else {\r\n <span class=\"text-slate-400\">-</span>\r\n }\r\n </div>\r\n\r\n <div>\r\n <div class=\"space-y-1\">\r\n <input\r\n class=\"w-full rounded-md border border-slate-300 px-2 py-1 text-sm text-slate-700 outline-none focus:border-slate-400\"\r\n type=\"number\"\r\n min=\"0\"\r\n max=\"100\"\r\n [value]=\"normalizeProgress(row.task.progress)\"\r\n (input)=\"onTaskProgressChanged(row.key, $any($event.target).value)\"\r\n />\r\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\r\n </div>\r\n </div>\r\n </div>\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-slate-500\">{{ labels().rowsLimited }}</p>\r\n }\r\n }\r\n }\r\n </div>\r\n\r\n <footer class=\"flex flex-wrap items-center justify-end gap-2 border-t border-slate-200 px-5 py-4\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n severity=\"secondary\"\r\n [outlined]=\"true\"\r\n (onClick)=\"close()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().replace\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(true)\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().append\"\r\n severity=\"secondary\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(false)\"\r\n />\r\n </footer>\r\n </section>\r\n </div>\r\n}\r\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data"] }] });
3505
3806
  }
3506
3807
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleImportModal, decorators: [{
3507
3808
  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"] }]
3809
+ 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"] }]
3509
3810
  }], 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"] }] } });
3510
3811
 
3511
3812
  const DEFAULT_MODES = [
@@ -3717,11 +4018,11 @@ class TaskScheduleShell {
3717
4018
  this.actionError.emit(message);
3718
4019
  }
3719
4020
  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"] }] });
4021
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: TaskScheduleShell, isStandalone: true, selector: "mt-task-schedule-shell", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, 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'\">\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\r\n [modelType]=\"currentModelType()\"\r\n [context]=\"context()\"\r\n [langCode]=\"resolvedLangCode()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [height]=\"height()\"\r\n (loadError)=\"onActionError($event)\"\r\n />\r\n\r\n @if (showImportModal()) {\r\n <mt-task-schedule-import-modal\r\n [visible]=\"showImportModal()\"\r\n [context]=\"context()\"\r\n [langCode]=\"resolvedLangCode()\"\r\n (closed)=\"closeImportModal()\"\r\n (failed)=\"onActionError($event)\"\r\n (applied)=\"onImportedTasksApplied()\"\r\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: ["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"] }] });
3721
4022
  }
3722
4023
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: TaskScheduleShell, decorators: [{
3723
4024
  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"] }]
4025
+ args: [{ selector: 'mt-task-schedule-shell', standalone: true, imports: [CommonModule, TaskSchedule, TaskScheduleImportModal], template: "<div class=\"task-schedule-shell\" [attr.dir]=\"resolvedLangCode() === 'ar' ? 'rtl' : 'ltr'\">\r\n <header class=\"task-schedule-shell__header\">\r\n <div class=\"task-schedule-shell__mode\">\r\n <label class=\"task-schedule-shell__label\">{{ labels().mode }}</label>\r\n <select\r\n class=\"task-schedule-shell__select\"\r\n [value]=\"currentModelType()\"\r\n (change)=\"onModeChange($any($event.target).value)\"\r\n >\r\n @for (mode of resolvedModes(); track mode.value) {\r\n <option [value]=\"mode.value\">{{ mode.label }}</option>\r\n }\r\n </select>\r\n </div>\r\n\r\n <div class=\"task-schedule-shell__actions\">\r\n @if (showSetBaselineAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canSetBaselineAction()\"\r\n (click)=\"setBaseline()\"\r\n >\r\n {{ baselinePending() ? labels().pending : labels().setBaseline }}\r\n </button>\r\n }\r\n\r\n @if (showImportAction()) {\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canOpenImport()\"\r\n (click)=\"openImportModal()\"\r\n >\r\n {{ labels().import }}\r\n </button>\r\n }\r\n\r\n <button\r\n type=\"button\"\r\n class=\"task-schedule-shell__btn\"\r\n [disabled]=\"!canExportTasks()\"\r\n (click)=\"exportTasks()\"\r\n >\r\n {{ labels().export }}\r\n </button>\r\n </div>\r\n </header>\r\n\r\n <mt-task-schedule\r\n [modelType]=\"currentModelType()\"\r\n [context]=\"context()\"\r\n [langCode]=\"resolvedLangCode()\"\r\n [dateFormat]=\"dateFormat()\"\r\n [height]=\"height()\"\r\n (loadError)=\"onActionError($event)\"\r\n />\r\n\r\n @if (showImportModal()) {\r\n <mt-task-schedule-import-modal\r\n [visible]=\"showImportModal()\"\r\n [context]=\"context()\"\r\n [langCode]=\"resolvedLangCode()\"\r\n (closed)=\"closeImportModal()\"\r\n (failed)=\"onActionError($event)\"\r\n (applied)=\"onImportedTasksApplied()\"\r\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"] }]
3725
4026
  }], 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"] }] } });
3726
4027
 
3727
4028
  /**