mirror of
https://github.com/makeplane/plane.git
synced 2026-07-12 13:29:56 +02:00
fix: cycle build issue (#1509)
* fix: cycle build issue * fix: removed beyond time * fix: today value + chart stacking
This commit is contained in:
@@ -277,7 +277,7 @@ export class CycleStore implements ICycleStore {
|
||||
getIsPointsDataAvailable = computedFn((cycleId: string) => {
|
||||
const cycle = this.cycleMap[cycleId];
|
||||
if (!cycle) return false;
|
||||
if (this.cycleMap[cycleId].version === 2) return cycle.progress.some((p) => p.total_estimate_points > 0);
|
||||
if (this.cycleMap[cycleId].version === 2) return cycle.progress?.some((p) => p.total_estimate_points > 0);
|
||||
else if (this.cycleMap[cycleId].version === 1) {
|
||||
const completionChart = cycle.estimate_distribution?.completion_chart || {};
|
||||
return !isEmpty(completionChart) && Object.keys(completionChart).some((p) => completionChart[p]! > 0);
|
||||
|
||||
@@ -31,10 +31,19 @@ type Props = {
|
||||
isFullWidth?: boolean;
|
||||
estimateType?: string;
|
||||
plotType: string;
|
||||
showToday?: boolean;
|
||||
};
|
||||
|
||||
export const ActiveCycleChart = observer((props: Props) => {
|
||||
const { areaToHighlight, data = [], cycle, isFullWidth = false, plotType, estimateType = "ISSUES" } = props;
|
||||
const {
|
||||
areaToHighlight,
|
||||
data = [],
|
||||
cycle,
|
||||
isFullWidth = false,
|
||||
plotType,
|
||||
estimateType = "ISSUES",
|
||||
showToday,
|
||||
} = props;
|
||||
|
||||
const { resolvedTheme } = useTheme();
|
||||
const colors = getColors(resolvedTheme);
|
||||
@@ -53,7 +62,7 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
data={dataWithRange}
|
||||
margin={{
|
||||
top: isFullWidth ? 10 : 30,
|
||||
right: isFullWidth ? 10 : 0,
|
||||
right: isFullWidth ? 10 : 20,
|
||||
bottom: isFullWidth ? 30 : 70,
|
||||
left: isFullWidth ? -30 : 20,
|
||||
}}
|
||||
@@ -126,10 +135,12 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
stroke={colors.axisLines}
|
||||
text={colors.axisText}
|
||||
startDate={startDate}
|
||||
showToday={showToday}
|
||||
/>
|
||||
}
|
||||
tickLine={false}
|
||||
interval={0}
|
||||
minTickGap={5}
|
||||
/>
|
||||
<YAxis
|
||||
tickCount={10}
|
||||
@@ -165,8 +176,9 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
fillOpacity={0.5}
|
||||
/>
|
||||
|
||||
{/* Required when manual cycles are implemented */}
|
||||
{/* Beyond Time */}
|
||||
<Area dataKey="beyondTime" stroke="#FF9999" strokeWidth={0} fill={`url(#fillTimeBeyond)`} />
|
||||
{/* <Area dataKey="beyondTime" stroke="#FF9999" strokeWidth={0} fill={`url(#fillTimeBeyond)`} />
|
||||
<ReferenceArea
|
||||
x1={endDate}
|
||||
x2={dataWithRange[dataWithRange.length - 1]?.date}
|
||||
@@ -183,7 +195,7 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
position="middle"
|
||||
/>
|
||||
)}
|
||||
</ReferenceArea>
|
||||
</ReferenceArea> */}
|
||||
|
||||
{/* Today */}
|
||||
{today < endDate && (
|
||||
@@ -191,8 +203,38 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
)}
|
||||
{/* Beyond Time */}
|
||||
<ReferenceLine x={endDate} stroke={colors.beyondTimeStroke} label="" strokeDasharray="3 3" />
|
||||
{/* Ideal - Actual */}
|
||||
<Area dataKey="range" strokeWidth={0} fill={`url(#diff)`} isAnimationActive={false} />
|
||||
|
||||
{/* Ideal */}
|
||||
<Line
|
||||
type="linear"
|
||||
dataKey="ideal"
|
||||
strokeWidth={1}
|
||||
stroke={colors.idealStroke}
|
||||
dot={false}
|
||||
strokeDasharray="5 5"
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
{areaToHighlight === "ideal" && (
|
||||
<Area
|
||||
dataKey="ideal"
|
||||
fill="url(#fillIdeal)"
|
||||
fillOpacity={0.4}
|
||||
stroke={colors.idealStroke}
|
||||
strokeWidth={0}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
)}
|
||||
{/* Started */}
|
||||
<Line type="linear" dataKey="started" strokeWidth={1} stroke={colors.startedStroke} dot={false} />
|
||||
<Line
|
||||
type="linear"
|
||||
dataKey="started"
|
||||
strokeWidth={2}
|
||||
stroke={colors.startedStroke}
|
||||
dot={false}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
{areaToHighlight === "started" && (
|
||||
<Area
|
||||
dataKey="started"
|
||||
@@ -222,26 +264,7 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
)}
|
||||
{/* Ideal */}
|
||||
<Line
|
||||
type="linear"
|
||||
dataKey="ideal"
|
||||
strokeWidth={1}
|
||||
stroke={colors.idealStroke}
|
||||
dot={false}
|
||||
strokeDasharray="5 5"
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
{areaToHighlight === "ideal" && (
|
||||
<Area
|
||||
dataKey="ideal"
|
||||
fill="url(#fillIdeal)"
|
||||
fillOpacity={0.4}
|
||||
stroke={colors.idealStroke}
|
||||
strokeWidth={0}
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Scope */}
|
||||
<Line
|
||||
type="stepAfter"
|
||||
@@ -267,8 +290,6 @@ export const ActiveCycleChart = observer((props: Props) => {
|
||||
isAnimationActive={false}
|
||||
/>
|
||||
)}
|
||||
{/* Ideal - Actual */}
|
||||
<Area dataKey="range" strokeWidth={0} fill={`url(#diff)`} isAnimationActive={false} />
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
);
|
||||
|
||||
@@ -10,9 +10,10 @@ type TProps = {
|
||||
endDate?: string;
|
||||
stroke?: string;
|
||||
text?: string;
|
||||
showToday?: boolean;
|
||||
};
|
||||
const CustomizedXAxisTicks = (props: TProps) => {
|
||||
const { x, y, payload, data, endDate, startDate, stroke, text } = props;
|
||||
const { x, y, payload, data, endDate, startDate, stroke, text, showToday } = props;
|
||||
if (data === undefined || endDate === undefined) return null;
|
||||
const [year, month, day] = payload.value.split("-");
|
||||
const monthName = new Date(payload.value).toLocaleString("default", { month: "short" });
|
||||
@@ -25,7 +26,7 @@ const CustomizedXAxisTicks = (props: TProps) => {
|
||||
<>
|
||||
<line x1={"0"} y1="-8" x2="0" y2="0" stroke={stroke} stroke-width="1" />
|
||||
<text
|
||||
x={day === "01" || payload.index === 0 ? "-10" : "-5"}
|
||||
x={day === "01" || payload.index === 0 ? "-10" : payload.value === endDate ? "5" : "-5"}
|
||||
y={0}
|
||||
dy={12}
|
||||
textAnchor={payload.index === data.length - 1 ? "end" : "start"}
|
||||
@@ -37,7 +38,7 @@ const CustomizedXAxisTicks = (props: TProps) => {
|
||||
</text>
|
||||
{(payload.value === startDate || payload.value === endDate) && (
|
||||
<text
|
||||
x={-8}
|
||||
x={payload.value === endDate ? "10" : "-8"}
|
||||
y={12}
|
||||
dy={16}
|
||||
textAnchor={payload.index === data.length - 1 ? "end" : "start"}
|
||||
@@ -52,7 +53,7 @@ const CustomizedXAxisTicks = (props: TProps) => {
|
||||
{payload.value === format(startOfToday(), "yyyy-MM-dd") && payload.value < endDate && (
|
||||
<>
|
||||
<line x1="0" y1="-8" x2="0" y2="0" stroke={stroke} stroke-width="1" />
|
||||
<text x={0} y={0} dy={12} textAnchor={"middle"} fill={text} style={{ fontSize: "10px" }}>
|
||||
<text x={0} y={0} dy={12} textAnchor={"middle"} fill={text} style={{ fontSize: "10px", fontWeight: 500 }}>
|
||||
{day}
|
||||
</text>
|
||||
{(payload.value === startDate || payload.value === endDate) && (
|
||||
@@ -67,19 +68,21 @@ const CustomizedXAxisTicks = (props: TProps) => {
|
||||
{payload.value === startDate ? "Start" : "End"}
|
||||
</text>
|
||||
)}
|
||||
<svg
|
||||
x={-17}
|
||||
y={payload.value === startDate || payload.value === endDate ? 30 : 18}
|
||||
dy={payload.value === startDate || payload.value === endDate ? 30 : 18}
|
||||
width="34"
|
||||
height="16px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect rx="2" width="100%" height="100%" fill="#667699" />
|
||||
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" fill="white" font-size="10px">
|
||||
Today
|
||||
</text>
|
||||
</svg>
|
||||
{showToday && (
|
||||
<svg
|
||||
x={-17}
|
||||
y={payload.value === startDate || payload.value === endDate ? 30 : 18}
|
||||
dy={payload.value === startDate || payload.value === endDate ? 30 : 18}
|
||||
width="34"
|
||||
height="16px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect rx="2" width="100%" height="100%" fill="#667699" />
|
||||
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" fill="white" font-size="10px">
|
||||
Today
|
||||
</text>
|
||||
</svg>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</g>
|
||||
|
||||
@@ -87,6 +87,7 @@ const ActiveCycleDetail = observer((props: ActiveCycleDetailProps) => {
|
||||
isFullWidth={containerWidth < 890}
|
||||
estimateType={computedEstimateType}
|
||||
plotType={computedPlotType}
|
||||
showToday
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -13,7 +13,9 @@ const ideal = (date: string, scope: number, cycle: ICycle) => {
|
||||
const formatV1Data = (isTypeIssue: boolean, cycle: ICycle, isBurnDown: boolean, endDate: Date | string) => {
|
||||
const today = format(startOfToday(), "yyyy-MM-dd");
|
||||
const data = isTypeIssue ? cycle.distribution : cycle.estimate_distribution;
|
||||
const extendedArray = generateDateArray(endDate, endDate).map((d) => d.date);
|
||||
const extendedArray = generateDateArray(endDate, endDate)
|
||||
.filter((d) => d.date >= cycle.start_date! && d.date <= cycle.end_date!)
|
||||
.map((d) => d.date);
|
||||
if (!data?.completion_chart) return null;
|
||||
if (isEmpty(data?.completion_chart)) return generateDateArray(new Date(cycle.start_date!), endDate);
|
||||
let progress = [...Object.keys(data.completion_chart), ...extendedArray].map((p) => {
|
||||
@@ -23,7 +25,7 @@ const formatV1Data = (isTypeIssue: boolean, cycle: ICycle, isBurnDown: boolean,
|
||||
const idealDone = ideal(p, total, cycle);
|
||||
return {
|
||||
date: p,
|
||||
scope: p! <= format(endDate as Date, "yyyy-MM-dd") ? total : null,
|
||||
scope: p! <= cycle.end_date! ? total : null,
|
||||
completed,
|
||||
backlog: isTypeIssue ? cycle.backlog_issues : cycle.backlog_estimate_points,
|
||||
started: p === today ? cycle[isTypeIssue ? "started_issues" : "started_estimate_points"] : undefined,
|
||||
@@ -42,7 +44,11 @@ const formatV1Data = (isTypeIssue: boolean, cycle: ICycle, isBurnDown: boolean,
|
||||
const formatV2Data = (isTypeIssue: boolean, cycle: ICycle, isBurnDown: boolean, endDate: Date | string) => {
|
||||
let today: Date | string = startOfToday();
|
||||
const extendedArray =
|
||||
endDate > today ? generateDateArray(today as Date, endDate).filter((d) => d.date >= cycle.start_date!) : [];
|
||||
endDate > today
|
||||
? generateDateArray(today as Date, endDate).filter(
|
||||
(d) => d.date >= cycle.start_date! && d.date <= cycle.end_date!
|
||||
)
|
||||
: [];
|
||||
if (!cycle?.progress) return null;
|
||||
if (isEmpty(cycle.progress)) return generateDateArray(new Date(cycle.start_date!), endDate);
|
||||
const startDate = cycle.start_date && format(new Date(cycle.start_date), "yyyy-MM-dd");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import { isEmpty } from "lodash";
|
||||
import { observer } from "mobx-react";
|
||||
// helpers
|
||||
import { TCycleEstimateType, TCyclePlotType } from "@plane/types";
|
||||
@@ -76,8 +75,8 @@ export const SidebarChart = observer((props: TProps) => {
|
||||
projectId={projectId}
|
||||
handlePlotChange={handlePlotChange}
|
||||
handleEstimateChange={handleEstimateChange}
|
||||
showEstimateSelection={!isEmpty(cycle.estimate_distribution)}
|
||||
className="!px-0 mt-0"
|
||||
cycleId={cycle.id}
|
||||
/>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<div className="flex items-center gap-1 text-xs">
|
||||
|
||||
Reference in New Issue
Block a user