@masterteam/task-schedule 0.0.17 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CommonModule } from '@angular/common';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { inject, Injectable, viewChild, input, signal, computed, effect, Component,
|
|
3
|
+
import { inject, Injectable, viewChild, input, signal, computed, effect, Component, Injector, output, ViewChild } from '@angular/core';
|
|
4
4
|
import * as i1$1 from '@syncfusion/ej2-angular-gantt';
|
|
5
5
|
import { GanttModule, DayMarkersService, EditService, ExcelExportService, FilterService, CriticalPathService, PdfExportService, RowDDService, SelectionService, SortService, ToolbarService, ContextMenuService, ResizeService } from '@syncfusion/ej2-angular-gantt';
|
|
6
6
|
import { switchMap, of, map, timeout, catchError, throwError, finalize, Subject, Subscription } from 'rxjs';
|
|
@@ -18,10 +18,8 @@ import { SelectField } from '@masterteam/components/select-field';
|
|
|
18
18
|
import { ClientForm } from '@masterteam/forms/client-form';
|
|
19
19
|
import { toSignal } from '@angular/core/rxjs-interop';
|
|
20
20
|
import { CheckboxField } from '@masterteam/components/checkbox-field';
|
|
21
|
-
import { DateField } from '@masterteam/components/date-field';
|
|
22
|
-
import { EntityPreview } from '@masterteam/components/entities';
|
|
23
|
-
import { NumberField } from '@masterteam/components/number-field';
|
|
24
21
|
import { TextField } from '@masterteam/components/text-field';
|
|
22
|
+
import { Tree } from '@masterteam/components/tree';
|
|
25
23
|
|
|
26
24
|
function normalizeTaskScheduleModelType(modelType) {
|
|
27
25
|
const normalized = String(modelType ?? '')
|
|
@@ -133,6 +131,7 @@ const NATIVE_PROPERTY_ALIAS_TARGETS = {
|
|
|
133
131
|
};
|
|
134
132
|
const DEFAULT_MPP_REQUEST_TIMEOUT_MS$1 = 300_000;
|
|
135
133
|
const DEFAULT_MPP_PREVIEW_MAX_ROWS = 400;
|
|
134
|
+
const DEFAULT_MPP_PREVIEW_MAX_RESPONSE_BYTES = 5_000_000;
|
|
136
135
|
class TaskScheduleFetchService {
|
|
137
136
|
http = inject(HttpClient);
|
|
138
137
|
load(modelType, context) {
|
|
@@ -156,10 +155,11 @@ class TaskScheduleFetchService {
|
|
|
156
155
|
'levels/{levelId}/{levelDataId}/schedule/mpp', { levelId, levelDataId });
|
|
157
156
|
const formData = new FormData();
|
|
158
157
|
formData.append('file', file, file.name);
|
|
159
|
-
return this.
|
|
160
|
-
.post(endpoint, formData)
|
|
161
|
-
.pipe(timeout(this.resolveMppRequestTimeoutMs(context)))).pipe(map((payload) => ({
|
|
158
|
+
return this.http.post(endpoint, formData, { responseType: 'text' }).pipe(timeout(this.resolveMppRequestTimeoutMs(context)), map((responseText) => this.parseImportResponseText(responseText, context, file.name)), map((payload) => ({
|
|
162
159
|
fileName: this.toNullableString(this.readObjectValue(payload, ['fileName', 'name'])) ?? file.name,
|
|
160
|
+
applied: payload === null ||
|
|
161
|
+
payload === undefined ||
|
|
162
|
+
this.isImportAppliedMarker(payload),
|
|
163
163
|
tasks: this.mapLooseTasks(this.extractTaskRows(payload), [], context.langCode === 'ar' ? 'ar' : 'en', new Map(), this.resolveMppPreviewMaxRows(context)),
|
|
164
164
|
raw: context.mppKeepRawPayload ? payload : undefined,
|
|
165
165
|
})));
|
|
@@ -708,7 +708,12 @@ class TaskScheduleFetchService {
|
|
|
708
708
|
'');
|
|
709
709
|
}
|
|
710
710
|
readData(request$) {
|
|
711
|
-
return request$.pipe(map((response) =>
|
|
711
|
+
return request$.pipe(map((response) => {
|
|
712
|
+
if (response === null || response === undefined) {
|
|
713
|
+
return response;
|
|
714
|
+
}
|
|
715
|
+
return response.data;
|
|
716
|
+
}), catchError((error) => {
|
|
712
717
|
const message = error?.error?.message ??
|
|
713
718
|
error?.message ??
|
|
714
719
|
error?.statusText ??
|
|
@@ -740,6 +745,42 @@ class TaskScheduleFetchService {
|
|
|
740
745
|
? Math.floor(value) + 1
|
|
741
746
|
: DEFAULT_MPP_PREVIEW_MAX_ROWS + 1;
|
|
742
747
|
}
|
|
748
|
+
resolveMppPreviewMaxResponseBytes(context) {
|
|
749
|
+
const value = Number(context.mppPreviewMaxResponseBytes);
|
|
750
|
+
return Number.isFinite(value) && value > 0
|
|
751
|
+
? Math.floor(value)
|
|
752
|
+
: DEFAULT_MPP_PREVIEW_MAX_RESPONSE_BYTES;
|
|
753
|
+
}
|
|
754
|
+
parseImportResponseText(responseText, context, fileName) {
|
|
755
|
+
const text = String(responseText ?? '').trim();
|
|
756
|
+
if (!text) {
|
|
757
|
+
return null;
|
|
758
|
+
}
|
|
759
|
+
if (text.length > this.resolveMppPreviewMaxResponseBytes(context)) {
|
|
760
|
+
return {
|
|
761
|
+
fileName,
|
|
762
|
+
applied: true,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
try {
|
|
766
|
+
const parsed = JSON.parse(text);
|
|
767
|
+
if (this.isObject(parsed) &&
|
|
768
|
+
Object.prototype.hasOwnProperty.call(parsed, 'data')) {
|
|
769
|
+
return parsed['data'];
|
|
770
|
+
}
|
|
771
|
+
return parsed;
|
|
772
|
+
}
|
|
773
|
+
catch {
|
|
774
|
+
return {
|
|
775
|
+
fileName,
|
|
776
|
+
applied: true,
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
isImportAppliedMarker(payload) {
|
|
781
|
+
return (this.isObject(payload) &&
|
|
782
|
+
(payload['applied'] === true || payload['imported'] === true));
|
|
783
|
+
}
|
|
743
784
|
readEndpoint(context, key) {
|
|
744
785
|
const value = context.endpoints?.[key];
|
|
745
786
|
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
@@ -1762,7 +1803,12 @@ class TaskScheduleActionService {
|
|
|
1762
1803
|
return assigneeId === null ? [] : [{ resourceId: assigneeId }];
|
|
1763
1804
|
}
|
|
1764
1805
|
readData(request$) {
|
|
1765
|
-
return request$.pipe(map((response) =>
|
|
1806
|
+
return request$.pipe(map((response) => {
|
|
1807
|
+
if (response === null || response === undefined) {
|
|
1808
|
+
return response;
|
|
1809
|
+
}
|
|
1810
|
+
return response.data;
|
|
1811
|
+
}), catchError((error) => {
|
|
1766
1812
|
const message = error?.error?.message ??
|
|
1767
1813
|
error?.message ??
|
|
1768
1814
|
error?.statusText ??
|
|
@@ -2630,14 +2676,6 @@ class TaskScheduleImportDialog {
|
|
|
2630
2676
|
fetchService = inject(TaskScheduleFetchService);
|
|
2631
2677
|
actionService = inject(TaskScheduleActionService);
|
|
2632
2678
|
transloco = inject(TranslocoService);
|
|
2633
|
-
selectionCellTpl = viewChild.required('selectionCellTpl');
|
|
2634
|
-
taskCellTpl = viewChild.required('taskCellTpl');
|
|
2635
|
-
startDateCellTpl = viewChild.required('startDateCellTpl');
|
|
2636
|
-
finishDateCellTpl = viewChild.required('finishDateCellTpl');
|
|
2637
|
-
actualStartDateCellTpl = viewChild.required('actualStartDateCellTpl');
|
|
2638
|
-
actualFinishDateCellTpl = viewChild.required('actualFinishDateCellTpl');
|
|
2639
|
-
assignedToCellTpl = viewChild.required('assignedToCellTpl');
|
|
2640
|
-
progressCellTpl = viewChild.required('progressCellTpl');
|
|
2641
2679
|
context = input(null, ...(ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []));
|
|
2642
2680
|
maxRows = input(400, ...(ngDevMode ? [{ debugName: "maxRows" }] : /* istanbul ignore next */ []));
|
|
2643
2681
|
selectedFile = signal(null, ...(ngDevMode ? [{ debugName: "selectedFile" }] : /* istanbul ignore next */ []));
|
|
@@ -2645,6 +2683,7 @@ class TaskScheduleImportDialog {
|
|
|
2645
2683
|
loadingApply = signal(false, ...(ngDevMode ? [{ debugName: "loadingApply" }] : /* istanbul ignore next */ []));
|
|
2646
2684
|
importResult = signal(null, ...(ngDevMode ? [{ debugName: "importResult" }] : /* istanbul ignore next */ []));
|
|
2647
2685
|
selectedTaskKeys = signal(new Set(), ...(ngDevMode ? [{ debugName: "selectedTaskKeys" }] : /* istanbul ignore next */ []));
|
|
2686
|
+
treeSelection = signal([], ...(ngDevMode ? [{ debugName: "treeSelection" }] : /* istanbul ignore next */ []));
|
|
2648
2687
|
errorMessage = signal(null, ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
2649
2688
|
activeLang = toSignal(this.transloco.langChanges$, {
|
|
2650
2689
|
initialValue: this.transloco.getActiveLang(),
|
|
@@ -2747,62 +2786,58 @@ class TaskScheduleImportDialog {
|
|
|
2747
2786
|
!this.loadingApply() &&
|
|
2748
2787
|
!this.loadingImport(), ...(ngDevMode ? [{ debugName: "canApply" }] : /* istanbul ignore next */ []));
|
|
2749
2788
|
previewPageSize = computed(() => Math.min(Math.max(this.previewRows().length, 1), 50), ...(ngDevMode ? [{ debugName: "previewPageSize" }] : /* istanbul ignore next */ []));
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
key
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
}
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
label: this.labels().progress,
|
|
2796
|
-
type: 'custom',
|
|
2797
|
-
customCellTpl: this.progressCellTpl(),
|
|
2798
|
-
},
|
|
2799
|
-
], ...(ngDevMode ? [{ debugName: "previewColumns" }] : /* istanbul ignore next */ []));
|
|
2789
|
+
previewTreeNodes = computed(() => {
|
|
2790
|
+
const maxRows = Math.max(1, this.maxRows());
|
|
2791
|
+
let remaining = maxRows;
|
|
2792
|
+
const mapNode = (task, depth, path) => {
|
|
2793
|
+
if (remaining <= 0) {
|
|
2794
|
+
return null;
|
|
2795
|
+
}
|
|
2796
|
+
remaining -= 1;
|
|
2797
|
+
const key = this.resolveTaskKey(task, path);
|
|
2798
|
+
const children = [];
|
|
2799
|
+
const childTasks = this.resolveChildTasks(task);
|
|
2800
|
+
for (let index = 0; index < childTasks.length; index += 1) {
|
|
2801
|
+
const child = mapNode(childTasks[index], depth + 1, `${path}.${index}`);
|
|
2802
|
+
if (child) {
|
|
2803
|
+
children.push(child);
|
|
2804
|
+
}
|
|
2805
|
+
if (remaining <= 0) {
|
|
2806
|
+
break;
|
|
2807
|
+
}
|
|
2808
|
+
}
|
|
2809
|
+
return {
|
|
2810
|
+
key,
|
|
2811
|
+
label: this.toTreeNodeLabel(task),
|
|
2812
|
+
icon: this.resolveTreeNodeIcon(task),
|
|
2813
|
+
expanded: depth < 2,
|
|
2814
|
+
data: {
|
|
2815
|
+
rowKey: key,
|
|
2816
|
+
task,
|
|
2817
|
+
},
|
|
2818
|
+
children,
|
|
2819
|
+
};
|
|
2820
|
+
};
|
|
2821
|
+
const nodes = [];
|
|
2822
|
+
const tasks = this.importResult()?.tasks ?? [];
|
|
2823
|
+
for (let index = 0; index < tasks.length; index += 1) {
|
|
2824
|
+
const node = mapNode(tasks[index], 0, `root.${index}`);
|
|
2825
|
+
if (node) {
|
|
2826
|
+
nodes.push(node);
|
|
2827
|
+
}
|
|
2828
|
+
if (remaining <= 0) {
|
|
2829
|
+
break;
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
return nodes;
|
|
2833
|
+
}, ...(ngDevMode ? [{ debugName: "previewTreeNodes" }] : /* istanbul ignore next */ []));
|
|
2800
2834
|
onFileChanged(event) {
|
|
2801
2835
|
const input = event.target;
|
|
2802
2836
|
const file = input?.files?.item(0) ?? null;
|
|
2803
2837
|
this.selectedFile.set(file);
|
|
2804
2838
|
this.importResult.set(null);
|
|
2805
2839
|
this.selectedTaskKeys.set(new Set());
|
|
2840
|
+
this.treeSelection.set([]);
|
|
2806
2841
|
this.errorMessage.set(null);
|
|
2807
2842
|
}
|
|
2808
2843
|
importFile() {
|
|
@@ -2834,6 +2869,10 @@ class TaskScheduleImportDialog {
|
|
|
2834
2869
|
.pipe(finalize(() => this.loadingImport.set(false)))
|
|
2835
2870
|
.subscribe({
|
|
2836
2871
|
next: (result) => {
|
|
2872
|
+
if (result.applied) {
|
|
2873
|
+
this.ref.close(true);
|
|
2874
|
+
return;
|
|
2875
|
+
}
|
|
2837
2876
|
this.importResult.set(result);
|
|
2838
2877
|
this.selectAllRows(true);
|
|
2839
2878
|
},
|
|
@@ -2854,12 +2893,33 @@ class TaskScheduleImportDialog {
|
|
|
2854
2893
|
}
|
|
2855
2894
|
selectAllRows(checked) {
|
|
2856
2895
|
const next = new Set();
|
|
2896
|
+
const nextSelection = [];
|
|
2857
2897
|
if (checked) {
|
|
2858
|
-
this.
|
|
2859
|
-
|
|
2898
|
+
this.collectTreeNodes(this.previewTreeNodes()).forEach((node) => {
|
|
2899
|
+
if (node.key) {
|
|
2900
|
+
next.add(node.key);
|
|
2901
|
+
nextSelection.push(node);
|
|
2902
|
+
}
|
|
2860
2903
|
});
|
|
2861
2904
|
}
|
|
2862
2905
|
this.selectedTaskKeys.set(next);
|
|
2906
|
+
this.treeSelection.set(nextSelection);
|
|
2907
|
+
}
|
|
2908
|
+
onTreeSelectionChange(selection) {
|
|
2909
|
+
const nodes = Array.isArray(selection)
|
|
2910
|
+
? selection
|
|
2911
|
+
: selection
|
|
2912
|
+
? [selection]
|
|
2913
|
+
: [];
|
|
2914
|
+
const next = new Set();
|
|
2915
|
+
nodes.forEach((node) => {
|
|
2916
|
+
const rowKey = this.readRowKeyFromTreeNode(node);
|
|
2917
|
+
if (rowKey) {
|
|
2918
|
+
next.add(rowKey);
|
|
2919
|
+
}
|
|
2920
|
+
});
|
|
2921
|
+
this.treeSelection.set(nodes);
|
|
2922
|
+
this.selectedTaskKeys.set(next);
|
|
2863
2923
|
}
|
|
2864
2924
|
applyImport(overrideCurrent) {
|
|
2865
2925
|
if (this.loadingImport() || this.loadingApply()) {
|
|
@@ -3106,6 +3166,44 @@ class TaskScheduleImportDialog {
|
|
|
3106
3166
|
const base = task.guid ?? task.id ?? path;
|
|
3107
3167
|
return `${String(base)}::${path}`;
|
|
3108
3168
|
}
|
|
3169
|
+
collectTreeNodes(nodes) {
|
|
3170
|
+
const output = [];
|
|
3171
|
+
const walk = (items) => {
|
|
3172
|
+
items.forEach((node) => {
|
|
3173
|
+
output.push(node);
|
|
3174
|
+
if (node.children?.length) {
|
|
3175
|
+
walk(node.children);
|
|
3176
|
+
}
|
|
3177
|
+
});
|
|
3178
|
+
};
|
|
3179
|
+
walk(nodes);
|
|
3180
|
+
return output;
|
|
3181
|
+
}
|
|
3182
|
+
readRowKeyFromTreeNode(node) {
|
|
3183
|
+
const data = node.data;
|
|
3184
|
+
return typeof data?.rowKey === 'string' && data.rowKey.trim()
|
|
3185
|
+
? data.rowKey
|
|
3186
|
+
: null;
|
|
3187
|
+
}
|
|
3188
|
+
toTreeNodeLabel(task) {
|
|
3189
|
+
const title = String(task.title ?? task.name ?? '').trim();
|
|
3190
|
+
const type = String(task.type ?? task.typeLabel ?? task.typeLable ?? '').trim() ||
|
|
3191
|
+
(task.isMilestone ? 'Milestone' : task['isSummary'] ? 'Summary' : 'Task');
|
|
3192
|
+
return `${title || type}`;
|
|
3193
|
+
}
|
|
3194
|
+
resolveTreeNodeIcon(task) {
|
|
3195
|
+
if (task.isMilestone) {
|
|
3196
|
+
return 'map.flag-02';
|
|
3197
|
+
}
|
|
3198
|
+
if (task['isSummary'] || this.resolveChildTasks(task).length) {
|
|
3199
|
+
return 'files.folder-01';
|
|
3200
|
+
}
|
|
3201
|
+
return 'custom.task';
|
|
3202
|
+
}
|
|
3203
|
+
formatPreviewDate(value) {
|
|
3204
|
+
const normalized = this.toApiDate(value);
|
|
3205
|
+
return normalized ?? '';
|
|
3206
|
+
}
|
|
3109
3207
|
resolveAssignedTo(task) {
|
|
3110
3208
|
const assignedTo = task.assignedTo;
|
|
3111
3209
|
if ((typeof assignedTo === 'string' || typeof assignedTo === 'number') &&
|
|
@@ -3250,24 +3348,20 @@ class TaskScheduleImportDialog {
|
|
|
3250
3348
|
this.errorMessage.set(message);
|
|
3251
3349
|
}
|
|
3252
3350
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleImportDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3253
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleImportDialog, isStandalone: true, selector: "mt-task-schedule-import-dialog", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "selectionCellTpl", first: true, predicate: ["selectionCellTpl"], descendants: true, isSignal: true }, { propertyName: "taskCellTpl", first: true, predicate: ["taskCellTpl"], descendants: true, isSignal: true }, { propertyName: "startDateCellTpl", first: true, predicate: ["startDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "finishDateCellTpl", first: true, predicate: ["finishDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "actualStartDateCellTpl", first: true, predicate: ["actualStartDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "actualFinishDateCellTpl", first: true, predicate: ["actualFinishDateCellTpl"], descendants: true, isSignal: true }, { propertyName: "assignedToCellTpl", first: true, predicate: ["assignedToCellTpl"], descendants: true, isSignal: true }, { propertyName: "progressCellTpl", first: true, predicate: ["progressCellTpl"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n [class]=\"modal.contentClass\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\n>\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\n <input\n #fileInput\n class=\"hidden\"\n type=\"file\"\n accept=\".mpp,.xer\"\n (change)=\"onFileChanged($event)\"\n />\n\n <mt-text-field\n [ngModel]=\"selectedFile()?.name ?? ''\"\n [readonly]=\"true\"\n [placeholder]=\"labels().selectFile\"\n />\n\n <mt-button\n [label]=\"labels().selectFile\"\n severity=\"secondary\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"fileInput.click()\"\n />\n\n <mt-button\n [label]=\"labels().startImport\"\n [disabled]=\"!canImport()\"\n [loading]=\"loadingImport()\"\n (onClick)=\"importFile()\"\n />\n </div>\n </div>\n\n @if (errorMessage()) {\n <div\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\n >\n {{ errorMessage() }}\n </div>\n }\n\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\n @if (importResult()) {\n @if (!previewRows().length) {\n <div\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\n >\n {{ labels().noTasks }}\n </div>\n } @else {\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\n <div\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\n >\n <div class=\"flex items-center gap-3\">\n <mt-checkbox-field\n [ngModel]=\"allSelected()\"\n (ngModelChange)=\"selectAllRows(!!$event)\"\n />\n <span class=\"text-sm text-surface-600\">\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\n </span>\n </div>\n\n @if (isTruncated()) {\n <p class=\"text-xs text-surface-500\">\n {{ labels().rowsLimited }}\n </p>\n }\n </div>\n\n <div class=\"px-2 py-2\">\n @defer (on idle) {\n <mt-table\n [data]=\"previewRows()\"\n [columns]=\"previewColumns()\"\n dataKey=\"key\"\n storageKey=\"task-schedule-import-preview-table\"\n size=\"small\"\n [stripedRows]=\"true\"\n [showGridlines]=\"true\"\n [pageSize]=\"previewPageSize()\"\n />\n } @placeholder {\n <div class=\"space-y-2 p-2\">\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button\n [label]=\"labels().cancel\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"close()\"\n />\n\n <mt-button\n [label]=\"labels().replace\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(true)\"\n />\n\n <mt-button\n [label]=\"labels().append\"\n severity=\"secondary\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(false)\"\n />\n</div>\n\n<ng-template #selectionCellTpl let-row>\n <div class=\"flex items-center justify-center\">\n <mt-checkbox-field\n [ngModel]=\"selectedTaskKeys().has(row.key)\"\n (ngModelChange)=\"toggleRowSelection(row.key, !!$event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #taskCellTpl let-row>\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\n <mt-text-field\n [ngModel]=\"row.task.title || row.task.name || ''\"\n (ngModelChange)=\"onTaskTitleChanged(row.key, $event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #startDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.startDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'startDate', $event)\"\n />\n</ng-template>\n\n<ng-template #finishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.finishDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'finishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualStartDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualStartDate || row.task.actualStart)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualStartDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualFinishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualFinishDate || row.task.actualFinish)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualFinishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #assignedToCellTpl let-row>\n <div class=\"min-w-0\">\n @if (resourceOptions().length) {\n <div class=\"space-y-2\">\n <mt-select-field\n [ngModel]=\"resolveAssignedValue(row.task)\"\n [options]=\"resourceOptions()\"\n optionLabel=\"label\"\n optionValue=\"id\"\n [showClear]=\"true\"\n [hasPlaceholderPrefix]=\"false\"\n [placeholder]=\"labels().assignedTo\"\n (ngModelChange)=\"onTaskAssignedToChanged(row.key, $event)\"\n />\n @if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n }\n </div>\n } @else if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n } @else {\n <span class=\"text-slate-400\">-</span>\n }\n </div>\n</ng-template>\n\n<ng-template #progressCellTpl let-row>\n <div class=\"space-y-2\">\n <mt-number-field\n [ngModel]=\"normalizeProgress(row.task.progress)\"\n [min]=\"0\"\n [max]=\"100\"\n [useGrouping]=\"false\"\n [maxFractionDigits]=\"0\"\n (ngModelChange)=\"onTaskProgressChanged(row.key, $event)\"\n />\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\n </div>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: DateField, selector: "mt-date-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "showIcon", "showClear", "showTime", "pInputs", "required"] }, { kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "component", type: NumberField, selector: "mt-number-field", inputs: ["field", "hint", "label", "placeholder", "class", "readonly", "pInputs", "format", "useGrouping", "maxFractionDigits", "min", "max", "required"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "ngmodule", type: TranslocoModule }], deferBlockDependencies: [() => [import('@masterteam/components/table').then(m => m.Table)]] });
|
|
3351
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleImportDialog, isStandalone: true, selector: "mt-task-schedule-import-dialog", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\r\n [class]=\"modal.contentClass\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\r\n>\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\r\n <input\r\n #fileInput\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n\r\n <mt-text-field\r\n [ngModel]=\"selectedFile()?.name ?? ''\"\r\n [readonly]=\"true\"\r\n [placeholder]=\"labels().selectFile\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().selectFile\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n [disabled]=\"loadingImport() || loadingApply()\"\r\n (onClick)=\"fileInput.click()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().startImport\"\r\n [disabled]=\"!canImport()\"\r\n [loading]=\"loadingImport()\"\r\n (onClick)=\"importFile()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (errorMessage()) {\r\n <div\r\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\r\n >\r\n {{ errorMessage() }}\r\n </div>\r\n }\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\r\n @if (importResult()) {\r\n @if (!previewRows().length) {\r\n <div\r\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\r\n >\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelected()\"\r\n (ngModelChange)=\"selectAllRows(!!$event)\"\r\n />\r\n <span class=\"text-sm text-surface-600\">\r\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\r\n </span>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-surface-500\">\r\n {{ labels().rowsLimited }}\r\n </p>\r\n }\r\n </div>\r\n\r\n <div class=\"px-2 py-2\">\r\n <mt-tree\r\n [value]=\"previewTreeNodes()\"\r\n [selection]=\"treeSelection()\"\r\n selectionMode=\"checkbox\"\r\n [propagateSelectionUp]=\"false\"\r\n [propagateSelectionDown]=\"false\"\r\n [filter]=\"true\"\r\n scrollHeight=\"28rem\"\r\n styleClass=\"task-schedule-import-tree\"\r\n (selectionChange)=\"onTreeSelectionChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n variant=\"outlined\"\r\n [disabled]=\"loadingImport() || loadingApply()\"\r\n (onClick)=\"close()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().replace\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(true)\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().append\"\r\n severity=\"secondary\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(false)\"\r\n />\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: CheckboxField, selector: "mt-checkbox-field", inputs: ["label", "labelPosition", "placeholder", "readonly", "pInputs", "required"], outputs: ["onChange"] }, { kind: "component", type: TextField, selector: "mt-text-field", inputs: ["field", "hint", "label", "placeholder", "class", "type", "readonly", "pInputs", "required", "maxLength", "icon", "iconPosition"] }, { kind: "component", type: Tree, selector: "mt-tree", inputs: ["value", "selection", "selectionMode", "nodeIcon", "propagateSelectionUp", "propagateSelectionDown", "checkAllChildren", "loading", "emptyMessage", "checkAllLabel", "filterPlaceholder", "dataKey", "filter", "filterMode", "virtualScroll", "virtualScrollItemSize", "scrollHeight", "styleClass", "style", "pInputs", "nodeActions", "nodeContextmenuActions", "contextMenuSelection"], outputs: ["selectionChange", "contextMenuSelectionChange", "action"] }, { kind: "ngmodule", type: TranslocoModule }] });
|
|
3254
3352
|
}
|
|
3255
|
-
i0.ɵɵ
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
TextField,
|
|
3268
|
-
TranslocoModule,
|
|
3269
|
-
], template: "<div\n [class]=\"modal.contentClass\"\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\n>\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\n <input\n #fileInput\n class=\"hidden\"\n type=\"file\"\n accept=\".mpp,.xer\"\n (change)=\"onFileChanged($event)\"\n />\n\n <mt-text-field\n [ngModel]=\"selectedFile()?.name ?? ''\"\n [readonly]=\"true\"\n [placeholder]=\"labels().selectFile\"\n />\n\n <mt-button\n [label]=\"labels().selectFile\"\n severity=\"secondary\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"fileInput.click()\"\n />\n\n <mt-button\n [label]=\"labels().startImport\"\n [disabled]=\"!canImport()\"\n [loading]=\"loadingImport()\"\n (onClick)=\"importFile()\"\n />\n </div>\n </div>\n\n @if (errorMessage()) {\n <div\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\n >\n {{ errorMessage() }}\n </div>\n }\n\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\n @if (importResult()) {\n @if (!previewRows().length) {\n <div\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\n >\n {{ labels().noTasks }}\n </div>\n } @else {\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\n <div\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\n >\n <div class=\"flex items-center gap-3\">\n <mt-checkbox-field\n [ngModel]=\"allSelected()\"\n (ngModelChange)=\"selectAllRows(!!$event)\"\n />\n <span class=\"text-sm text-surface-600\">\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\n </span>\n </div>\n\n @if (isTruncated()) {\n <p class=\"text-xs text-surface-500\">\n {{ labels().rowsLimited }}\n </p>\n }\n </div>\n\n <div class=\"px-2 py-2\">\n @defer (on idle) {\n <mt-table\n [data]=\"previewRows()\"\n [columns]=\"previewColumns()\"\n dataKey=\"key\"\n storageKey=\"task-schedule-import-preview-table\"\n size=\"small\"\n [stripedRows]=\"true\"\n [showGridlines]=\"true\"\n [pageSize]=\"previewPageSize()\"\n />\n } @placeholder {\n <div class=\"space-y-2 p-2\">\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n <div class=\"h-9 rounded bg-surface-100\"></div>\n </div>\n }\n </div>\n </div>\n }\n }\n </div>\n</div>\n\n<div [class]=\"modal.footerClass\">\n <mt-button\n [label]=\"labels().cancel\"\n variant=\"outlined\"\n [disabled]=\"loadingImport() || loadingApply()\"\n (onClick)=\"close()\"\n />\n\n <mt-button\n [label]=\"labels().replace\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(true)\"\n />\n\n <mt-button\n [label]=\"labels().append\"\n severity=\"secondary\"\n [disabled]=\"!canApply()\"\n [loading]=\"loadingApply()\"\n (onClick)=\"applyImport(false)\"\n />\n</div>\n\n<ng-template #selectionCellTpl let-row>\n <div class=\"flex items-center justify-center\">\n <mt-checkbox-field\n [ngModel]=\"selectedTaskKeys().has(row.key)\"\n (ngModelChange)=\"toggleRowSelection(row.key, !!$event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #taskCellTpl let-row>\n <div class=\"min-w-0\" [style.paddingInlineStart.px]=\"row.depth * 18\">\n <mt-text-field\n [ngModel]=\"row.task.title || row.task.name || ''\"\n (ngModelChange)=\"onTaskTitleChanged(row.key, $event)\"\n />\n </div>\n</ng-template>\n\n<ng-template #startDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.startDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'startDate', $event)\"\n />\n</ng-template>\n\n<ng-template #finishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"toDateFieldValue(row.task.finishDate)\"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'finishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualStartDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualStartDate || row.task.actualStart)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualStartDate', $event)\"\n />\n</ng-template>\n\n<ng-template #actualFinishDateCellTpl let-row>\n <mt-date-field\n [ngModel]=\"\n toDateFieldValue(row.task.actualFinishDate || row.task.actualFinish)\n \"\n [showClear]=\"true\"\n (ngModelChange)=\"onTaskDateChanged(row.key, 'actualFinishDate', $event)\"\n />\n</ng-template>\n\n<ng-template #assignedToCellTpl let-row>\n <div class=\"min-w-0\">\n @if (resourceOptions().length) {\n <div class=\"space-y-2\">\n <mt-select-field\n [ngModel]=\"resolveAssignedValue(row.task)\"\n [options]=\"resourceOptions()\"\n optionLabel=\"label\"\n optionValue=\"id\"\n [showClear]=\"true\"\n [hasPlaceholderPrefix]=\"false\"\n [placeholder]=\"labels().assignedTo\"\n (ngModelChange)=\"onTaskAssignedToChanged(row.key, $event)\"\n />\n @if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n }\n </div>\n } @else if (row.task.assignedTo) {\n <mt-entity-preview [data]=\"toAssignedEntity(row.task)\" />\n } @else {\n <span class=\"text-slate-400\">-</span>\n }\n </div>\n</ng-template>\n\n<ng-template #progressCellTpl let-row>\n <div class=\"space-y-2\">\n <mt-number-field\n [ngModel]=\"normalizeProgress(row.task.progress)\"\n [min]=\"0\"\n [max]=\"100\"\n [useGrouping]=\"false\"\n [maxFractionDigits]=\"0\"\n (ngModelChange)=\"onTaskProgressChanged(row.key, $event)\"\n />\n <mt-entity-preview [data]=\"toProgressEntity(row.task)\" />\n </div>\n</ng-template>\n" }]
|
|
3270
|
-
}], ctorParameters: null, propDecorators: { selectionCellTpl: [{ type: i0.ViewChild, args: ['selectionCellTpl', { isSignal: true }] }], taskCellTpl: [{ type: i0.ViewChild, args: ['taskCellTpl', { isSignal: true }] }], startDateCellTpl: [{ type: i0.ViewChild, args: ['startDateCellTpl', { isSignal: true }] }], finishDateCellTpl: [{ type: i0.ViewChild, args: ['finishDateCellTpl', { isSignal: true }] }], actualStartDateCellTpl: [{ type: i0.ViewChild, args: ['actualStartDateCellTpl', { isSignal: true }] }], actualFinishDateCellTpl: [{ type: i0.ViewChild, args: ['actualFinishDateCellTpl', { isSignal: true }] }], assignedToCellTpl: [{ type: i0.ViewChild, args: ['assignedToCellTpl', { isSignal: true }] }], progressCellTpl: [{ type: i0.ViewChild, args: ['progressCellTpl', { isSignal: true }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }] } }) });
|
|
3353
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleImportDialog, decorators: [{
|
|
3354
|
+
type: Component,
|
|
3355
|
+
args: [{ selector: 'mt-task-schedule-import-dialog', standalone: true, imports: [
|
|
3356
|
+
CommonModule,
|
|
3357
|
+
FormsModule,
|
|
3358
|
+
Button,
|
|
3359
|
+
CheckboxField,
|
|
3360
|
+
TextField,
|
|
3361
|
+
Tree,
|
|
3362
|
+
TranslocoModule,
|
|
3363
|
+
], template: "<div\r\n [class]=\"modal.contentClass\"\r\n [attr.dir]=\"isRtl() ? 'rtl' : 'ltr'\"\r\n class=\"flex h-full min-h-0 flex-col gap-4 !overflow-y-hidden p-5\"\r\n>\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-50 p-4\">\r\n <div class=\"grid gap-3 lg:grid-cols-[minmax(0,1fr)_auto_auto] lg:items-end\">\r\n <input\r\n #fileInput\r\n class=\"hidden\"\r\n type=\"file\"\r\n accept=\".mpp,.xer\"\r\n (change)=\"onFileChanged($event)\"\r\n />\r\n\r\n <mt-text-field\r\n [ngModel]=\"selectedFile()?.name ?? ''\"\r\n [readonly]=\"true\"\r\n [placeholder]=\"labels().selectFile\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().selectFile\"\r\n severity=\"secondary\"\r\n variant=\"outlined\"\r\n [disabled]=\"loadingImport() || loadingApply()\"\r\n (onClick)=\"fileInput.click()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().startImport\"\r\n [disabled]=\"!canImport()\"\r\n [loading]=\"loadingImport()\"\r\n (onClick)=\"importFile()\"\r\n />\r\n </div>\r\n </div>\r\n\r\n @if (errorMessage()) {\r\n <div\r\n class=\"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700\"\r\n >\r\n {{ errorMessage() }}\r\n </div>\r\n }\r\n\r\n <div class=\"min-h-0 flex-1 overflow-y-auto\">\r\n @if (importResult()) {\r\n @if (!previewRows().length) {\r\n <div\r\n class=\"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800\"\r\n >\r\n {{ labels().noTasks }}\r\n </div>\r\n } @else {\r\n <div class=\"rounded-lg border border-surface-200 bg-surface-0\">\r\n <div\r\n class=\"flex flex-wrap items-center justify-between gap-3 border-b border-surface-200 bg-surface-50 px-4 py-3\"\r\n >\r\n <div class=\"flex items-center gap-3\">\r\n <mt-checkbox-field\r\n [ngModel]=\"allSelected()\"\r\n (ngModelChange)=\"selectAllRows(!!$event)\"\r\n />\r\n <span class=\"text-sm text-surface-600\">\r\n {{ selectedTaskKeys().size }} / {{ previewRows().length }}\r\n </span>\r\n </div>\r\n\r\n @if (isTruncated()) {\r\n <p class=\"text-xs text-surface-500\">\r\n {{ labels().rowsLimited }}\r\n </p>\r\n }\r\n </div>\r\n\r\n <div class=\"px-2 py-2\">\r\n <mt-tree\r\n [value]=\"previewTreeNodes()\"\r\n [selection]=\"treeSelection()\"\r\n selectionMode=\"checkbox\"\r\n [propagateSelectionUp]=\"false\"\r\n [propagateSelectionDown]=\"false\"\r\n [filter]=\"true\"\r\n scrollHeight=\"28rem\"\r\n styleClass=\"task-schedule-import-tree\"\r\n (selectionChange)=\"onTreeSelectionChange($event)\"\r\n />\r\n </div>\r\n </div>\r\n }\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <mt-button\r\n [label]=\"labels().cancel\"\r\n variant=\"outlined\"\r\n [disabled]=\"loadingImport() || loadingApply()\"\r\n (onClick)=\"close()\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().replace\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(true)\"\r\n />\r\n\r\n <mt-button\r\n [label]=\"labels().append\"\r\n severity=\"secondary\"\r\n [disabled]=\"!canApply()\"\r\n [loading]=\"loadingApply()\"\r\n (onClick)=\"applyImport(false)\"\r\n />\r\n</div>\r\n" }]
|
|
3364
|
+
}], propDecorators: { context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }] } });
|
|
3271
3365
|
|
|
3272
3366
|
class TaskScheduleQueueService {
|
|
3273
3367
|
basicOrderColumns = new Map();
|