dhtmlxGantt поддерживает два формата данных для загрузки:
Для загрузки данных в диаграмму Ганта вы можете использовать методы gantt.parse
или gantt.load
.
gantt.init("gantt_here");
gantt.load("tasks.json");
Related sample: Basic initialization
Если переданные в Gantt данные некорректны, их древовидная структура может стать циклической, что приведет к ошибке циклической ссылки.
Если вы хотите загрузить данные непосредственно из объекта, метод gantt.parse
— это то, что вам нужно:
Загрузка из встроенного источника данных
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);
Related sample: Basic initialization
Если ваши данные содержат значения "start_date" и "end_date", и даты представлены в упрощенном формате (например, 01-12-2021 без времени), может потребоваться дополнительная конфигурация. Ознакомьтесь с этим руководством: Отображение даты окончания задачи и включительные даты окончания.
Для получения данных с сервера используйте метод gantt.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 вы можете определить маршрут сервера для обработки AJAX-запросов Gantt:
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 });
});
});
});
Список поддерживаемых форматов данных можно найти в статье Поддерживаемые Форматы Данных.
Существует три способа определить расписание задачи в потоке данных:
Если одно из свойств отсутствует, Gantt рассчитывает его на основе двух других.
Related sample: 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
}
// Задача будет загружена с пересчитанной длительностью на основе 'start_date' и 'end_date'
{
"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:
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);
};
Вот некоторая ясность о том, как правильно обрабатывать и отображать даты окончания задач.
Gantt может интерпретировать эти даты так, что это приведет к неожиданным результатам. Например:
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
Здесь даты начала и окончания указывают на один и тот же момент времени, в результате чего длительность равна 0.
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:[]);
В этом случае отображаемая дата окончания может показаться вводящей в заблуждение, так как она может выглядеть как 3 апреля, хотя задача фактически заканчивается 2 апреля.
Даже если даты задачи не содержат временных деталей, Gantt сохраняет их как объекты JS Date с включенным временем. Вот как это работает:
Если дата окончания отображается без времени, она может выглядеть вводящей в заблуждение, как показано в Сценарии 2. Однако это поведение по умолчанию можно изменить через конфигурацию. Следующий раздел предоставляет решения для этого.
1) Первое, чего стоит избегать, это изменение фактических дат задач, хранящихся в диаграмме Ганта.
Иногда вы можете рассмотреть возможность изменения дат задач, загружаемых в 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, дата окончания будет отображаться как 2 апреля 2020 года:
Вот код для этого изменения:
// переопределение конфигурации колонок
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");
Этот подход обновляет дату окончания задачи во всем гриде, заголовках лайтбокса и других местах, где появляется дата окончания.
Если вы используете включительный формат даты окончания и хотите, чтобы он работал с встроенным редактированием, вам потребуется создать пользовательский редактор для редактирования включительных дат окончания задач. Вот пример:
// включительный редактор для дат окончания
// используйте редактор по умолчанию, но переопределите методы 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}
];
// измените шаблоны лайтбокса и грида для отображения дат задач в включительном формате
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 sample: Редактор включительных дат окончания
2b) Если ваше приложение требует, чтобы "включительные" даты окончания были сохранены (например, однодневная задача, начинающаяся 2 апреля 2020 года, будет иметь start_date: "02-04-2022"
и end_date: "02-04-2022"
), вам нужно будет выполнить следующее:
Источник данных диаграммы Ганта — это объект, содержащий два типа информации:
Для полного списка свойств объекта задачи, смотрите статью Свойства задачи.
Формат даты по умолчанию для данных 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
.
Для полного списка свойств объекта связи, смотрите статью Свойства связи.
Вы можете добавлять пользовательские свойства к элементам данных, помимо обязательных. Эти дополнительные свойства будут разобраны как строки и загружены на клиентскую сторону для дальнейшего использования по мере необходимости.
Ознакомьтесь с примерами данных с пользовательскими свойствами здесь.
При использовании базы данных лучше иметь отдельные таблицы для задач и связей.
Рекомендуемая структура для базы данных для загрузки задач и связей в диаграмму Ганта выглядит следующим образом:
Вот 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`)
);
Вот последовательность событий для методов загрузки данных:
onBeforeParse
onTaskLoading
onParse
onLoadStart
onLoadEnd
onBeforeDataRender
onBeforeTaskDisplay
onDataRender
onBeforeGanttRender
onGanttRender