UNPKG

suivi-dhx-trial-gantt

Version:

An open source JavaScript Gantt chart that helps you illustrate a project schedule in a nice-looking chart.

395 lines (343 loc) 16 kB
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"> <title>Resource histogram</title> <script src="../../codebase/dhtmlxgantt.js?v=9.0.7"></script> <script src="./common/resource_filter.js?v=9.0.7"></script> <link rel="stylesheet" href="../../codebase/dhtmlxgantt.css?v=9.0.7"> <link rel="stylesheet" href="../common/controls_styles.css?v=9.0.7"> <style> html, body { padding: 0px; margin: 0px; height: 100%; } #gantt_here { width:100%; height: 100vh; } .gantt_grid_scale .gantt_grid_head_cell, .gantt_task .gantt_task_scale .gantt_scale_cell { font-weight: bold; font-size: 14px; color: rgba(0, 0, 0, 0.7); } .folder_row { font-weight: bold; } .highlighted_resource, .highlighted_resource.odd { background-color: rgba(255, 251, 224, 0.6); } .gantt_task_cell.week_end { background-color: #e8e8e87d; } .gantt_task_row.gantt_selected .gantt_task_cell.week_end { background-color: #e8e8e87d !important; } .group_row, .group_row.odd, .gantt_task_row.group_row { background-color: rgba(232, 232, 232, 0.6); } .owner-label { width: 20px; height: 20px; line-height: 20px; font-size: 12px; display: inline-block; border: 1px solid #cccccc; border-radius: 25px; background: #e6e6e6; color: #6f6f6f; margin: 0 3px; font-weight: bold; } .resource-select-panel .gantt_layout_content { line-height: 35px; text-align: right; padding-right: 15px; overflow: hidden !important; } .resource-select { padding: 3px; margin-left: 13px; } .column_overload .gantt_histogram_fill { background-color:color-mix(in srgb, var(--dhx-gantt-base-colors-error), transparent 60%); } </style> </head> <body> <div id="gantt_here"></div> <script> gantt.plugins({ grouping: true, auto_scheduling: true }); // enable parsing the resource data using built-in functions and names gantt.config.resources = true; gantt.config.resource_store = "resource"; gantt.config.resource_property = "owner"; gantt.config.order_branch = true; gantt.config.open_tree_initially = true; // configuration of the columns in the main Grid gantt.config.columns = [ { name: "text", tree: true, width: 200, resize: true }, { name: "start_date", align: "center", width: 100, resize: true }, { name: "owner", align: "center", width: 75, label: "Owner", template: function (task) { if (task.type == gantt.config.types.project) { return ""; } const resources = gantt.getTaskResources(task.id); if (!resources.length) { return "Unassigned"; } else if (resources.length === 1) { return resources[0].text; } else { return resources.map(function (resource) { return "<div class='owner-label' title='" + resource.text + "'>" + resource.text.substr(0, 1) + "</div>"; }).join(""); } }, resize: true }, { name: "duration", width: 60, align: "center", resize: true }, { name: "add", width: 44 } ]; const UNASSIGNED_ID = 5; const WORK_DAY = 8; gantt.templates.timeline_cell_class = function (task, date) { if (!gantt.isWorkTime({ date: date, task: task })) return "week_end"; return ""; }; function getAllocatedValue(tasks, resource) { let result = 0; tasks.forEach(function (item) { const assignments = gantt.getResourceAssignments(resource.id, item.id); assignments.forEach(function (assignment) { result += Number(assignment.value); }); }); return result; } const cap = {}; function getCapacity(date, resource) { /* it is sample function your could to define your own function for get Capability of resources in day */ if (gantt.$resourcesStore.hasChild(resource.id)) { return -1; } let val = date.valueOf(); if (!cap[val + resource.id]) { cap[val + resource.id] = [0, 1, 2, 3][Math.floor(Math.random() * 100) % 4]; } return cap[val + resource.id] * WORK_DAY; } gantt.templates.histogram_cell_class = function (start_date, end_date, resource, tasks) { if (getAllocatedValue(tasks, resource) > getCapacity(start_date, resource)) { return "column_overload" } }; gantt.templates.histogram_cell_label = function (start_date, end_date, resource, tasks) { if (tasks.length && !gantt.$resourcesStore.hasChild(resource.id)) { return getAllocatedValue(tasks, resource) + "/" + getCapacity(start_date, resource); } else { if (!gantt.$resourcesStore.hasChild(resource.id)) { return '&ndash;'; } return ''; } }; gantt.templates.histogram_cell_allocated = function (start_date, end_date, resource, tasks) { return getAllocatedValue(tasks, resource); }; gantt.templates.histogram_cell_capacity = function (start_date, end_date, resource, tasks) { if (!gantt.isWorkTime(start_date)) { return 0; } return getCapacity(start_date, resource); }; const resourceTemplates = { grid_row_class: function (start, end, resource) { const css = []; if (gantt.$resourcesStore.hasChild(resource.id)) { css.push("folder_row"); css.push("group_row"); } return css.join(" "); }, task_row_class: function (start, end, resource) { const css = []; if (gantt.$resourcesStore.hasChild(resource.id)) { css.push("group_row"); } return css.join(" "); } }; // Lightbox sections (edit form) gantt.locale.labels.section_resources = "Owners"; gantt.config.lightbox.sections = [ { name: "description", height: 38, map_to: "text", type: "textarea", focus: true }, { name: "resources", type: "resources", map_to: "auto", default_value: 8 }, { name: "time", type: "duration", map_to: "auto" } ]; gantt.config.resource_render_empty_cells = true; function getResourceAssignments(resourceId) { let assignments; const store = gantt.getDatastore(gantt.config.resource_store); if (store.hasChild(resourceId)) { assignments = []; store.getChildren(resourceId).forEach(function (childId) { assignments = assignments.concat(gantt.getResourceAssignments(childId)); }); } else { assignments = gantt.getResourceAssignments(resourceId); } return assignments; } const resourceConfig = { scale_height: 30, row_height: 45, scales: [ { unit: "day", step: 1, date: "%d %M" } ], columns: [ { name: "name", label: "Name", tree: true, width: 200, template: function (resource) { return resource.text; }, resize: true }, { name: "progress", label: "Complete", align: "center", template: function (resource) { const store = gantt.getDatastore(gantt.config.resource_store); let totalToDo = 0, totalDone = 0; const assignments = getResourceAssignments(resource.id); assignments.forEach(function (assignment) { const task = gantt.getTask(assignment.task_id); totalToDo += task.duration; totalDone += task.duration * (task.progress || 0); }); let completion = 0; if (totalToDo) { completion = (totalDone / totalToDo) * 100; } return Math.floor(completion) + "%"; }, resize: true }, { name: "workload", label: "Workload", align: "center", template: function (resource) { let totalDuration = 0; const assignments = getResourceAssignments(resource.id); assignments.forEach(function (assignment) { const task = gantt.getTask(assignment.task_id); totalDuration += Number(assignment.value) * task.duration; }); return (totalDuration || 0) + "h"; }, resize: true }, { name: "capacity", label: "Capacity", align: "center", template: function (resource) { const store = gantt.getDatastore(gantt.config.resource_store); const n = store.hasChild(resource.id) ? store.getChildren(resource.id).length : 1 const state = gantt.getState(); return gantt.calculateDuration(state.min_date, state.max_date) * n * WORK_DAY + "h"; } } ] }; gantt.config.layout = { css: "gantt_container", rows: [ { gravity: 2, cols: [ { view: "grid", group: "grids", scrollY: "scrollVer" }, { resizer: true, width: 1 }, { view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer" }, { view: "scrollbar", id: "scrollVer", group: "vertical" } ] }, { resizer: true, width: 1, next: "resources" }, { height: 35, cols: [ { html: "<label>Resource<select class='resource-select'></select>", css: "resource-select-panel", group: "grids" }, { resizer: true, width: 1 }, { html: "" } ] }, { gravity: 1, id: "resources", config: resourceConfig, templates: resourceTemplates, cols: [ { view: "resourceGrid", group: "grids", scrollY: "resourceVScroll" }, { resizer: true, width: 1 }, { view: "resourceHistogram", capacity: 24, scrollX: "scrollHor", scrollY: "resourceVScroll" }, { view: "scrollbar", id: "resourceVScroll", group: "vertical" } ] }, { view: "scrollbar", id: "scrollHor" } ] }; gantt.init("gantt_here"); gantt.parse({ "data": [ { "id": 1, "text": "Office itinerancy", "type": "project", "start_date": "02-04-2025 00:00", "duration": 17, "progress": 0.4, "owner": [{ "resource_id": "5", "value": 3 }], "parent": 0 }, { "id": 2, "text": "Office facing", "type": "project", "start_date": "02-04-2025 00:00", "duration": 8, "progress": 0.6, "owner": [{ "resource_id": "5", "value": 4 }], "parent": "1" }, { "id": 3, "text": "Furniture installation", "type": "project", "start_date": "11-04-2025 00:00", "duration": 8, "parent": "1", "progress": 0.6, "owner": [{ "resource_id": "5", "value": 2 }] }, { "id": 4, "text": "The employee relocation", "type": "project", "start_date": "13-04-2025 00:00", "duration": 5, "parent": "1", "progress": 0.5, "owner": [{ "resource_id": "5", "value": 4 }], "priority": 3 }, { "id": 5, "text": "Interior office", "type": "task", "start_date": "03-04-2025 00:00", "duration": 7, "parent": "2", "progress": 0.6, "owner": [{ "resource_id": "6", "value": 5 }], "priority": 1 }, { "id": 6, "text": "Air conditioners check", "type": "task", "start_date": "03-04-2025 00:00", "duration": 7, "parent": "2", "progress": 0.6, "owner": [{ "resource_id": "7", "value": 1 }], "priority": 2 }, { "id": 7, "text": "Workplaces preparation", "type": "task", "start_date": "12-04-2025 00:00", "duration": 8, "parent": "3", "progress": 0.6, "owner": [{ "resource_id": "10", "value": 2 }] }, { "id": 8, "text": "Preparing workplaces", "type": "task", "start_date": "14-04-2025 00:00", "duration": 5, "parent": "4", "progress": 0.5, "owner": [{ "resource_id": "10", "value": 4 }, { "resource_id": "9", "value": 5 }], "priority": 1 }, { "id": 9, "text": "Workplaces importation", "type": "task", "start_date": "21-04-2025 00:00", "duration": 4, "parent": "4", "progress": 0.5, "owner": [{ "resource_id": "7", "value": 3 }] }, { "id": 10, "text": "Workplaces exportation", "type": "task", "start_date": "27-04-2025 00:00", "duration": 3, "parent": "4", "progress": 0.5, "owner": [{ "resource_id": "8", "value": 5 }], "priority": 2 }, { "id": 11, "text": "Product launch", "type": "project", "progress": 0.6, "start_date": "02-04-2025 00:00", "duration": 13, "owner": [{ "resource_id": "5", "value": 4 }], "parent": 0 }, { "id": 12, "text": "Perform Initial testing", "type": "task", "start_date": "03-04-2025 00:00", "duration": 5, "parent": "11", "progress": 1, "owner": [{ "resource_id": "7", "value": 6 }] }, { "id": 13, "text": "Development", "type": "project", "start_date": "03-04-2025 00:00", "duration": 11, "parent": "11", "progress": 0.5, "owner": [{ "resource_id": "5", "value": 2 }] }, { "id": 14, "text": "Analysis", "type": "task", "start_date": "03-04-2025 00:00", "duration": 6, "parent": "11", "owner": [], "progress": 0.8 }, { "id": 15, "text": "Design", "type": "project", "start_date": "03-04-2025 00:00", "duration": 5, "parent": "11", "progress": 0.2, "owner": [{ "resource_id": "5", "value": 5 }] }, { "id": 16, "text": "Documentation creation", "type": "task", "start_date": "03-04-2025 00:00", "duration": 7, "parent": "11", "progress": 0, "owner": [{ "resource_id": "7", "value": 2 }], "priority": 1 }, { "id": 17, "text": "Develop System", "type": "task", "start_date": "03-04-2025 00:00", "duration": 2, "parent": "13", "progress": 1, "owner": [{ "resource_id": "8", "value": 1 }], "priority": 2 }, { "id": 25, "text": "Beta Release", "type": "milestone", "start_date": "06-04-2025 00:00", "parent": "13", "progress": 0, "owner": [{ "resource_id": "5", "value": 1 }], "duration": 0 }, { "id": 18, "text": "Integrate System", "type": "task", "start_date": "10-04-2025 00:00", "duration": 2, "parent": "13", "progress": 0.8, "owner": [{ "resource_id": "6", "value": 2 }], "priority": 3 }, { "id": 19, "text": "Test", "type": "task", "start_date": "13-04-2025 00:00", "duration": 4, "parent": "13", "progress": 0.2, "owner": [{ "resource_id": "6", "value": 3 }] }, { "id": 20, "text": "Marketing", "type": "task", "start_date": "13-04-2025 00:00", "duration": 4, "parent": "13", "progress": 0, "owner": [{ "resource_id": "8", "value": 4 }], "priority": 1 }, { "id": 21, "text": "Design database", "type": "task", "start_date": "03-04-2025 00:00", "duration": 4, "parent": "15", "progress": 0.5, "owner": [{ "resource_id": "6", "value": 5 }] }, { "id": 22, "text": "Software design", "type": "task", "start_date": "03-04-2025 00:00", "duration": 4, "parent": "15", "progress": 0.1, "owner": [{ "resource_id": "8", "value": 3 }], "priority": 1 }, { "id": 23, "text": "Interface setup", "type": "task", "start_date": "03-04-2025 00:00", "duration": 5, "parent": "15", "progress": 0, "owner": [{ "resource_id": "8", "value": 5 }], "priority": 1 }, { "id": 24, "text": "Release v1.0", "type": "milestone", "start_date": "20-04-2025 00:00", "parent": "11", "progress": 0, "owner": [{ "resource_id": "5", "value": 3 }], "duration": 0 } ], "links": [ { "id": "2", "source": "2", "target": "3", "type": "0" }, { "id": "3", "source": "3", "target": "4", "type": "0" }, { "id": "7", "source": "8", "target": "9", "type": "0" }, { "id": "8", "source": "9", "target": "10", "type": "0" }, { "id": "16", "source": "17", "target": "25", "type": "0" }, { "id": "17", "source": "18", "target": "19", "type": "0" }, { "id": "18", "source": "19", "target": "20", "type": "0" }, { "id": "22", "source": "13", "target": "24", "type": "0" }, { "id": "23", "source": "25", "target": "18", "type": "0" } ], // load resource values "resources": [ { "id": 1, "text": "QA", "parent": null }, { "id": 2, "text": "Development", "parent": null }, { "id": 3, "text": "Sales", "parent": null }, { "id": 4, "text": "Other", "parent": null }, { "id": 5, "text": "Unassigned", "parent": 4 }, { "id": 6, "text": "John", "parent": 1, "unit": "hours/day" }, { "id": 7, "text": "Mike", "parent": 2, "unit": "hours/day" }, { "id": 8, "text": "Anna", "parent": 2, "unit": "hours/day" }, { "id": 9, "text": "Bill", "parent": 3, "unit": "hours/day" }, { "id": 10, "text": "Floe", "parent": 3, "unit": "hours/day" } ] }); </script> </body> </html>