forked from github/plane
fix: cycle stats empty state (#1338)
* chore: active cycle percentage fix * fix: progress chart x-axis values
This commit is contained in:
parent
9c85704be3
commit
d3c56c1765
@ -3,7 +3,7 @@ import React from "react";
|
||||
// ui
|
||||
import { LineGraph } from "components/ui";
|
||||
// helpers
|
||||
import { renderShortNumericDateFormat } from "helpers/date-time.helper";
|
||||
import { getDatesInRange, renderShortNumericDateFormat } from "helpers/date-time.helper";
|
||||
//types
|
||||
import { TCompletionChartDistribution } from "types";
|
||||
|
||||
@ -46,6 +46,27 @@ const ProgressChart: React.FC<Props> = ({ distribution, startDate, endDate, tota
|
||||
pending: distribution[key],
|
||||
}));
|
||||
|
||||
const generateXAxisTickValues = () => {
|
||||
const dates = getDatesInRange(startDate, endDate);
|
||||
|
||||
const maxDates = 4;
|
||||
const totalDates = dates.length;
|
||||
|
||||
if (totalDates <= maxDates) return dates;
|
||||
else {
|
||||
const interval = Math.ceil(totalDates / maxDates);
|
||||
const limitedDates = [];
|
||||
|
||||
for (let i = 0; i < totalDates; i += interval)
|
||||
limitedDates.push(renderShortNumericDateFormat(dates[i]));
|
||||
|
||||
if (!limitedDates.includes(renderShortNumericDateFormat(dates[totalDates - 1])))
|
||||
limitedDates.push(renderShortNumericDateFormat(dates[totalDates - 1]));
|
||||
|
||||
return limitedDates;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full flex justify-center items-center">
|
||||
<LineGraph
|
||||
@ -86,7 +107,7 @@ const ProgressChart: React.FC<Props> = ({ distribution, startDate, endDate, tota
|
||||
]}
|
||||
layers={["grid", "markers", "areas", DashedLine, "slices", "points", "axes", "legends"]}
|
||||
axisBottom={{
|
||||
tickValues: chartData.map((item, index) => (index % 2 === 0 ? item.currentDate : "")),
|
||||
tickValues: generateXAxisTickValues(),
|
||||
}}
|
||||
enablePoints={false}
|
||||
enableArea
|
||||
|
@ -395,6 +395,7 @@ export const ActiveCycleDetails: React.FC = () => {
|
||||
<div className="text-brand-primary">High Priority Issues</div>
|
||||
<div className="my-3 flex max-h-[240px] min-h-[240px] flex-col gap-2.5 overflow-y-scroll rounded-md">
|
||||
{issues ? (
|
||||
issues.length > 0 ? (
|
||||
issues.map((issue) => (
|
||||
<div
|
||||
key={issue.id}
|
||||
@ -421,7 +422,6 @@ export const ActiveCycleDetails: React.FC = () => {
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div
|
||||
className={`grid h-6 w-6 place-items-center items-center rounded border shadow-sm flex-shrink-0 ${
|
||||
@ -471,6 +471,11 @@ export const ActiveCycleDetails: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="grid place-items-center text-brand-secondary text-sm text-center">
|
||||
No issues present in the cycle.
|
||||
</div>
|
||||
)
|
||||
) : (
|
||||
<Loader className="space-y-3">
|
||||
<Loader.Item height="50px" />
|
||||
@ -481,6 +486,7 @@ export const ActiveCycleDetails: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{issues && issues.length > 0 && (
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<div className="h-1 w-full rounded-full bg-brand-surface-2">
|
||||
<div
|
||||
@ -502,6 +508,7 @@ export const ActiveCycleDetails: React.FC = () => {
|
||||
{issues?.length}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col justify-between border-brand-base p-4">
|
||||
<div className="flex items-start justify-between gap-4 py-1.5 text-xs">
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { Fragment } from "react";
|
||||
|
||||
// headless ui
|
||||
import { Tab } from "@headlessui/react";
|
||||
@ -32,6 +32,7 @@ export const ActiveCycleProgressStats: React.FC<Props> = ({ cycle }) => {
|
||||
|
||||
return (
|
||||
<Tab.Group
|
||||
as={Fragment}
|
||||
defaultIndex={currentValue(tab)}
|
||||
onChange={(i) => {
|
||||
switch (i) {
|
||||
@ -68,10 +69,11 @@ export const ActiveCycleProgressStats: React.FC<Props> = ({ cycle }) => {
|
||||
Labels
|
||||
</Tab>
|
||||
</Tab.List>
|
||||
<Tab.Panels className="flex w-full px-4 pb-4">
|
||||
{cycle.total_issues > 0 ? (
|
||||
<Tab.Panels as={Fragment}>
|
||||
<Tab.Panel
|
||||
as="div"
|
||||
className="flex flex-col w-full mt-2 gap-1 overflow-y-scroll items-center text-brand-secondary"
|
||||
className="w-full gap-1 overflow-y-scroll items-center text-brand-secondary p-4"
|
||||
>
|
||||
{cycle.distribution.assignees.map((assignee, index) => {
|
||||
if (assignee.assignee_id)
|
||||
@ -121,7 +123,7 @@ export const ActiveCycleProgressStats: React.FC<Props> = ({ cycle }) => {
|
||||
</Tab.Panel>
|
||||
<Tab.Panel
|
||||
as="div"
|
||||
className="flex flex-col w-full mt-2 gap-1 overflow-y-scroll items-center text-brand-secondary"
|
||||
className="w-full gap-1 overflow-y-scroll items-center text-brand-secondary p-4"
|
||||
>
|
||||
{cycle.distribution.labels.map((label, index) => (
|
||||
<SingleProgressStats
|
||||
@ -143,6 +145,11 @@ export const ActiveCycleProgressStats: React.FC<Props> = ({ cycle }) => {
|
||||
))}
|
||||
</Tab.Panel>
|
||||
</Tab.Panels>
|
||||
) : (
|
||||
<div className="grid place-items-center text-brand-secondary text-sm text-center mt-4">
|
||||
No issues present in the cycle.
|
||||
</div>
|
||||
)}
|
||||
</Tab.Group>
|
||||
);
|
||||
};
|
||||
|
@ -282,12 +282,18 @@ export const SingleCycleList: React.FC<TSingleStatProps> = ({
|
||||
>
|
||||
{cycleStatus === "current" ? (
|
||||
<span className="flex gap-1">
|
||||
{cycle.total_issues > 0 ? (
|
||||
<>
|
||||
<RadialProgressBar
|
||||
progress={(cycle.completed_issues / cycle.total_issues) * 100}
|
||||
/>
|
||||
<span>
|
||||
{Math.floor((cycle.completed_issues / cycle.total_issues) * 100)} %
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span className="normal-case">No issues present</span>
|
||||
)}
|
||||
</span>
|
||||
) : cycleStatus === "upcoming" ? (
|
||||
<span className="flex gap-1">
|
||||
|
@ -25,13 +25,18 @@ export const findHowManyDaysLeft = (date: string | Date) => {
|
||||
return Math.ceil(timeDiff / (1000 * 3600 * 24));
|
||||
};
|
||||
|
||||
export const getDatesInRange = (startDate: Date, endDate: Date) => {
|
||||
export const getDatesInRange = (startDate: string | Date, endDate: string | Date) => {
|
||||
startDate = new Date(startDate);
|
||||
endDate = new Date(endDate);
|
||||
|
||||
const date = new Date(startDate.getTime());
|
||||
const dates = [];
|
||||
|
||||
while (date <= endDate) {
|
||||
dates.push(new Date(date));
|
||||
date.setDate(date.getDate() + 1);
|
||||
}
|
||||
|
||||
return dates;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user