Перейти к основному содержимому

Загрузка данных

dhtmlxGantt поддерживает два формата данных для загрузки информации:

Для заполнения диаграммы Gantt данными вы можете использовать методы parse или load.

gantt.init("gantt_here");
gantt.load("tasks.json");

Basic initialization

заметка

Предоставление некорректных данных в Gantt может привести к тому, что его древовидная структура станет циклической, что вызовет ошибку циклической ссылки.

Загрузка из объекта


Если вы хотите загрузить данные напрямую из объекта, используйте метод parse:

Loading from an inline data source

var data = {
tasks:[
{id:1, text:"Project #1", start_date:"01-04-2020", duration:18},
{id:2, text:"Task #1", start_date:"02-04-2020", duration:8, parent:1},
{id:3, text:"Task #2", start_date:"11-04-2020", duration:8, parent:1}
]
};
gantt.init("gantt_here");
gantt.parse(data); /*!*/

Basic initialization

заметка

Если ваши объекты данных содержат одновременно "start_date" и "end_date", но значения дат включают только дату (например, 01-12-2021, без времени), может потребоваться дополнительная настройка. Подробнее смотрите в разделе Отображение даты окончания задачи и включительно конец периода.

Загрузка с сервера


На стороне клиента

Для получения данных с сервера используйте метод load:

gantt.html

gantt.init("gantt_here");
gantt.load("data.json"); /*!*/

Метод load отправляет AJAX-запрос по указанному URL и ожидает ответ с данными в одном из поддерживаемых форматов. Например:

data.json

{
"tasks":[
{"id":1, "text":"Project #1", "start_date":"01-04-2020", "duration":18},
{"id":2, "text":"Task #1", "start_date":"02-04-2020","duration":8, "parent":1},
{"id":3, "text":"Task #2", "start_date":"11-04-2020","duration":8, "parent":1}
],
"links":[
{"id":1, "source":1, "target":2, "type":"1"},
{"id":2, "source":2, "target":3, "type":"0"}
]
}

Вы можете указать формат во втором аргументе метода: "json", "xml" или "oldxml".

gantt.load("data.xml", "xml");

На стороне сервера

На сервере у вас может быть статический файл с данными или скрипт, который собирает данные из источника и отправляет их в ответе. Настройка на сервере зависит от используемого вами фреймворка.

заметка

Подробные инструкции и примеры кода для различных платформ смотрите в Интеграция с серверной стороной.

Например, в Node.js вы настраиваете маршрут сервера, который обрабатывает URL, по которому Gantt отправляет AJAX-запрос за данными.

gantt.load("/data"); 

Этот маршрут должен возвращать JSON примерно такого вида:

app.get("/data", function(req, res){
db.query("SELECT * FROM gantt_tasks", function(err, rows){
if (err) console.log(err);
db.query("SELECT * FROM gantt_links", function(err, links){
if (err) console.log(err);
for (var i = 0; i < rows.length; i++){
rows[i].start_date = rows[i].start_date.format("YYYY-MM-DD");
rows[i].open = true;
}

res.send({ tasks:rows, links : links });
});
});
});
заметка

Все поддерживаемые форматы данных перечислены в Поддерживаемые форматы данных.

Загрузка дат задач


Определение расписания задачи

Есть три способа задать расписание задачи в данных:

  • start_date + duration
  • start_date + end_date
  • duration + end_date

Свойство, которое не указано, будет вычислено на основе двух других.

Backward planning

Свойство end_date имеет приоритет над duration. Если указаны все три параметра, Gantt проигнорирует duration и вычислит его на основе дат начала и окончания. Например:

{
"id":"20", "text":"Project #2",
"start_date":"01-04-2025",
"duration":3,
"end_date":"05-04-2025",
"order":10,"progress":0.4,
"type": "project", "open": true
}

// На самом деле задача будет загружена с duration, вычисленным по датам начала и окончания:
{
"id":"20", "text":"Project #2",
"start_date":"01-04-2025",
"duration":4,
"end_date":"05-04-2025",
"order":10,"progress":0.4,
"type": "project", "open": true
}

Использование ISO-формата даты

Gantt поддерживает ISO-формат даты. Для его использования необходимо переопределить функции парсинга и форматирования дат:

gantt.templates.parse_date = function(date) { 
return new Date(date);
};
gantt.templates.format_date = function(date) {
return date.toISOString();
};

Динамическое изменение формата даты

Если вы хотите изменить формат даты на лету, обновите шаблон parse_date следующим образом:

var cfg = gantt.config;
var strToDate = gantt.date.str_to_date(cfg.date_format, cfg.server_utc);

gantt.templates.parse_date = function(date){
return strToDate (date);
};

Отображение даты окончания задачи и включительно конец периода

В этом разделе объясняется, как правильно сохранять и отображать дату окончания задачи.

Сначала рассмотрим два распространённых сценария при работе с датами задач:

Сценарий 1

  • Длительность задачи измеряется в целых днях (duration_unit="day")
  • Данные задачи содержат даты начала и окончания в формате "%Y-%m-%d" или "%d-%m-%Y" (без времени)

Из-за того, как dhtmlxGantt интерпретирует и хранит даты окончания задач, результат может отличаться от ожидаемого.

Пример:

gantt.parse({ tasks: [
{
id: 1,
text: "Task 1",
start_date: "22-12-2021",
end_date: "22-12-2021"
}
]}, links:[]);

console.log(gantt.getTask(1).end_date);
// 22 декабря 2021 00:00:00

console.log(gantt.getTask(1).duration);
// 0

В этом случае даты начала и окончания совпадают, поэтому длительность задачи равна нулю.

Сценарий 2

  • В гриде отображается End Date
  • Формат даты окончания не содержит времени
gantt.config.columns = [
{name: "text", label: "Name", tree: true, width: 200, resize: true},
{name: "duration", label: "Duration", width:80, align: "center", resize: true},
{name: "start_date", label: "Start", width:80, align: "center", resize: true},
{name: "end_date", label: "Finish", width:80, align: "center", resize: true}
];

gantt.init("gantt_here");

gantt.parse({ tasks: [
{
id: 1,
text: "Task 1",
start_date: "02-04-2020",
end_date: "02-04-2020"
}
]}, links:[]);

Здесь в гриде дата окончания (end_date) отображается как 3 апреля, хотя задача фактически завершается в конце 2 апреля.

Далее объясняется, как Gantt хранит даты окончания.

Как Gantt хранит даты окончания

Даже если часть времени не указана (duration_unit = "day"), dhtmlxGantt всегда хранит даты как объекты JavaScript Date, которые содержат компоненты времени.

Формат хранения дат окончания:

  • Секунды и миллисекунды всегда равны нулю, так как Gantt не поддерживает единицы меньше одной минуты
  • Дата окончания указывает на начало дня (или часа), следующего за последним активным днём (или часом). Например:
    • Задача, начинающаяся 2 апреля и длящаяся 1 день, будет иметь даты начала и окончания: "02-04-2022 00:00:00 - 03-04-2022 00:00:00". Дата окончания указывает на начало 3 апреля.
    • Задача, начинающаяся 2 апреля в 13:00 и длящаяся 1 час, будет иметь даты: "02-04-2022 13:00:00 - 02-04-2022 14:00:00". Дата окончания указывает на начало следующего часа.

Если дата окончания отображается без времени, это может ввести в заблуждение. В примере из Сценария 2 даты выглядят как "02-04-2022 - 03-04-2022", что можно ошибочно интерпретировать как двухдневную задачу вместо однодневной.

Это стандартное поведение. Хотя оно может сбивать с толку, доступны настройки, позволяющие это изменить, о чём рассказывается в следующих разделах.

Как изменить поведение по умолчанию?

1) Первое, чего следует избегать - это изменение фактических дат задач, хранящихся в Gantt.

Возможно, вы захотите изменить даты задач при загрузке в Gantt, например, устанавливая дату окончания как 02-04-2022 23:59:59. Тем не менее, лучше не использовать этот подход, так как это может привести к конфликтам в расчетах длительности задач и авто-планировании.

Вместо этого рекомендуем использовать следующие методы:

2a) Чтобы изменить формат отображения дат окончания задач в Gantt (например, чтобы включить дату окончания в длительность задачи), вы можете переопределить шаблон task_end_date.

Рассмотрим задачу, начинающуюся 2 апреля 2020 года, с длительностью один день, и посмотрим, как шаблон влияет на дату окончания.

По умолчанию дата окончания задачи отображается как 3 апреля 2020 года (03-04-2020 00:00:00):

task_end_date_template_default

Но если использовать шаблон task_end_date, та же задача будет отображаться как завершающаяся 2 апреля 2020 года:

task_end_date_template

Пример кода:

// переопределяем конфигурацию колонок
gantt.config.columns = [
{name: "wbs", label: "#", width: 60, align: "center", template: gantt.getWBSCode},
{name: "text", label: "Name", tree: true, width: 200, resize: true},
{name: "start_date", label: "Start", width:80, align: "center", resize: true},
{name: "end_date", label: "Finish", width:80, align: "center", resize: true},
{name:"add"}
];

// переопределяем шаблон
gantt.templates.task_end_date = function(date){
return gantt.templates.task_date(new Date(date.valueOf() - 1));
};

var gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");
gantt.templates.grid_date_format = function(date, column){
if(column === "end_date"){
return gridDateToStr(new Date(date.valueOf() - 1));
}else{
return gridDateToStr(date);
}
}
gantt.init("gantt_here");

Этот способ меняет отображение даты окончания задачи в гриде, заголовке lightbox и других местах, где отображается дата окончания.

Если вы используете формат включающей даты окончания и хотите, чтобы он корректно работал с inline editing в гриде, потребуется создать собственный редактор для редактирования включающих дат окончания, например:

// редактор для включающих дат окончания
// используем стандартный редактор, но переопределяем методы set_value/get_value
var dateEditor = gantt.config.editor_types.date;
gantt.config.editor_types.end_date = gantt.mixin({
set_value: function(value, id, column, node){
var correctedValue = gantt.date.add(value, -1, "day");
return dateEditor.set_value.apply(this, [correctedValue, id, column, node]);
},
get_value: function(id, column, node) {
var selectedValue = dateEditor.get_value.apply(this, [id, column, node]);
return gantt.date.add(selectedValue, 1, "day");
},
}, dateEditor);

var textEditor = {type: "text", map_to: "text"};
var startDateEditor = {type: "date", map_to: "start_date"};
var endDateEditor = {type: "end_date", map_to: "end_date"};
var durationEditor = {type: "number", map_to: "duration", min:0, max: 100};

gantt.config.columns = [
{name: "text", label: "Name", tree: true, width: 200, editor: textEditor,
resize: true},
{name: "duration", label: "Duration", width:80, align: "center",
editor: durationEditor, resize: true},
{name: "start_date", label: "Start", width:140, align: "center",
editor: startDateEditor, resize: true},
{name: "end_date", label: "Finish", width:140, align: "center",
editor: endDateEditor, resize: true}
];

// изменяем шаблоны lightbox и грида для отображения дат задач во включающем формате
gantt.templates.task_end_date = function(date){
return gantt.templates.task_date(new Date(date.valueOf() - 1));
};

var gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");
gantt.templates.grid_date_format = function(date, column){
if(column === "end_date"){
return gridDateToStr(new Date(date.valueOf() - 1));
}else{
return gridDateToStr(date);
}
}

Related example: Редактор включающей даты окончания

2b) Если другим частям вашего приложения нужны даты окончания, сохранённые во "включающем" формате (т.е. задача, начинающаяся 2 апреля 2020 года и длящаяся один день, хранится с start_date: "02-04-2022", end_date: "02-04-2022"), потребуется дополнительная обработка дат окончания:

  • добавляйте один день к датам окончания перед загрузкой данных в Gantt
  • вычитайте один день из дат окончания перед сохранением изменений из Gantt обратно в хранилище данных

Свойства данных


Источник данных для диаграммы Gantt - это объект, содержащий два основных типа информации:

  • tasks - элементы задач.
  • links - связи-зависимости.

Свойства объекта задачи

заметка

Полный список свойств объекта задачи приведён в статье Task properties.

Формат дат по умолчанию для JSON и XML данных - "%d-%m-%Y %H:%i" (см. спецификацию формата даты).

Чтобы изменить его, используйте опцию конфигурации date_format.

gantt.config.date_format="%Y-%m-%d";
gantt.init("gantt_here");

После загрузки в Gantt свойства start_date и end_date преобразуются в объекты Date.

Если ваши форматы дат не поддерживаются конфигом date_format, вы можете выполнить парсинг вручную с помощью шаблона parse_date.

заметка

Полный список свойств объекта связи доступен в статье Link properties.

Пользовательские свойства

Вы не ограничены обязательными свойствами и можете добавлять любые пользовательские свойства в ваши элементы данных. Дополнительные свойства будут распознаны как строки и отправлены на клиентскую сторону, где вы сможете использовать их по своему усмотрению.

Примеры данных с пользовательскими свойствами смотрите здесь.

Структура базы данных


Для работы с базой данных рекомендуется использовать две отдельные таблицы: одну для задач, другую - для связей.

tutorial_db_tables

Типичная структура базы данных для загрузки задач и связей в диаграмму Gantt выглядит так:

  • gantt_tasks - таблица для хранения задач Gantt
    • id - (string,number) идентификатор задачи.
    • start_date - (Date) дата начала задачи.
    • text - (string) описание задачи.
    • progress - (number) от 0 до 1, процент выполнения задачи.
    • duration - (number) длительность задачи в текущих единицах времени.
    • parent - (number) идентификатор родительской задачи.
    • type - (string) необязательное, тип задачи.
    • readonly - (boolean) необязательное, помечает задачу как только для чтения.
    • editable - (boolean) необязательное, помечает задачу как доступную для редактирования.
  • gantt_links - таблица для хранения связей Gantt
    • id - (string,number) идентификатор связи.
    • source - (number) идентификатор исходной задачи.
    • target - (number) идентификатор целевой задачи.
    • type - (string) тип зависимости:
      • 0 - 'finish_to_start'
      • 1 - 'start_to_start'
      • 2 - 'finish_to_finish'
      • 3 - 'start_to_finish'
    • lag - (number) необязательное, лаг задачи.
    • readonly - (boolean) необязательное, помечает связь как только для чтения.
    • editable - (boolean) необязательное, помечает связь как доступную для редактирования.

Для создания этих двух таблиц используйте следующий SQL:

CREATE TABLE `gantt_links` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`source` int(11) NOT NULL,
`target` int(11) NOT NULL,
`type` varchar(1) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE `gantt_tasks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`text` varchar(255) NOT NULL,
`start_date` datetime NOT NULL,
`duration` int(11) NOT NULL,
`progress` float NOT NULL,
`sortorder` int(11) NOT NULL,
`parent` int(11) NOT NULL,
PRIMARY KEY (`id`)
)

Поток событий


Ниже представлен поток событий, связанных с методами загрузки:

gantt.parse():

gantt.load()

gantt.refreshData():

gantt.render():