private static createTasks()

in src/gantt.ts [839:1103]


    private static createTasks(
        dataView: DataView,
        taskTypes: TaskTypes,
        host: IVisualHost,
        formatters: GanttChartFormatters,
        colors: IColorPalette,
        settings: GanttSettings,
        taskColor: string,
        localizationManager: ILocalizationManager,
        isEndDateFillled: boolean): Task[] {

        let tasks: Task[] = [],
            addedParents: string[] = [];

        const values: GanttColumns<any> = GanttColumns.getCategoricalValues(dataView);

        if (!values.Task) {
            return tasks;
        }

        const colorHelper: ColorHelper = new ColorHelper(colors, Gantt.LegendPropertyIdentifier);
        const groupValues: GanttColumns<DataViewValueColumn>[] = GanttColumns.getGroupedValueColumns(dataView);
        const sortingOptions: SortingOptions = Gantt.getSortingOptions(dataView);

        let collapsedTasks: string[] = JSON.parse(settings.collapsedTasks.list);
        let durationUnit: string = settings.general.durationUnit;
        let duration: number = settings.general.durationMin;
        let taskProgressShow: boolean = settings.taskCompletion.show;

        let endDate: Date = null;

        values.Task.forEach((categoryValue: PrimitiveValue, index: number) => {
            let color: string = taskColor || Gantt.DefaultValues.TaskColor;
            let completion: number = 0;
            let taskType: TaskTypeMetadata = null;
            let wasDowngradeDurationUnit: boolean = false;
            let tooltips: VisualTooltipDataItem[] = [];
            let stepDurationTransformation: number = 0;

            const selectionBuilder: ISelectionIdBuilder = host
                .createSelectionIdBuilder()
                .withCategory(dataView.categorical.categories[0], index);

            if (groupValues) {
                groupValues.forEach((group: GanttColumns<DataViewValueColumn>) => {
                    let maxCompletionFromTasks: number = _.max(values.Completion);
                    maxCompletionFromTasks = maxCompletionFromTasks > Gantt.ComplectionMax ? Gantt.ComplectionMaxInPercent : Gantt.ComplectionMax;

                    if (group.Duration && group.Duration.values[index] !== null) {
                        taskType = _.find(taskTypes.types,
                            (typeMeta: TaskTypeMetadata) => typeMeta.name === group.Duration.source.groupName);

                        if (taskType) {
                            selectionBuilder.withCategory(taskType.selectionColumn, 0);
                            color = colorHelper.getColorForMeasure(taskType.columnGroup.objects, taskType.name);
                        }

                        duration = group.Duration.values[index] > settings.general.durationMin ? group.Duration.values[index] as number : settings.general.durationMin;

                        if (duration && duration % 1 !== 0) {
                            durationUnit = DurationHelper.downgradeDurationUnit(durationUnit, duration);
                            stepDurationTransformation =
                                GanttDurationUnitType.indexOf(settings.general.durationUnit) - GanttDurationUnitType.indexOf(durationUnit);

                            duration = DurationHelper.transformDuration(duration, durationUnit, stepDurationTransformation);
                            wasDowngradeDurationUnit = true;
                        }

                        completion = ((group.Completion && group.Completion.values[index])
                            && taskProgressShow
                            && Gantt.convertToDecimal(group.Completion.values[index] as number, settings.taskCompletion.maxCompletion, maxCompletionFromTasks)) || null;

                        if (completion !== null) {
                            if (completion < Gantt.ComplectionMin) {
                                completion = Gantt.ComplectionMin;
                            }

                            if (completion > Gantt.ComplectionMax) {
                                completion = Gantt.ComplectionMax;
                            }
                        }

                    } else if (group.EndDate && group.EndDate.values[index] !== null) {
                        taskType = _.find(taskTypes.types,
                            (typeMeta: TaskTypeMetadata) => typeMeta.name === group.EndDate.source.groupName);

                        if (taskType) {
                            selectionBuilder.withCategory(taskType.selectionColumn, 0);
                            color = colorHelper.getColorForMeasure(taskType.columnGroup.objects, taskType.name);
                        }

                        endDate = group.EndDate.values[index] ? group.EndDate.values[index] as Date : null;
                        if (typeof (endDate) === "string" || typeof (endDate) === "number") {
                            endDate = new Date(endDate);
                        }

                        completion = ((group.Completion && group.Completion.values[index])
                            && taskProgressShow
                            && Gantt.convertToDecimal(group.Completion.values[index] as number, settings.taskCompletion.maxCompletion, maxCompletionFromTasks)) || null;

                        if (completion !== null) {
                            if (completion < Gantt.ComplectionMin) {
                                completion = Gantt.ComplectionMin;
                            }

                            if (completion > Gantt.ComplectionMax) {
                                completion = Gantt.ComplectionMax;
                            }
                        }
                    }
                });
            }

            const selectionId: powerbi.extensibility.ISelectionId = selectionBuilder.createSelectionId();
            const extraInformation: ExtraInformation[] = [];
            const resource: string = (values.Resource && values.Resource[index] as string) || "";
            const parent: string = (values.Parent && values.Parent[index] as string) || null;
            const Milestone: string = (values.Milestones && !_.isEmpty(values.Milestones[index]) && values.Milestones[index]) || null;

            const startDate: Date = (values.StartDate && values.StartDate[index]
                && isValidDate(new Date(values.StartDate[index])) && new Date(values.StartDate[index]))
                || new Date(Date.now());

            if (values.ExtraInformation) {
                const extraInformationKeys: any[] = Object.keys(values.ExtraInformation);
                for (const key of extraInformationKeys) {
                    const value: string = values.ExtraInformation[key][index];
                    if (value) {
                        extraInformation.push({
                            displayName: key,
                            value: value
                        });
                    }
                }
            }

            const task: Task = {
                color,
                completion,
                resource,
                index: null,
                name: categoryValue as string,
                start: startDate,
                end: endDate,
                parent,
                children: null,
                visibility: true,
                duration,
                taskType: taskType && taskType.name,
                description: categoryValue as string,
                tooltipInfo: tooltips,
                selected: false,
                identity: selectionId,
                extraInformation,
                daysOffList: [],
                wasDowngradeDurationUnit,
                stepDurationTransformation,
                Milestones: Milestone && startDate ? [{ type: Milestone, start: startDate, tooltipInfo: null, category: categoryValue as string }] : []
            };

            if (parent) {
                let parentTask: Task = null;
                if (addedParents.indexOf(parent) === -1) {
                    addedParents.push(parent);

                    parentTask = {
                        index: 0,
                        name: parent,
                        start: null,
                        duration: null,
                        completion: null,
                        resource: null,
                        end: null,
                        parent: null,
                        children: [task],
                        visibility: true,
                        taskType: null,
                        description: null,
                        color: null,
                        tooltipInfo: null,
                        extraInformation: _.includes(collapsedTasks, parent) ? extraInformation : null,
                        daysOffList: null,
                        wasDowngradeDurationUnit: null,
                        selected: null,
                        identity: selectionBuilder.createSelectionId(),
                        Milestones: Milestone && startDate ? [{ type: Milestone, start: startDate, tooltipInfo: null, category: categoryValue as string }] : []
                    };

                    tasks.push(parentTask);

                } else {
                    parentTask = tasks.filter(x => x.index === 0 && x.name === parent)[0];

                    parentTask.children.push(task);
                }
            }

            tasks.push(task);
        });

        Gantt.downgradeDurationUnitIfNeeded(tasks, durationUnit);

        if (values.Parent) {
            tasks = Gantt.sortTasksWithParents(tasks, sortingOptions);
        }

        tasks.forEach(task => {
            if (task.children && task.children.length) {
                return;
            }

            if (task.end && task.start && isValidDate(task.end)) {
                const durationInMilliseconds: number = task.end.getTime() - task.start.getTime(),
                    minDurationUnitInMilliseconds: number = Gantt.getMinDurationUnitInMilliseconds(durationUnit);

                task.end = durationInMilliseconds < minDurationUnitInMilliseconds ? Gantt.getEndDate(durationUnit, task.start, task.duration) : task.end;
            } else {
                task.end = isValidDate(task.end) ? task.end : Gantt.getEndDate(durationUnit, task.start, task.duration);
            }

            if (settings.daysOff.show && duration) {
                let datesDiff: number = 0;
                do {
                    task.daysOffList = Gantt.calculateDaysOff(
                        +settings.daysOff.firstDayOfWeek,
                        new Date(task.start.getTime()),
                        new Date(task.end.getTime())
                    );

                    if (task.daysOffList.length) {
                        const isDurationFilled: boolean = _.findIndex(dataView.metadata.columns, col => col.roles.hasOwnProperty(GanttRoles.Duration)) !== -1;
                        if (isDurationFilled) {
                            let extraDuration = Gantt.calculateExtraDurationDaysOff(task.daysOffList, task.start, task.end, +settings.daysOff.firstDayOfWeek, durationUnit);
                            task.end = Gantt.getEndDate(durationUnit, task.start, task.duration + extraDuration);
                        }

                        const lastDayOffListItem = task.daysOffList[task.daysOffList.length - 1];
                        const lastDayOff: Date = lastDayOffListItem[1] === 1 ? lastDayOffListItem[0]
                            : new Date(lastDayOffListItem[0].getFullYear(), lastDayOffListItem[0].getMonth(), lastDayOffListItem[0].getDate() + 1);
                        datesDiff = Math.ceil((task.end.getTime() - lastDayOff.getTime()) / MillisecondsInADay);
                    }
                } while (task.daysOffList.length && datesDiff - DaysInAWeekend > DaysInAWeek);
            }

            if (task.parent) {
                task.visibility = collapsedTasks.indexOf(task.parent) === -1;
            }
        });

        tasks.forEach((task: Task) => {
            if (!task.children || _.includes(collapsedTasks, task.name)) {
                task.tooltipInfo = Gantt.getTooltipInfo(task, formatters, durationUnit, localizationManager, isEndDateFillled);
                if (task.Milestones) {
                    task.Milestones.forEach((milestone) => {
                        const dateFormatted = formatters.startDateFormatter.format(task.start);
                        const dateTypesSettings = settings.dateType;
                        milestone.tooltipInfo = Gantt.getTooltipForMilestoneLine(dateFormatted, localizationManager, dateTypesSettings, [milestone.type], [milestone.category]);

                    });
                }
            }
        });

        return tasks;
    }