@masterteam/task-schedule 0.0.24 → 0.0.26

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.
@@ -2669,15 +2669,18 @@ class TaskScheduleDialog {
2669
2669
  ...(request.fields ?? []),
2670
2670
  {
2671
2671
  // Parent reference is the anchor row's schedule guid / externalId,
2672
- // not its numeric database id.
2673
- propertyKey: 'externalParentId',
2672
+ // not its numeric database id. Send it under the canonical `parentId`
2673
+ // key (the same key the drag-drop reparent and bulk-update paths use)
2674
+ // so the new task is actually nested as a subtask; `externalParentId`
2675
+ // is only a legacy alias and isn't reliably honored on create.
2676
+ propertyKey: 'parentId',
2674
2677
  value: this.parentGuid(),
2675
2678
  },
2676
2679
  ],
2677
2680
  };
2678
2681
  }
2679
2682
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
2680
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleDialog, isStandalone: true, selector: "mt-task-schedule-dialog", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, task: { classPropertyName: "task", publicName: "task", isSignal: true, isRequired: false, transformFunction: null }, typeOptions: { classPropertyName: "typeOptions", publicName: "typeOptions", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, parentGuid: { classPropertyName: "parentGuid", publicName: "parentGuid", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "clientForm", first: true, predicate: ClientForm, descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"'p-4 overflow-y-auto ' + (modal.contentClass || '')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [options]=\"typeSelectOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [label]=\"'task-schedule.dialog.type' | transloco\"\r\n [placeholder]=\"'task-schedule.dialog.typePlaceholder' | transloco\"\r\n [ngModel]=\"selectedType() ?? undefined\"\r\n (onChange)=\"onTypeChange($event)\"\r\n />\r\n\r\n @if (selectedType()) {\r\n <mt-client-form\r\n #clientForm\r\n [moduleKey]=\"'ModuleData'\"\r\n [moduleId]=\"selectedModuleId() ?? undefined\"\r\n [operationKey]=\"mode() === 'edit' ? 'Update' : 'Create'\"\r\n [formMode]=\"mode()\"\r\n [levelId]=\"context()?.levelId ?? undefined\"\r\n [levelDataId]=\"context()?.levelDataId ?? undefined\"\r\n [moduleDataId]=\"selectedModuleDataId() ?? undefined\"\r\n [lang]=\"langCode()\"\r\n [autoLoad]=\"true\"\r\n [ignoredFieldKeys]=\"ignoredFieldKeys()\"\r\n [submitRequestMapper]=\"submitRequestMapper\"\r\n (submitted)=\"onClientFormSubmitted($event)\"\r\n />\r\n } @else {\r\n <div\r\n class=\"rounded-xl border border-surface bg-content px-4 py-4 text-sm text-muted-color\"\r\n >\r\n {{ \"task-schedule.dialog.typeFirst\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <div class=\"flex items-center justify-end gap-3\">\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.cancel' | transloco\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.save' | transloco\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ClientForm, selector: "mt-client-form", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "returnUrl", "defaultValues", "submitRequestMapper", "readonly", "autoLoad", "formMode", "renderMode", "showInternalStepActions", "confirmWarningsOnSubmit", "confirmWarningsOnStepChange", "readonlyFieldDisplayMode", "lookups", "statuses", "ignoredFieldKeys", "allowedFieldKeys"], outputs: ["loaded", "submitted", "errored", "modeDetected", "formSourceDetected", "footerStateChanged"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
2683
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.8", type: TaskScheduleDialog, isStandalone: true, selector: "mt-task-schedule-dialog", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null }, task: { classPropertyName: "task", publicName: "task", isSignal: true, isRequired: false, transformFunction: null }, typeOptions: { classPropertyName: "typeOptions", publicName: "typeOptions", isSignal: true, isRequired: false, transformFunction: null }, langCode: { classPropertyName: "langCode", publicName: "langCode", isSignal: true, isRequired: false, transformFunction: null }, parentGuid: { classPropertyName: "parentGuid", publicName: "parentGuid", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "clientForm", first: true, predicate: ClientForm, descendants: true, isSignal: true }], ngImport: i0, template: "<div [class]=\"'p-4 overflow-y-auto ' + (modal.contentClass || '')\">\r\n <div class=\"flex flex-col gap-4\">\r\n <mt-select-field\r\n [options]=\"typeSelectOptions()\"\r\n optionLabel=\"label\"\r\n optionValue=\"value\"\r\n [label]=\"'task-schedule.dialog.type' | transloco\"\r\n [placeholder]=\"'task-schedule.dialog.typePlaceholder' | transloco\"\r\n [ngModel]=\"selectedType() ?? undefined\"\r\n (onChange)=\"onTypeChange($event)\"\r\n />\r\n\r\n @if (selectedType()) {\r\n <mt-client-form\r\n #clientForm\r\n [moduleKey]=\"'ModuleData'\"\r\n [moduleId]=\"selectedModuleId() ?? undefined\"\r\n [operationKey]=\"mode() === 'edit' ? 'Update' : 'Create'\"\r\n [formMode]=\"mode()\"\r\n [levelId]=\"context()?.levelId ?? undefined\"\r\n [levelDataId]=\"context()?.levelDataId ?? undefined\"\r\n [moduleDataId]=\"selectedModuleDataId() ?? undefined\"\r\n [lang]=\"langCode()\"\r\n [autoLoad]=\"true\"\r\n [ignoredFieldKeys]=\"ignoredFieldKeys()\"\r\n [submitRequestMapper]=\"submitRequestMapper\"\r\n (submitted)=\"onClientFormSubmitted($event)\"\r\n />\r\n } @else {\r\n <div\r\n class=\"rounded-xl border border-surface bg-content px-4 py-4 text-sm text-muted-color\"\r\n >\r\n {{ \"task-schedule.dialog.typeFirst\" | transloco }}\r\n </div>\r\n }\r\n </div>\r\n</div>\r\n\r\n<div [class]=\"modal.footerClass\">\r\n <div class=\"flex items-center justify-end gap-3\">\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.cancel' | transloco\"\r\n variant=\"outlined\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"cancel()\"\r\n />\r\n <mt-button\r\n [label]=\"'task-schedule.dialog.save' | transloco\"\r\n severity=\"primary\"\r\n [loading]=\"submitting()\"\r\n [disabled]=\"submitting()\"\r\n (onClick)=\"save()\"\r\n />\r\n </div>\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: SelectField, selector: "mt-select-field", inputs: ["field", "hint", "label", "placeholder", "hasPlaceholderPrefix", "class", "readonly", "pInputs", "options", "optionValue", "optionLabel", "filter", "filterBy", "dataKey", "showClear", "clearAfterSelect", "required", "group", "size", "optionGroupLabel", "optionGroupChildren", "loading", "optionIcon", "optionIconColor", "optionIconShape", "optionAvatarShape", "optionGroupIcon", "optionGroupIconColor", "optionGroupIconShape", "optionGroupAvatarShape", "markCurrentUser"], outputs: ["onChange"] }, { kind: "component", type: ClientForm, selector: "mt-client-form", inputs: ["moduleKey", "operationKey", "moduleId", "levelId", "levelDataId", "moduleDataId", "requestSchemaId", "draftProcessId", "preview", "forceOriginalForm", "returnUrl", "defaultValues", "submitRequestMapper", "readonly", "autoLoad", "formMode", "renderMode", "showInternalStepActions", "confirmWarningsOnSubmit", "confirmWarningsOnStepChange", "readonlyFieldDisplayMode", "lookups", "statuses", "ignoredFieldKeys", "allowedFieldKeys"], outputs: ["loaded", "submitted", "errored", "modeDetected", "formSourceDetected", "footerStateChanged"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "pipe", type: i2.TranslocoPipe, name: "transloco" }] });
2681
2684
  }
2682
2685
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: TaskScheduleDialog, decorators: [{
2683
2686
  type: Component,
@@ -3135,16 +3138,23 @@ class TaskScheduleImportDialog {
3135
3138
  }
3136
3139
  buildApplyPayloadTask(row) {
3137
3140
  const task = row.task;
3141
+ // The MPP parse leaves externalId as "None" for tasks without one; the
3142
+ // import DTO rejects "None" and requires unique externalIds, expressing
3143
+ // hierarchy via externalParentId (parentGuid is ignored). Send the task's
3144
+ // stable unique id as externalId and link children to the parent's id.
3145
+ const externalParentId = this.resolveParentExternalIdForPreviewRow(row.key);
3138
3146
  const payloadTask = {
3139
3147
  ...task,
3140
3148
  name: String(task.title ?? task.name ?? ''),
3141
3149
  predecessors: task.predecessor ?? task.predecessors ?? '',
3142
- parentGuid: task.parentGuid ?? this.resolveParentGuidForPreviewRow(row.key),
3150
+ parentGuid: externalParentId,
3143
3151
  assignedTo: this.resolveAssignedTo(task),
3144
3152
  isSelected: true,
3145
3153
  subtasks: [],
3146
3154
  children: [],
3147
3155
  };
3156
+ payloadTask['externalId'] = this.toStableExternalId(task);
3157
+ payloadTask['externalParentId'] = externalParentId;
3148
3158
  payloadTask['startDate'] = this.toApiDateTime(task.startDate);
3149
3159
  payloadTask['finishDate'] = this.toApiDateTime(task.finishDate);
3150
3160
  payloadTask['baselineStart'] = this.toApiDateTime(task.baselineStartDate ?? task.baselineStart);
@@ -3157,7 +3167,7 @@ class TaskScheduleImportDialog {
3157
3167
  String(task.type ?? task.typeLabel ?? task.typeLable ?? '').toLowerCase() === 'milestone';
3158
3168
  return payloadTask;
3159
3169
  }
3160
- resolveParentGuidForPreviewRow(rowKey) {
3170
+ resolveParentExternalIdForPreviewRow(rowKey) {
3161
3171
  const path = this.readPathFromRowKey(rowKey);
3162
3172
  if (!path) {
3163
3173
  return null;
@@ -3167,13 +3177,29 @@ class TaskScheduleImportDialog {
3167
3177
  return null;
3168
3178
  }
3169
3179
  const parent = this.findTaskByPath(steps.slice(0, -1).join('.'));
3170
- if (!parent) {
3171
- return null;
3180
+ return parent ? this.toStableExternalId(parent) : null;
3181
+ }
3182
+ /**
3183
+ * A unique, stable external id for the import DTO. The MPP parse yields
3184
+ * `guid`/`externalId` of "None" for tasks without one, which the backend
3185
+ * rejects as a duplicate/reserved value — fall back to the task's unique id.
3186
+ */
3187
+ toStableExternalId(task) {
3188
+ const candidates = [
3189
+ task.guid,
3190
+ task['externalId'],
3191
+ task.id,
3192
+ ];
3193
+ for (const candidate of candidates) {
3194
+ if (candidate === null || candidate === undefined) {
3195
+ continue;
3196
+ }
3197
+ const value = String(candidate).trim();
3198
+ if (value && value.toLowerCase() !== 'none') {
3199
+ return value;
3200
+ }
3172
3201
  }
3173
- const parentGuid = parent.guid ?? parent.id ?? null;
3174
- return parentGuid === null || parentGuid === undefined
3175
- ? null
3176
- : String(parentGuid);
3202
+ return null;
3177
3203
  }
3178
3204
  resolveChildTasks(task) {
3179
3205
  const subtasks = Array.isArray(task.subtasks) ? task.subtasks : [];