Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
components.gantt.Schedule.js Maven / Gradle / Ivy
import { Helmet } from 'react-helmet';
import { useTranslation } from 'react-i18next';
import { useConfig } from 'hooks/config';
import { MomentSvelteGanttDateAdapter, SvelteGantt, SvelteGanttDependencies, SvelteGanttTable } from 'svelte-gantt';
import { useEffect, useRef, useState } from 'react';
import { Box } from '@mui/material';
import 'moment/locale/nl'; // required to load the dutch language for moment
import GanttDrawer from 'components/gantt/Settings';
import { mformat } from './utils/date';
import { createConfig, getResourceUsage, createSvelteResources, createSvelteTasks, handleSvelteData } from 'components/gantt/common';
import { useParams } from 'react-router';
import { GET_LIST_DATA, GET_LIST_WITH_SCHEMA } from 'queries/list';
import { useQuery } from '@apollo/client';
import { useNotifier } from 'hooks/notification';
import { NotFound } from 'pages';
import LambdaComponent from 'components/common/LambdaComponent';
import CenteredLoader from 'components/common/CenteredLoader';
import moment from 'moment-business-days';
import SidebarLayout from 'components/layout/common/SidebarLayout';
const Schedule = () => {
const { t } = useTranslation()
const { project } = useConfig()
const { resourceKey, taskKey } = useParams()
// TODO: set holidays:
//var july4th = '2015-07-04';
//var laborDay = '2015-09-07';
//var boxingDay = '2020-12-26';
//moment.updateLocale('us', {
// holidays: [ july4th, laborDay ],
// holidayFormat: 'YYYY-MM-DD',
// forcedBusinessDays: [ boxingDay ],
// forcedBusinessDaysFormat: 'YYYY-MM-DD',
// workingWeekdays: [1, 2, 3, 4, 5, 6] // Defines days from 1 (Monday) to 6 (Saturday) as business days. Note that Sunday is day 0.
//});'
const momentConfig = {
nextBusinessDayLimit: 365
}
moment.updateLocale('en', momentConfig)
moment.updateLocale('nl', momentConfig)
console.log("Creating gantt chart with:\nresources: %o\ntasks : %o",
resourceKey || 'planningresources',
taskKey || 'productionplanning'
)
return (
<>
{t('schedule')} | {project}
>
)
}
const GanttDataProvider = ({children}) => {
const { resourceKey, taskKey } = useParams()
const notifier = useNotifier()
const resourceRequest = createRequest(resourceKey || 'planningresources' )
const taskRequest = createRequest(taskKey || 'productionplanning')
const resourceResult = useQuery(GET_LIST_WITH_SCHEMA, resourceRequest)
const taskResult = useQuery(GET_LIST_WITH_SCHEMA, taskRequest)
const [loading, setLoading] = useState(true)
const [error, setError] = useState(false)
const [resources, setResources] = useState()
const [tasks, setTasks] = useState()
const ops = {setError, setLoading, notifier, setResources, setTasks}
// create rows
useEffect(() => {
handleSvelteData({
result: resourceResult,
createRows: createSvelteResources,
setData: setResources,
ops
})
}, [resourceResult.loading])
// create tasks
useEffect(() => {
if (resources != null) {
handleSvelteData({
result: taskResult,
createRows: (schema, rows) => createSvelteTasks(schema, rows, resources),
setData: setTasks,
ops
})
}
}, [taskResult.loading, resources])
useEffect(() => {
if (resources && tasks)
setLoading(false)
}, [resources, tasks])
if (loading) {
return
} else if (error) {
return
} else {
return (
{children}
)
}
}
const GanttSchedule = ({resources, tasks}) => {
const config = useRef(createConfig(resources, tasks))
return (
}
sidebarProps={{
shortcut: "BracketRight",
enabled: {
collapsed: false
}
}}
>
)
}
const GanttComponent = ({config}) => {
const { t } = useTranslation()
const timeRanges = [
{
id: 0,
from: moment().startOf('day'),
to: moment().endOf('day'),
classes: null,
label: t("gantt.today"),
},
];
config.current.options = {
from: config.current.from,
to: config.current.to,
rows: config.current.rows,
tasks: config.current.tasks,
...config.current.createWindowConfig(),
dateAdapter: new MomentSvelteGanttDateAdapter(moment),
timeRanges,
zoomLevels: [],
rowHeight: 30,
rowPadding: 6,
minWidth: 800,
tableHeaders: [{ title: t('gantt.resource'), property: 'label', width: 140, type: 'tree' }],
tableWidth: 245,
reflectOnParentRows: true,
ganttTableModules: [SvelteGanttTable],
ganttBodyModules: [SvelteGanttDependencies],
taskElementHook: (node, task) => {
let popup;
function onHover(e) {
popup = createPopup(task, config.current.resources, node, t);
}
function onLeave(e) {
if(popup) {
popup.remove();
}
}
node.addEventListener('mouseenter', onHover);
node.addEventListener('mouseleave', onLeave);
return {
destroy() {
node.removeEventListener('mouseenter', onHover);
node.removeEventListener('mouseleave', onLeave);
}
}
},
taskContent: (task) => {
if (task.gears?.type == "capacity" && task.gears.overcapacity > 0)
return JSON.stringify(task.gears.demand)
else
return ''
}
}
// useEffect to load Gantt
useEffect(() => {
if (!config.current.gantt) {
// Create Gantt
const ganttInstance = new SvelteGantt({ target: document.getElementById('example-gantt'), props: config.current.options })
// try out some event handlers
// ganttInstance.api.tasks.on.select((task) => console.log('Listener: task selected', task));
// ganttInstance.api.tasks.on.changed((task) => console.log('Listener: task changed', task));
config.current.gantt = ganttInstance
}
}, [])
return (
<>
{/* GANTT CONTAINER */}
>
)
};
function createPopup(task, resources, node, t) {
const rect = node.getBoundingClientRect();
const div = document.createElement('div');
div.zIndex = "10"
div.style = "z-index:1;background-color:white;padding:10px; border-radius:5px;box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);"
div.className = 'sg-popup';
const getResource = (task) => resources.find(resource => resource.id == task.gears.resourceId)
const resource = getResource(task)
const space = (repeat) => " ".repeat(repeat)
const createKeyValueRow = (key, value) => {
return `
${key}
:${space(2)}
${value}
`
}
const createListTable = (entries, columnGetters = [(entry) => entry]) => {
const createTableRow = (body) => `${body} `
const createTableCols = (entry, getters) => getters.map(getter => `${getter(entry)} `).join("\n")
const createEntryRows = () => entries.map(entry => createTableRow(createTableCols(entry, columnGetters))).join("\n")
if (Array.isArray(entries) && entries.length) {
if (!Array.isArray(columnGetters))
return createListTable(entries, [columnGetters])
else {
return `
`
}
}
else return ''
}
const createCapacityHtml = (task) => {
const addStatusTasks = (label, task, taskGetter) =>
createKeyValueRow(label, createListTable(taskGetter(task), (task) => task.label))
const addResourceTasks = (label, task, taskGetter) =>
createKeyValueRow(label, createListTable(taskGetter(task), [(task) => `(${getResourceUsage(task)})`, (task) => space(1), (task) => task.label]))
const statusHtml = (status) => {
const createBorder = (color, content) => `
${t(`gantt.status-${content}`)}
`
switch(status) {
case "high": return createBorder("#ff0000", status)
case "full": return createBorder("rgba(255, 140, 0)", status)
case "low": return createBorder("#3CB043", status)
default: return status
}
}
return `
${createKeyValueRow(t("gantt.status"), statusHtml(task.gears.state))}
${createKeyValueRow(t("gantt.week"), task.from.isoWeek())}
${createKeyValueRow(t("gantt.capacity"), task.gears.capacity)}
${createKeyValueRow(t("gantt.required"), `${task.gears.demand} (${task.gears.overcapacity})`)}
${addStatusTasks(t("gantt.running"), task, (task) => task.gears.running)}
${addResourceTasks(t("gantt.backlog"), task, (task) => task.gears.planned)}
${addStatusTasks(t("gantt.finished"), task, (task) => task.gears.finished)}
`
}
const createTaskHtml = (task) => {
const conflictLine = task.gears.conflicts
? createKeyValueRow("Conflict", createListTable(Array.from(task.gears.conflicts, task => `${task.label} ${t('gantt.withresource')} ${getResource(task).label}`)))
: ``
const hoursPerWeek = resource.gears.capacity // in hours
const hoursPerDay = hoursPerWeek/5 // per working day
const roundToTwo = (num) => +(Math.round(num + "e+2") + "e-2")
const dayMaximum = roundToTwo(hoursPerDay)
return `
${createKeyValueRow(t("gantt.task"), task.label)}
${createKeyValueRow(t("gantt.name"), task.gears.name)}
${createKeyValueRow(t("gantt.client"), task.gears.client)}
${createKeyValueRow(t("gantt.drawingnumber"), task.gears.drawingNumber)}
${createKeyValueRow(t("gantt.required"), task.gears.hours)}
${createKeyValueRow(t("gantt.daymax"), dayMaximum)}
${createKeyValueRow(t("gantt.duration"), t('gantt.taskduration', {days: task.gears.duration.days, hours: task.gears.duration.hours, minutes: task.gears.duration.minutes}))}
${createKeyValueRow(t("gantt.from"), mformat(task.from))}
${createKeyValueRow(t("gantt.to"), mformat(task.to))}
${createKeyValueRow(t("gantt.resource"), resource.label)}
${conflictLine}
`
}
div.innerHTML = task.gears.type == "capacity" ? createCapacityHtml(task) : createTaskHtml(task)
div.style.position = 'absolute';
div.style.top = `${rect.bottom}px`;
div.style.left = `${rect.left + rect.width / 2}px`;
document.body.appendChild(div);
return div;
}
const createRequest = (key) => ({
variables: { key, filter: null, count: 999999, start: 0 },
query: GET_LIST_DATA,
path: 'list.data',
countPath: 'list.count'
})
export default Schedule;