Управление проектами — один из самых сложных аспектов ведения бизнеса в современном технологическом мире. В течение многих лет DHTMLX Gantt был надежным инструментом для создания бизнес-веб-приложений на основе многофункциональных диаграмм Ганта. Теперь пришло время вывести наш флагманский продукт на новый уровень, обновив его до версии 8.0.

Но самые важные улучшения этого обновления качества жизни вы найдете в Gantt API. Они предназначены для облегчения вашего опыта кодирования с помощью нашего компонента диаграммы Ганта JavaScript и помогают вам максимально использовать его в веб-проектах.

Прежде всего, мы упростили процесс обработки ресурсов проекта и связанных с ними заданий с помощью нескольких улучшений API. Мы надеемся, что вам пригодятся обновления алгоритмов автоматического планирования, временных ограничений, критического пути, резервного времени и группировки задач. Также есть несколько изменений для более эффективной работы с раздельными и сводными задачами. Кроме того, вы можете найти другие полезные вещи, такие как экран «пустого состояния» для Ганта, фоновая сетка в пустой временной шкале Ганта, встроенный API экспорта, подтверждение удаления задач со стороны сервера, новый способ добавления настраиваемый HTML-контент в ячейках временной шкалы и многое другое.

С визуальной точки зрения вы, безусловно, оцените новый дизайн образцов Ганта.

В этом сообщении блога мы представляем подробный обзор этого крупного обновления.

Новый дизайн для образцов Ганта

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

Теперь вы можете быстро найти ссылки на методы, свойства и события, используемые в конкретном образце, на вкладке Справочник по API. Вы также можете просмотреть исходный код, просто переключившись на вкладку Исходный код без необходимости открывать его в новом окне браузера. Если вы хотите поделиться определенным образцом со своей командой, вы можете просто скопировать ссылку на образец на вкладке «Поделиться». Чтобы открыть образец на новой странице, просто нажмите кнопку «Открыть образец».

Кроме того, образцы страниц теперь полностью адаптивны, поэтому они отлично работают на различных мобильных устройствах. Например, просмотреть исходный код или открыть ссылки на документацию со смартфона или планшета не проблема.

Упрощенная конфигурация управления ресурсами

Управление ресурсами, вероятно, является одной из самых востребованных функций нашего компонента Ганта, и мы придумали ряд идей о том, как оптимизировать ваш опыт кодирования с его помощью в версии 8.0.

Прежде всего, мы ввели возможность загрузки ресурсов и назначений ресурсов вместе с задачами и зависимостями между ними. Это можно сделать с помощью методов gantt.parse или gantt.load:

gantt.parse({
    tasks: [
        ...,
        {
            id: 5,
            text: "Interior office",
            type: "task",
            start_date: "03-04-2024 00:00",
            duration: 7,
            parent: "2",
            owner: [
            {
                    resource_id: "6",
                    value: 3,
                    start_date: "03-04-2024 00:00",
                    end_date: "05-04-2024 00:00",
            }]
        },
        ...
    ],
    links: [],
    resources: [
        {id: 6, text: "John", unit: "hours/day" },
        {id: 7, text: "Mike", unit: "hours/day" },
        {id: 8, text: "Anna", unit: "hours/day" },
        {id: 9, text: "Bill", unit: "hours/day" },
        {id: 10, text: "Floe", unit: "hours/day" }
    ]
});

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

Теперь любые изменения ресурсов и их назначения в диаграмме Ганта можно отправлять в обработчик данных отдельными записями с постоянными идентификаторами, что упрощает интеграцию с бэкенд-API.

gantt.config.resources = {
    dataprocessor_assignments: true,
    dataprocessor_resources: true,
};
gantt.createDataProcessor(function(entity, action, data, id){
       switch (entity) {
             case "task":
                    break;
             case "link":
                    break;
             case "resource":
                    break;
             case "assignment":
   
                   break;
             }
});

Также можно зафиксировать изменения, связанные с ресурсами, в обработчике, переключившись в режим пользовательской маршрутизации в dataProcessor или используя объявление функции.

В результате ресурсы Ганта можно загружать и сохранять так же, как задачи и ссылки.

В версии 8.0 вы также сможете воспользоваться многочисленными изменениями в конфигурации представления ресурсов.

Здесь следует отметить, что хранилище данных для ресурсов теперь создается автоматически при инициализации диаграммы Ганта. Чтобы внести дополнительные изменения в хранилище ресурсов, следует применить новую опцию gantt.config.resources:

gantt.config.resources = {
    resource_store: {
        type: "treeDataStore",
        fetchTasks: true,
        initItem: function(item) {
            item.parent = item.parent || gantt.config.root_id;
            item[gantt.config.resource_property] = item.parent;
            item.open = true;
            return item;
        }
    },
}

Но в то же время по-прежнему можно создать хранилище данных ресурсов вручную и использовать его по умолчанию.

Начиная с версии 8.0 у вас есть возможность сделать назначения ресурсов редактируемыми на диаграмме ресурсов с помощью следующей конфигурации:

gantt.config.resources = {
    editable_resource_diagram: true
};

И, наконец, теперь вы можете указать поведение элемента управления ресурсами в лайтбоксе с помощью функции lightbox_resources. По умолчанию элемент управления ресурсами будет заполнен данными из хранилища данных ресурсов.

Подробнее об этих важных дополнениях к нашему JavaScript Gantt можно прочитать в документации.

Сохранение древовидной структуры при группировке задач (PRO)

Группировка задач — широко используемая функция нашего Ганта, позволяющая быстро упорядочивать задачи Ганта по определенному признаку. Для версии 8.0 наши клиенты дали нам подсказку, как сделать ее еще лучше. До этого древовидная структура Ганта после группировки не сохранялась, т.е. задачи отображались плоским списком, что создавало некоторые неудобства для конечных пользователей. Это больше не проблема. Теперь после выполнения манипуляций с группировкой структура дерева Ганта остается видимой, когда родительская и дочерняя задачи принадлежат одной группе.

Чтобы помочь вам активировать эту полезную функцию через API, мы добавили новый логический параметр save_tree_structure в метод gantt.groupBy. Все, что вам нужно сделать, это установить для этого параметра значение true.

gantt.groupBy({
     groups: groups,
     relation_property: gantt.config.resource_property,
     group_id: "group_id",
     group_text: "text",
     delimiter: ", ",
     default_group_label: "No Material",
     save_tree_structure: true
});

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

Обратите внимание, что эта функция доступна только в PRO-версии DHTMLX Gantt.

Пустой экран состояния для Ганта

Ранее, если диаграмма Ганта, построенная с помощью DHTMLX, не содержала никаких задач, она отображалась пустой. Это может быть неверно истолковано начинающими пользователями как проблема с загрузкой диаграммы или любая другая ошибка, что приведет к путанице в отношении того, что делать дальше. Поэтому одной из задач, с которыми столкнулись наши клиенты, была реализация всеобъемлющего пустого состояния для Ганта.

Чтобы решить эту проблему, мы представили новую встроенную функцию «Пустой экран» в Гантте. Он полностью настраивается и может отображаться либо в сетке, либо в части временной шкалы диаграммы. Основная цель пустого экрана состояния — предложить конечным пользователям начать планировать свою деятельность, когда в диаграмму Ганта не загружены данные. В коде эта функция активируется через конфигурацию show_empty_state.

gantt.config.show_empty_state = true;

Кроме того, объект ext в Gantt API теперь также включает расширение emptyStateElement с набором методов, связанных с «пустым состоянием». Например, используя метод getContainer(), вы можете показать «пустое состояние» на временной шкале Ганта без каких-либо задач вместо сетки, т.е. изменить контейнер, к которому будет применяться «пустое состояние»:

gantt.ext.emptyStateElement.getContainer = function() {
      return gantt.$task_data.closest(".gantt_layout_content");
};

Также есть возможность изменить содержимое, отображаемое в сообщении «пустое состояние», с помощью метода renderContent():

gantt.ext.emptyStateElement.renderContent = function(container) {
       return `<div class='gantt_empty_state'>
           <div class='gantt_empty_state_image'></div>
           <div class='gantt_empty_state_text'>
                <div class='gantt_empty_state_text_link'     data-empty-state-create-task>${gantt.locale.labels.empty_state_text_link}</div>
           <div class='gantt_empty_state_text_description'>${gantt.locale.labels.empty_state_text_description}</div>
      </div>
</div>`;
};

Чтобы ознакомиться с другими новыми методами, представленными в расширении emptyStateElement, посетите эту страницу документации.

Фоновая сетка на пустой временной шкале Ганта

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

Чтобы добавить фоновую сетку на временную шкалу, вам потребуется следующая настройка:

gantt.config.timeline_placeholder = true;

При необходимости вы также можете выделить определенные столбцы и ячейки в фоновой сетке с помощью шаблона timeline_cell_class:

gantt.templates.timeline_cell_class = function (task, date) {
   if (!gantt.isWorkTime({ date: date, task: task })) {
       return "weekend";
   }
};

Что касается фоновых строк, то в шаблон будет добавлен временный объект задачи, как описано в документации.

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

Новый способ включения экспорта Ганта

Экспорт — важная функция DHTMLX Gantt. Ранее вы могли начать использовать его, включив экспортный файл api.js на HTML-страницу или поместив его в папку конфигурации и импортировав (при использовании JS-фреймворков и Node.js). В версии 8.0 мы предоставляем более удобный способ включения этой функции. Теперь вы можете настроить его для работы с методом plugins():

gantt.plugins({
   export_api: true
})

Узнайте больше об этой новинке в Миграционных заметках.

Наследование ограничений из проектов (PRO)

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

Новая версия библиотеки DHTMLX Gantt устраняет это неудобство, предлагая возможность наследовать ограничения задач проектного типа (или просто проектов) в их дочерних задачах. Это означает, что вам просто нужно установить желаемый тип ограничения для родительского проекта, который будет автоматически применяться к его дочерним элементам. При этом, если какая-либо из дочерних задач уже имеет собственное ограничение, оно не будет заменено ограничением родительской задачи.

Внутри эта функция включается путем изменения значения недавно добавленного свойства gantt.config.auto_scheduling_project_constraint с false (значение по умолчанию) на true.

gantt.config.auto_scheduling_project_constraint = true;

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

Обратите внимание, что эта функция доступна только в PRO-версии DHTMLX Gantt.

Улучшенный расчет критического пути и времени простоя

Своевременное выполнение проектов — основная цель использования диаграмм Ганта. Но часто бывает так, что в силу каких-то обстоятельств проектные задачи требуют дополнительного времени для выполнения. Это может стать настоящей головной болью для менеджера проекта, потому что такие задержки могут повлиять на общий срок проекта. В нашем Гантте вы можете рассчитать резервное время (свободное и общее) и критический путь для задач Ганта, чтобы быть готовым к таким чрезвычайным ситуациям. Новая версия включает несколько полезных изменений для этих функций.

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

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

Начиная с версии 8.0, алгоритмы, используемые в нашем Гантте для расчета критического пути, резервных периодов и автоматического планирования, также могут включать значения хода выполнения задачи, как и в MS Project.
Это поможет решить некоторые проблемы, связанные с выполненных задач (прогресс 100%) в указанных алгоритмах и обеспечить следующее:

  • Завершенные задачи имеют нулевой резерв
  • Завершенные задачи не учитываются в процессе автоматического планирования
  • Завершенные задачи не могут быть частью критического пути в Гантте

Эта функция отключена по умолчанию, и обновление не изменит поведение алгоритмов расчета Ганта в существующих приложениях наших клиентов.

С технической точки зрения это нововведение включается с помощью необязательного свойства auto_scheduling_use_progress:

gantt.config.auto_scheduling_use_progress = true;
gantt.init("gantt_here");

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

И помните, что свойство auto_scheduling_use_progress доступно только в PRO-версии DHTMLX Gantt.

Обновления для задач разделения и объединения

В DHTMLX Gantt возможности разделения и объединения задач имеют решающее значение для представления данных проекта в виде иерархий «родители-потомки» или в виде сводок.

В версии 8.0 мы даем вам больше свободы в плане настройки отдельных сводных и разделенных задач. Новый Гант позволяет применять различные стили для сводных и разделенных задач в зависимости от их положения на временной шкале.

Это делается с помощью шаблона task_class, дополненного новым свойством task.$rendered_at, которое указывает идентификатор строки, в которой отображается конкретная разделенная задача или элемент сводки. график Ганта:

gantt.templates.task_class = function(start, end, task) {
    if(task.$rendered_at) {
           if(gantt.calculateTaskLevel(gantt.getTask(task.$rendered_at)) === 1) {
                   return "phase-level-split-task"; // or "phase-level-rollup";
           }
    }
    return " ";
};

Теперь вы можете контролировать видимость каждой задачи объединения в ее родительском проекте. Это реализовано с помощью нового события onBeforeRollupTaskDisplay.

Мы также добавили опцию фильтрации для разделенных задач. Чтобы использовать эту полезную функцию управления задачами, вам потребуется использовать событие onBeforeSplitTaskDisplay и возвращать true или false для конкретной подзадачи. отображаться или не отображаться на диаграмме Ганта соответственно.

gantt.attachEvent("onBeforeSplitTaskDisplay", function (id, task, parent) {
       if (task.progress === 1) {
           return false;
       }
       return true;
});

И последнее, на что мы укажем в этом разделе, мы должны упомянуть, что свойство свертки задач Ганта с типом проекта теперь может принимать значение false. Это поможет гарантировать, что элементы свертки не будут отображаться в заданной задаче проекта. При всех других значениях свойства rollup задачи объединения будут отображаться в проектах как обычно.

Подтверждение сервера для удаленных задач

При выполнении базовых операций над задачами на диаграмме Ганта через UI необходимо убедиться, что эти действия корректно сохраняются на стороне сервера и информировать об этом пользователя. Для этой цели DHTMLX использует встроенную библиотеку DataProcessor. Но до недавнего времени он был ограничен сохранением изменений данных, связанных с созданием и редактированием задач.

Отныне объект DataProcessor включает новый параметр настройки deleteAfterConfirmation: true, который поможет справиться с удалением задач:

const dp = gantt.createDataProcessor({
    url: "/gantt/backend/data",
    mode: "REST",
    deleteAfterConfirmation: true
});

or

const dp = new gantt.dataProcessor("/api");
dp.init(gantt);
dp.setTransactionMode("REST");
dp.deleteAfterConfirmation = true;

Вот как это работает на практике:

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

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

Каждый проект по-своему уникален, и руководителям проектов может потребоваться добавить дополнительные визуальные элементы в ячейки временной шкалы для более эффективного управления задачами. До версии 8.0 такую ​​функциональность можно было реализовать только с помощью метода addTaskLayer(). Он служит для наложения дополнительного слоя с пользовательскими элементами для задач на временной шкале.

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

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

Используя DHTMLX Gantt 8.0, вы можете добавлять собственный контент с изображениями, значками или другими пользовательскими элементами HTML в любые ячейки временной шкалы с помощью специального шаблона — timeline_cell_content.

Вот так реализован в коде шаблон timeline_cell_content:

gantt.templates.timeline_cell_content = function (task, date) {
   if (17 <= task.id && task.id <= 20){
       const demoValue = randomValueForDate(date, 7)
       var value2 = Math.round(demoValue + demoValue * 0.15);
       return `<div class='cost'>${randomValueForDate(date, 7)}</div>
       <div class='cost'>${value2}</div>`;
   }
   return "";
};

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

Следует отметить, что пользовательское содержимое в ячейках будет отображаться «под» панелями задач, т.е. панели задач будут иметь более высокий z-индекс. Поэтому содержимое ячейки не будет видно, когда панель задач будет размещена поверх нее.

Когда необходимо показать содержимое над панелью задач, вам нужно добавить z-индекс к пользовательскому элементу:

.cost{
  position:absolute;
  z-index: 5;
  pointer-events: none;
}

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

Новая опция поиска для задач проекта

Компонент DHTMLX Gantt версии 8.0 поставляется с новым параметром поиска для метода getTaskBy(). Точнее, теперь этот метод позволяет искать задачи проектного типа. В более ранних версиях приходилось прибегать к использованию функции в качестве параметра метода для перебора не только обычных задач и вех, но и проектов:

var task = gantt.getTaskBy(function(task){
   return task.text == "Project #2";
});
console.log(task);

Это может вызвать некоторые неудобства и снизить производительность Ганта. Таким образом, мы добавили необязательный параметр, чтобы указать, какие типы задач должны быть возвращены.

Например, вы можете выбрать все типы задач, установив их значения в третьем параметре на true:

gantt.getTaskBy("progress", 1, { task: true, project: true, milestone: true })

В случае, если вы хотите видеть только проекты, вам просто нужно установить project: true в параметре:

gantt.getTaskBy("progress", 1, { project: true})

Это основные функции, реализованные в DHTMLX Gantt 8.0.

Источник: релизная статья, опубликованная 20 марта 2023 г. в блоге DHTMLX.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.