diff --git a/packages/frontend/src/scripts/components/inputs/DateInput.tsx b/packages/frontend/src/scripts/components/inputs/DateInput.tsx
index 32f0b8a8..786d1df9 100644
--- a/packages/frontend/src/scripts/components/inputs/DateInput.tsx
+++ b/packages/frontend/src/scripts/components/inputs/DateInput.tsx
@@ -13,7 +13,8 @@ export const DateInput = (props: {class?: string, label: string, change?: (value
const required = props.required
function onChange(event: React.ChangeEvent
diff --git a/packages/frontend/src/scripts/components/views/ProductMilestone.tsx b/packages/frontend/src/scripts/components/views/ProductMilestone.tsx
index dcf3f921..5e54f041 100644
--- a/packages/frontend/src/scripts/components/views/ProductMilestone.tsx
+++ b/packages/frontend/src/scripts/components/views/ProductMilestone.tsx
@@ -10,7 +10,7 @@ import { UserContext } from '../../contexts/User'
import { useProduct } from '../../hooks/entity'
import { useAsyncHistory } from '../../hooks/history'
import { useMilestones, useMembers } from '../../hooks/list'
-import { formatDateTime } from '../../functions/time'
+import { formatDateHourMinute } from '../../functions/time'
import { LegalFooter } from '../snippets/LegalFooter'
import { ProductFooter, ProductFooterItem } from '../snippets/ProductFooter'
import { MilestoneProgressWidget } from '../widgets/MilestoneProgress'
@@ -67,12 +67,12 @@ export const ProductMilestoneView = () => {
) },
{ label: 'Start', class: 'nowrap center', content: milestone => (
- {formatDateTime(new Date(milestone.start))}
+ {formatDateHourMinute(new Date(milestone.start))}
) },
{ label: 'End', class: 'nowrap center', content: milestone => (
- {formatDateTime(new Date(milestone.end))}
+ {formatDateHourMinute(new Date(milestone.end))}
) },
{ label: 'Open', class: 'center', content: milestone => (
diff --git a/packages/frontend/src/scripts/components/views/ProductMilestoneIssue.tsx b/packages/frontend/src/scripts/components/views/ProductMilestoneIssue.tsx
index 0d649809..ff85ff5e 100644
--- a/packages/frontend/src/scripts/components/views/ProductMilestoneIssue.tsx
+++ b/packages/frontend/src/scripts/components/views/ProductMilestoneIssue.tsx
@@ -12,7 +12,7 @@ import { useAsyncHistory } from '../../hooks/history'
import { useMembers, useIssues } from '../../hooks/list'
import { useIssuesComments } from '../../hooks/map'
import { calculateActual } from '../../functions/burndown'
-import { formatDateTime } from '../../functions/time'
+import { formatDateHourMinute } from '../../functions/time'
import { PartCount } from '../counts/Parts'
import { LegalFooter } from '../snippets/LegalFooter'
import { ProductFooter, ProductFooterItem } from '../snippets/ProductFooter'
@@ -200,16 +200,16 @@ export const ProductMilestoneIssueView = () => {
This milestone starts on - {formatDateTime(new Date(milestone.start))} + {formatDateHourMinute(new Date(milestone.start))} and ends on - {formatDateTime(new Date(milestone.end))} + {formatDateHourMinute(new Date(milestone.end))}
{contextUser ? ( diff --git a/packages/frontend/src/scripts/components/widgets/BurndownChart.tsx b/packages/frontend/src/scripts/components/widgets/BurndownChart.tsx index 735509fd..252b1b5d 100644 --- a/packages/frontend/src/scripts/components/widgets/BurndownChart.tsx +++ b/packages/frontend/src/scripts/components/widgets/BurndownChart.tsx @@ -3,27 +3,127 @@ import { useState } from 'react' import { CartesianGrid, Legend, Line, LineChart, ReferenceLine, ResponsiveContainer, XAxis, YAxis } from 'recharts' -/* +import { formatDate, formatDateHour, formatDateHourMinute, formatMonth } from '../../functions/time' + +function monthTickFormatter(time: number) { + return formatMonth(new Date(time)) +} + function dateTickFormatter(time: number) { return formatDate(new Date(time)) } -function dateTimeTickFormatter(time: number) { - return formatDateTime(new Date(time)) +function dateHourTickFormatter(time: number) { + return formatDateHour(new Date(time)) +} + +function dateHourMinuteTickFormatter(time: number) { + return formatDateHourMinute(new Date(time)) } -*/ export const BurndownChartWidget = (props: { start: number, end: number, total: number, actual: { time: number, actual: number }[] }) => { // CONSTANTS - const start = props.start - const end = props.end + let start = props.start + let end = props.end + + const span = end - start const now = Date.now() + + const startDate = new Date(start) + const endDate = new Date(end) + + let step: number + + if (span <= 1000 * 60 * 60) { + + step = 1000 * 60 + + startDate.setMinutes(startDate.getMinutes(), 0, 0) + start = startDate.getTime() + + endDate.setMinutes(endDate.getMinutes() + 1, 0, 0) + end = endDate.getTime() + + } else if (span <= 1000 * 60 * 60 * 24) { + + step = 1000 * 60 * 60 + + startDate.setHours(startDate.getHours(), 0, 0, 0) + start = startDate.getTime() + + endDate.setHours(endDate.getHours() + 1, 0, 0, 0) + end = endDate.getTime() + + } else if (span <= 1000 * 60 * 60 * 24 * 48) { + + step = 1000 * 60 * 60 * 24 + + startDate.setDate(startDate.getDate()) + startDate.setHours(0, 0, 0, 0) + start = startDate.getTime() + + endDate.setDate(endDate.getDate() + 1) + endDate.setHours(0, 0, 0, 0) + end = endDate.getTime() + + } else { + + startDate.setMonth(startDate.getMonth(), 2) + startDate.setHours(0, 0, 0, 0) + start = startDate.getTime() + + endDate.setMonth(endDate.getMonth() + 1, 2) + endDate.setHours(0, 0, 0, 0) + end = endDate.getTime() + + } + const total = props.total const actual = props.actual const padding = 50 + const domain = [start, end] + + const ticks = [] + if (step) { + for (let i = start; i <= end; i += step) { + ticks.push(i) + } + } else { + while (startDate <= endDate) { + ticks.push(startDate.getTime()) + startDate.setMonth(startDate.getMonth() + 1) + } + } + + let tickFormatter: (timestamp: number) => string + if (step) { + if (step <= 1000 * 60) { + tickFormatter = dateHourMinuteTickFormatter + } else if (step <= 1000 * 60 * 60) { + tickFormatter = dateHourTickFormatter + } else { + tickFormatter = dateTickFormatter + } + } else { + tickFormatter = monthTickFormatter + } + + let height: number + if (step) { + if (step <= 1000 * 60) { + height = 150 + } else if (step <= 1000 * 60 * 60) { + height = 130 + } else { + height = 90 + } + } else { + height = 70 + } + // INITIAL STATES const initialTarget = [{ time: start, target: total }, { time: end, target: 0 }] @@ -35,8 +135,8 @@ export const BurndownChartWidget = (props: { start: number, end: number, total: // EFFECTS React.useEffect(() => { - setTarget([{ time: start, target: total }, { time: end, target: 0 }]) - }, [start, end, total]) + setTarget([{ time: props.start, target: total }, { time: props.end, target: 0 }]) + }, [props.start, props.end, total]) // RETURN @@ -45,14 +145,14 @@ export const BurndownChartWidget = (props: { start: number, end: number, total:
{comment ? (
<>
-