fix: project states fixes (#2731)
* fix: project states fixes * fix: states fixes * fix: formating all files
This commit is contained in:
parent
bd1a850f35
commit
20fb79567f
156 changed files with 1585 additions and 1758 deletions
|
|
@ -32,8 +32,7 @@ export const GithubLoginButton: FC<GithubLoginButtonProps> = (props) => {
|
|||
}, [code, gitCode, handleSignIn]);
|
||||
|
||||
useEffect(() => {
|
||||
const origin =
|
||||
typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
|
||||
const origin = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
|
||||
setLoginCallBackURL(`${origin}/` as any);
|
||||
}, []);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,10 +49,7 @@ export const CustomTooltip: React.FC<Props> = ({ datum, analytics, params }) =>
|
|||
: ""
|
||||
}`}
|
||||
>
|
||||
{params.segment === "assignees__id"
|
||||
? renderAssigneeName(tooltipValue.toString())
|
||||
: tooltipValue}
|
||||
:
|
||||
{params.segment === "assignees__id" ? renderAssigneeName(tooltipValue.toString()) : tooltipValue}:
|
||||
</span>
|
||||
<span>{datum.value}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,9 +22,7 @@ export const AnalyticsScope: React.FC<Props> = ({ defaultAnalytics }) => (
|
|||
keys={["count"]}
|
||||
height="250px"
|
||||
colors={() => `#f97316`}
|
||||
customYAxisTickValues={defaultAnalytics.pending_issue_user.map((d) =>
|
||||
d.count > 0 ? d.count : 50
|
||||
)}
|
||||
customYAxisTickValues={defaultAnalytics.pending_issue_user.map((d) => (d.count > 0 ? d.count : 50))}
|
||||
tooltip={(datum) => {
|
||||
const assignee = defaultAnalytics.pending_issue_user.find(
|
||||
(a) => a.assignees__id === `${datum.indexValue}`
|
||||
|
|
|
|||
|
|
@ -31,9 +31,7 @@ export const NotAuthorizedView: React.FC<Props> = ({ actionButton, type }) => {
|
|||
alt="ProjectSettingImg"
|
||||
/>
|
||||
</div>
|
||||
<h1 className="text-xl font-medium text-custom-text-100">
|
||||
Oops! You are not authorized to view this page
|
||||
</h1>
|
||||
<h1 className="text-xl font-medium text-custom-text-100">Oops! You are not authorized to view this page</h1>
|
||||
|
||||
<div className="w-full max-w-md text-base text-custom-text-200">
|
||||
{user ? (
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@ import { SelectMonthModal } from "components/automation";
|
|||
import { CustomSelect, CustomSearchSelect, ToggleSwitch, StateGroupIcon, DoubleCircleIcon, Loader } from "@plane/ui";
|
||||
// icons
|
||||
import { ArchiveX } from "lucide-react";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// types
|
||||
import { IProject } from "types";
|
||||
// fetch keys
|
||||
|
|
@ -23,12 +21,12 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
|||
// states
|
||||
const [monthModal, setmonthModal] = useState(false);
|
||||
|
||||
const { user: userStore, project: projectStore } = useMobxStore();
|
||||
const { user: userStore, project: projectStore, projectState: projectStateStore } = useMobxStore();
|
||||
|
||||
const userRole = userStore.currentProjectRole;
|
||||
const projectDetails = projectStore.currentProjectDetails;
|
||||
const stateGroups = projectStore.projectStatesByGroups ?? undefined;
|
||||
const states = getStatesList(stateGroups);
|
||||
// const stateGroups = projectStateStore.groupedProjectStates ?? undefined;
|
||||
const states = projectStateStore.projectStates;
|
||||
|
||||
const options = states
|
||||
?.filter((state) => state.group === "cancelled")
|
||||
|
|
@ -45,7 +43,7 @@ export const AutoCloseAutomation: React.FC<Props> = observer((props) => {
|
|||
|
||||
const multipleOptions = (options ?? []).length > 1;
|
||||
|
||||
const defaultState = stateGroups && stateGroups.cancelled ? stateGroups.cancelled[0].id : null;
|
||||
const defaultState = states?.find((s) => s.group === "cancelled")?.id || null;
|
||||
|
||||
const selectedOption = states?.find((s) => s.id === projectDetails?.default_state ?? defaultState);
|
||||
const currentDefaultState = states?.find((s) => s.id === defaultState);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
import React, { Dispatch, SetStateAction, useCallback } from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR, { mutate } from "swr";
|
||||
|
||||
// cmdk
|
||||
import { Command } from "cmdk";
|
||||
// services
|
||||
|
|
@ -13,8 +10,6 @@ import { ProjectStateService } from "services/project";
|
|||
import { Spinner, StateGroupIcon } from "@plane/ui";
|
||||
// icons
|
||||
import { Check } from "lucide-react";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// types
|
||||
import { IUser, IIssue } from "types";
|
||||
// fetch keys
|
||||
|
|
@ -34,11 +29,10 @@ export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, use
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, issueId } = router.query;
|
||||
|
||||
const { data: stateGroups, mutate: mutateIssueDetails } = useSWR(
|
||||
const { data: states, mutate: mutateStates } = useSWR(
|
||||
workspaceSlug && projectId ? STATES_LIST(projectId as string) : null,
|
||||
workspaceSlug && projectId ? () => stateService.getStates(workspaceSlug as string, projectId as string) : null
|
||||
);
|
||||
const states = getStatesList(stateGroups);
|
||||
|
||||
const submitChanges = useCallback(
|
||||
async (formData: Partial<IIssue>) => {
|
||||
|
|
@ -60,14 +54,14 @@ export const ChangeIssueState: React.FC<Props> = ({ setIsPaletteOpen, issue, use
|
|||
await issueService
|
||||
.patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
|
||||
.then(() => {
|
||||
mutateIssueDetails();
|
||||
mutateStates();
|
||||
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
},
|
||||
[workspaceSlug, issueId, projectId, mutateIssueDetails, user]
|
||||
[workspaceSlug, issueId, projectId, mutateStates, user]
|
||||
);
|
||||
|
||||
const handleIssueState = (stateId: string) => {
|
||||
|
|
|
|||
|
|
@ -57,8 +57,7 @@ const ProgressChart: React.FC<Props> = ({ distribution, startDate, endDate, tota
|
|||
const interval = Math.ceil(totalDates / maxDates);
|
||||
const limitedDates = [];
|
||||
|
||||
for (let i = 0; i < totalDates; i += interval)
|
||||
limitedDates.push(renderShortNumericDateFormat(dates[i]));
|
||||
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]));
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
|
|||
</button>
|
||||
)}
|
||||
|
||||
<CustomMenu width="auto" ellipsis >
|
||||
<CustomMenu width="auto" ellipsis>
|
||||
{!isCompleted && (
|
||||
<>
|
||||
<CustomMenu.MenuItem onClick={handleEditCycle}>
|
||||
|
|
|
|||
|
|
@ -34,16 +34,8 @@ export const MonthChartView: FC<any> = () => {
|
|||
style={{ width: `${currentViewData?.data.width}px` }}
|
||||
>
|
||||
<div className="text-xs space-x-1">
|
||||
<span className="text-custom-text-200">
|
||||
{monthDay.dayData.shortTitle[0]}
|
||||
</span>{" "}
|
||||
<span
|
||||
className={
|
||||
monthDay.today
|
||||
? "bg-custom-primary-100 text-white px-1 rounded-full"
|
||||
: ""
|
||||
}
|
||||
>
|
||||
<span className="text-custom-text-200">{monthDay.dayData.shortTitle[0]}</span>{" "}
|
||||
<span className={monthDay.today ? "bg-custom-primary-100 text-white px-1 rounded-full" : ""}>
|
||||
{monthDay.day}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -63,9 +55,7 @@ export const MonthChartView: FC<any> = () => {
|
|||
>
|
||||
<div
|
||||
className={`relative h-full w-full flex-1 flex justify-center ${
|
||||
["sat", "sun"].includes(monthDay?.dayData?.shortTitle || "")
|
||||
? `bg-custom-background-90`
|
||||
: ``
|
||||
["sat", "sun"].includes(monthDay?.dayData?.shortTitle || "") ? `bg-custom-background-90` : ``
|
||||
}`}
|
||||
>
|
||||
{/* {monthDay?.today && (
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ export const months: WeekMonthDataType[] = [
|
|||
{ key: 11, shortTitle: "dec", title: "december" },
|
||||
];
|
||||
|
||||
export const charCapitalize = (word: string) =>
|
||||
`${word.charAt(0).toUpperCase()}${word.substring(1)}`;
|
||||
export const charCapitalize = (word: string) => `${word.charAt(0).toUpperCase()}${word.substring(1)}`;
|
||||
|
||||
export const bindZero = (value: number) => (value > 9 ? `${value}` : `0${value}`);
|
||||
|
||||
|
|
@ -50,9 +49,7 @@ export const datePreview = (date: Date, includeTime: boolean = false) => {
|
|||
month = months[month as number] as WeekMonthDataType;
|
||||
const year = date.getFullYear();
|
||||
|
||||
return `${charCapitalize(month?.shortTitle)} ${day}, ${year}${
|
||||
includeTime ? `, ${timePreview(date)}` : ``
|
||||
}`;
|
||||
return `${charCapitalize(month?.shortTitle)} ${day}, ${year}${includeTime ? `, ${timePreview(date)}` : ``}`;
|
||||
};
|
||||
|
||||
// context data
|
||||
|
|
@ -137,8 +134,6 @@ export const allViewsWithData: ChartDataType[] = [
|
|||
];
|
||||
|
||||
export const currentViewDataWithView = (view: string = "month") => {
|
||||
const currentView: ChartDataType | undefined = allViewsWithData.find(
|
||||
(_viewData) => _viewData.key === view
|
||||
);
|
||||
const currentView: ChartDataType | undefined = allViewsWithData.find((_viewData) => _viewData.key === view);
|
||||
return currentView;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,12 +3,7 @@ import { ChartDataType } from "../types";
|
|||
// data
|
||||
import { weeks, months } from "../data";
|
||||
// helpers
|
||||
import {
|
||||
generateDate,
|
||||
getWeekNumberByDate,
|
||||
getNumberOfDaysInMonth,
|
||||
getDatesBetweenTwoDates,
|
||||
} from "./helpers";
|
||||
import { generateDate, getWeekNumberByDate, getNumberOfDaysInMonth, getDatesBetweenTwoDates } from "./helpers";
|
||||
|
||||
type GetAllDaysInMonthInMonthViewType = {
|
||||
date: any;
|
||||
|
|
@ -34,9 +29,7 @@ const getAllDaysInMonthInMonthView = (month: number, year: number) => {
|
|||
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
|
||||
active: false,
|
||||
today:
|
||||
currentDate.getFullYear() === year &&
|
||||
currentDate.getMonth() === month &&
|
||||
currentDate.getDate() === _day + 1
|
||||
currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === _day + 1
|
||||
? true
|
||||
: false,
|
||||
});
|
||||
|
|
@ -72,16 +65,8 @@ export const generateBiWeekChart = (monthPayload: ChartDataType, side: null | "l
|
|||
if (side === null) {
|
||||
const currentDate = renderState.data.currentDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -96,16 +81,8 @@ export const generateBiWeekChart = (monthPayload: ChartDataType, side: null | "l
|
|||
} else if (side === "left") {
|
||||
const currentDate = renderState.data.startDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -116,16 +93,8 @@ export const generateBiWeekChart = (monthPayload: ChartDataType, side: null | "l
|
|||
} else if (side === "right") {
|
||||
const currentDate = renderState.data.endDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ export const getWeekNumberByDate = (date: Date) => {
|
|||
const firstWeekStart = firstDayOfYear.getTime() - daysOffset * 24 * 60 * 60 * 1000;
|
||||
const weekStart = new Date(firstWeekStart);
|
||||
|
||||
const weekNumber =
|
||||
Math.floor((date.getTime() - weekStart.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;
|
||||
const weekNumber = Math.floor((date.getTime() - weekStart.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;
|
||||
|
||||
return weekNumber;
|
||||
};
|
||||
|
|
@ -25,8 +24,7 @@ export const getNumberOfDaysInMonth = (month: number, year: number) => {
|
|||
return date.getDate();
|
||||
};
|
||||
|
||||
export const generateDate = (day: number, month: number, year: number) =>
|
||||
new Date(year, month, day);
|
||||
export const generateDate = (day: number, month: number, year: number) => new Date(year, month, day);
|
||||
|
||||
export const getDatesBetweenTwoDates = (startDate: Date, endDate: Date) => {
|
||||
const months = [];
|
||||
|
|
@ -45,8 +43,7 @@ export const getDatesBetweenTwoDates = (startDate: Date, endDate: Date) => {
|
|||
months.push(new Date(currentYear, currentMonth));
|
||||
currentDate.setMonth(currentDate.getMonth() + 1);
|
||||
}
|
||||
if (endYear === currentDate.getFullYear() && endMonth === currentDate.getMonth())
|
||||
months.push(endDate);
|
||||
if (endYear === currentDate.getFullYear() && endMonth === currentDate.getMonth()) months.push(endDate);
|
||||
|
||||
return months;
|
||||
};
|
||||
|
|
@ -73,9 +70,7 @@ export const getAllDaysInMonth = (month: number, year: number) => {
|
|||
weekNumber: getWeekNumberByDate(date),
|
||||
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
|
||||
today:
|
||||
currentDate.getFullYear() === year &&
|
||||
currentDate.getMonth() === month &&
|
||||
currentDate.getDate() === _day + 1
|
||||
currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === _day + 1
|
||||
? true
|
||||
: false,
|
||||
});
|
||||
|
|
@ -99,10 +94,7 @@ export const generateMonthDataByMonth = (month: number, year: number) => {
|
|||
return monthPayload;
|
||||
};
|
||||
|
||||
export const generateMonthDataByYear = (
|
||||
monthPayload: ChartDataType,
|
||||
side: null | "left" | "right"
|
||||
) => {
|
||||
export const generateMonthDataByYear = (monthPayload: ChartDataType, side: null | "left" | "right") => {
|
||||
let renderState = monthPayload;
|
||||
const renderPayload: any = [];
|
||||
|
||||
|
|
@ -114,16 +106,8 @@ export const generateMonthDataByYear = (
|
|||
if (side === null) {
|
||||
const currentDate = renderState.data.currentDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -138,16 +122,8 @@ export const generateMonthDataByYear = (
|
|||
} else if (side === "left") {
|
||||
const currentDate = renderState.data.startDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -158,16 +134,8 @@ export const generateMonthDataByYear = (
|
|||
} else if (side === "right") {
|
||||
const currentDate = renderState.data.endDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// Generating the date by using the year, month, and day
|
||||
export const generateDate = (day: number, month: number, year: number) =>
|
||||
new Date(year, month, day);
|
||||
export const generateDate = (day: number, month: number, year: number) => new Date(year, month, day);
|
||||
|
||||
// Getting the number of days in a month
|
||||
export const getNumberOfDaysInMonth = (month: number, year: number) => {
|
||||
|
|
@ -20,8 +19,7 @@ export const getWeekNumberByDate = (date: Date) => {
|
|||
const firstWeekStart = firstDayOfYear.getTime() - daysOffset * 24 * 60 * 60 * 1000;
|
||||
const weekStart = new Date(firstWeekStart);
|
||||
|
||||
const weekNumber =
|
||||
Math.floor((date.getTime() - weekStart.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;
|
||||
const weekNumber = Math.floor((date.getTime() - weekStart.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;
|
||||
|
||||
return weekNumber;
|
||||
};
|
||||
|
|
@ -86,8 +84,7 @@ export const getDatesBetweenTwoDates = (startDate: Date, endDate: Date) => {
|
|||
dates.push(new Date(currentYear, currentMonth));
|
||||
currentDate.setMonth(currentDate.getMonth() + 1);
|
||||
}
|
||||
if (endYear === currentDate.getFullYear() && endMonth === currentDate.getMonth())
|
||||
dates.push(endDate);
|
||||
if (endYear === currentDate.getFullYear() && endMonth === currentDate.getMonth()) dates.push(endDate);
|
||||
|
||||
return dates;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ export const getWeekNumberByDate = (date: Date) => {
|
|||
const firstWeekStart = firstDayOfYear.getTime() - daysOffset * 24 * 60 * 60 * 1000;
|
||||
const weekStart = new Date(firstWeekStart);
|
||||
|
||||
const weekNumber =
|
||||
Math.floor((date.getTime() - weekStart.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;
|
||||
const weekNumber = Math.floor((date.getTime() - weekStart.getTime()) / (7 * 24 * 60 * 60 * 1000)) + 1;
|
||||
|
||||
return weekNumber;
|
||||
};
|
||||
|
|
@ -25,8 +24,7 @@ export const getNumberOfDaysInMonth = (month: number, year: number) => {
|
|||
return date.getDate();
|
||||
};
|
||||
|
||||
export const generateDate = (day: number, month: number, year: number) =>
|
||||
new Date(year, month, day);
|
||||
export const generateDate = (day: number, month: number, year: number) => new Date(year, month, day);
|
||||
|
||||
export const getDatesBetweenTwoDates = (startDate: Date, endDate: Date) => {
|
||||
const months = [];
|
||||
|
|
@ -45,8 +43,7 @@ export const getDatesBetweenTwoDates = (startDate: Date, endDate: Date) => {
|
|||
months.push(new Date(currentYear, currentMonth));
|
||||
currentDate.setMonth(currentDate.getMonth() + 1);
|
||||
}
|
||||
if (endYear === currentDate.getFullYear() && endMonth === currentDate.getMonth())
|
||||
months.push(endDate);
|
||||
if (endYear === currentDate.getFullYear() && endMonth === currentDate.getMonth()) months.push(endDate);
|
||||
|
||||
return months;
|
||||
};
|
||||
|
|
@ -73,9 +70,7 @@ export const getAllDaysInMonth = (month: number, year: number) => {
|
|||
weekNumber: getWeekNumberByDate(date),
|
||||
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
|
||||
today:
|
||||
currentDate.getFullYear() === year &&
|
||||
currentDate.getMonth() === month &&
|
||||
currentDate.getDate() === _day + 1
|
||||
currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === _day + 1
|
||||
? true
|
||||
: false,
|
||||
});
|
||||
|
|
@ -99,10 +94,7 @@ export const generateMonthDataByMonth = (month: number, year: number) => {
|
|||
return monthPayload;
|
||||
};
|
||||
|
||||
export const generateMonthDataByYear = (
|
||||
monthPayload: ChartDataType,
|
||||
side: null | "left" | "right"
|
||||
) => {
|
||||
export const generateMonthDataByYear = (monthPayload: ChartDataType, side: null | "left" | "right") => {
|
||||
let renderState = monthPayload;
|
||||
const renderPayload: any = [];
|
||||
|
||||
|
|
@ -114,16 +106,8 @@ export const generateMonthDataByYear = (
|
|||
if (side === null) {
|
||||
const currentDate = renderState.data.currentDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -138,16 +122,8 @@ export const generateMonthDataByYear = (
|
|||
} else if (side === "left") {
|
||||
const currentDate = renderState.data.startDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -158,16 +134,8 @@ export const generateMonthDataByYear = (
|
|||
} else if (side === "right") {
|
||||
const currentDate = renderState.data.endDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,7 @@ import { ChartDataType, IGanttBlock } from "../types";
|
|||
// data
|
||||
import { weeks, months } from "../data";
|
||||
// helpers
|
||||
import {
|
||||
generateDate,
|
||||
getWeekNumberByDate,
|
||||
getNumberOfDaysInMonth,
|
||||
getDatesBetweenTwoDates,
|
||||
} from "./helpers";
|
||||
import { generateDate, getWeekNumberByDate, getNumberOfDaysInMonth, getDatesBetweenTwoDates } from "./helpers";
|
||||
|
||||
type GetAllDaysInMonthInMonthViewType = {
|
||||
date: any;
|
||||
|
|
@ -62,9 +57,7 @@ const getAllDaysInMonthInMonthView = (month: number, year: number): IMonthChild[
|
|||
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
|
||||
active: false,
|
||||
today:
|
||||
currentDate.getFullYear() === year &&
|
||||
currentDate.getMonth() === month &&
|
||||
currentDate.getDate() === _day + 1
|
||||
currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === _day + 1
|
||||
? true
|
||||
: false,
|
||||
});
|
||||
|
|
@ -100,16 +93,8 @@ export const generateMonthChart = (monthPayload: ChartDataType, side: null | "le
|
|||
if (side === null) {
|
||||
const currentDate = renderState.data.currentDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -124,16 +109,8 @@ export const generateMonthChart = (monthPayload: ChartDataType, side: null | "le
|
|||
} else if (side === "left") {
|
||||
const currentDate = renderState.data.startDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -144,16 +121,8 @@ export const generateMonthChart = (monthPayload: ChartDataType, side: null | "le
|
|||
} else if (side === "right") {
|
||||
const currentDate = renderState.data.endDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -191,10 +160,7 @@ export const getNumberOfDaysBetweenTwoDatesInMonth = (startDate: Date, endDate:
|
|||
};
|
||||
|
||||
// calc item scroll position and width
|
||||
export const getMonthChartItemPositionWidthInMonth = (
|
||||
chartData: ChartDataType,
|
||||
itemData: IGanttBlock
|
||||
) => {
|
||||
export const getMonthChartItemPositionWidthInMonth = (chartData: ChartDataType, itemData: IGanttBlock) => {
|
||||
let scrollPosition: number = 0;
|
||||
let scrollWidth: number = 0;
|
||||
|
||||
|
|
@ -207,9 +173,7 @@ export const getMonthChartItemPositionWidthInMonth = (
|
|||
|
||||
// position code starts
|
||||
const positionTimeDifference: number = startDate.getTime() - itemStartDate.getTime();
|
||||
const positionDaysDifference: number = Math.abs(
|
||||
Math.floor(positionTimeDifference / (1000 * 60 * 60 * 24))
|
||||
);
|
||||
const positionDaysDifference: number = Math.abs(Math.floor(positionTimeDifference / (1000 * 60 * 60 * 24)));
|
||||
scrollPosition = positionDaysDifference * chartData.data.width;
|
||||
|
||||
var diffMonths = (itemStartDate.getFullYear() - startDate.getFullYear()) * 12;
|
||||
|
|
@ -221,9 +185,7 @@ export const getMonthChartItemPositionWidthInMonth = (
|
|||
|
||||
// width code starts
|
||||
const widthTimeDifference: number = itemStartDate.getTime() - itemTargetDate.getTime();
|
||||
const widthDaysDifference: number = Math.abs(
|
||||
Math.floor(widthTimeDifference / (1000 * 60 * 60 * 24))
|
||||
);
|
||||
const widthDaysDifference: number = Math.abs(Math.floor(widthTimeDifference / (1000 * 60 * 60 * 24)));
|
||||
scrollWidth = (widthDaysDifference + 1) * chartData.data.width + 1;
|
||||
// width code ends
|
||||
|
||||
|
|
|
|||
|
|
@ -36,10 +36,7 @@ const generateMonthDataByMonthAndYearInMonthView = (month: number, year: number)
|
|||
return weekPayload;
|
||||
};
|
||||
|
||||
export const generateQuarterChart = (
|
||||
quarterPayload: ChartDataType,
|
||||
side: null | "left" | "right"
|
||||
) => {
|
||||
export const generateQuarterChart = (quarterPayload: ChartDataType, side: null | "left" | "right") => {
|
||||
let renderState = quarterPayload;
|
||||
const renderPayload: any = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -3,12 +3,7 @@ import { ChartDataType } from "../types";
|
|||
// data
|
||||
import { weeks, months } from "../data";
|
||||
// helpers
|
||||
import {
|
||||
generateDate,
|
||||
getWeekNumberByDate,
|
||||
getNumberOfDaysInMonth,
|
||||
getDatesBetweenTwoDates,
|
||||
} from "./helpers";
|
||||
import { generateDate, getWeekNumberByDate, getNumberOfDaysInMonth, getDatesBetweenTwoDates } from "./helpers";
|
||||
|
||||
type GetAllDaysInMonthInMonthViewType = {
|
||||
date: any;
|
||||
|
|
@ -34,9 +29,7 @@ const getAllDaysInMonthInMonthView = (month: number, year: number) => {
|
|||
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
|
||||
active: false,
|
||||
today:
|
||||
currentDate.getFullYear() === year &&
|
||||
currentDate.getMonth() === month &&
|
||||
currentDate.getDate() === _day + 1
|
||||
currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === _day + 1
|
||||
? true
|
||||
: false,
|
||||
});
|
||||
|
|
@ -72,16 +65,8 @@ export const generateWeekChart = (monthPayload: ChartDataType, side: null | "lef
|
|||
if (side === null) {
|
||||
const currentDate = renderState.data.currentDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -96,16 +81,8 @@ export const generateWeekChart = (monthPayload: ChartDataType, side: null | "lef
|
|||
} else if (side === "left") {
|
||||
const currentDate = renderState.data.startDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() - 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
@ -116,16 +93,8 @@ export const generateWeekChart = (monthPayload: ChartDataType, side: null | "lef
|
|||
} else if (side === "right") {
|
||||
const currentDate = renderState.data.endDate;
|
||||
|
||||
minusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + 1,
|
||||
currentDate.getDate()
|
||||
);
|
||||
plusDate = new Date(
|
||||
currentDate.getFullYear(),
|
||||
currentDate.getMonth() + range,
|
||||
currentDate.getDate()
|
||||
);
|
||||
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
|
||||
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
|
||||
|
||||
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
|||
cycle: cycleStore,
|
||||
cycleIssueFilter: cycleIssueFilterStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
} = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
|
@ -178,7 +179,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
|
|||
}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display" placement="bottom-end">
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
|||
module: moduleStore,
|
||||
moduleFilter: moduleFilterStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
} = useMobxStore();
|
||||
const activeLayout = issueFilterStore.userDisplayFilters.layout;
|
||||
|
|
@ -177,7 +178,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
|
|||
}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display" placement="bottom-end">
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@ import { observer } from "mobx-react-lite";
|
|||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// constants
|
||||
import { ISSUE_DISPLAY_FILTERS_BY_LAYOUT } from "constants/issue";
|
||||
// helper
|
||||
import { truncateText } from "helpers/string.helper";
|
||||
// ui
|
||||
import { Breadcrumbs, BreadcrumbItem, LayersIcon } from "@plane/ui";
|
||||
import { Breadcrumbs, LayersIcon } from "@plane/ui";
|
||||
// icons
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
// components
|
||||
|
|
@ -22,7 +20,11 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { project: projectStore, archivedIssueFilters: archivedIssueFiltersStore } = useMobxStore();
|
||||
const {
|
||||
project: projectStore,
|
||||
archivedIssueFilters: archivedIssueFiltersStore,
|
||||
projectState: projectStateStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const { currentProjectDetails } = projectStore;
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
|
|||
}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display" placement="bottom-end">
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
|||
const {
|
||||
issueFilter: issueFilterStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
inbox: inboxStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
} = useMobxStore();
|
||||
|
|
@ -172,7 +173,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
|||
}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display" placement="bottom-end">
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
|||
issueFilter: issueFilterStore,
|
||||
projectViewFilters: projectViewFiltersStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
projectViews: projectViewsStore,
|
||||
} = useMobxStore();
|
||||
|
||||
|
|
@ -163,7 +164,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
|
|||
}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""] ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
<FiltersDropdown title="Display" placement="bottom-end">
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const CompletedCycleIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color = "black",
|
||||
}) => (
|
||||
export const CompletedCycleIcon: React.FC<Props> = ({ width = "24", height = "24", className, color = "black" }) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height={height} width={width} className={className}>
|
||||
<path
|
||||
d="m21.65 36.6-6.9-6.85 2.1-2.1 4.8 4.7 9.2-9.2 2.1 2.15ZM6 44V7h6.25V4h3.25v3h17V4h3.25v3H42v37Zm3-3h30V19.5H9Zm0-24.5h30V10H9Zm0 0V10v6.5Z"
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const CurrentCycleIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color = "black",
|
||||
}) => (
|
||||
export const CurrentCycleIcon: React.FC<Props> = ({ width = "24", height = "24", className, color = "black" }) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height={height} width={width} className={className}>
|
||||
<path
|
||||
d="M15.3 28.3q-.85 0-1.425-.575-.575-.575-.575-1.425 0-.85.575-1.425.575-.575 1.425-.575.85 0 1.425.575.575.575.575 1.425 0 .85-.575 1.425-.575.575-1.425.575Zm8.85 0q-.85 0-1.425-.575-.575-.575-.575-1.425 0-.85.575-1.425.575-.575 1.425-.575.85 0 1.425.575.575.575.575 1.425 0 .85-.575 1.425-.575.575-1.425.575Zm8.5 0q-.85 0-1.425-.575-.575-.575-.575-1.425 0-.85.575-1.425.575-.575 1.425-.575.85 0 1.425.575.575.575.575 1.425 0 .85-.575 1.425-.575.575-1.425.575ZM6 44V7h6.25V4h3.25v3h17V4h3.25v3H42v37Zm3-3h30V19.5H9Zm0-24.5h30V10H9Zm0 0V10v6.5Z"
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const DocumentIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color,
|
||||
}) => (
|
||||
export const DocumentIcon: React.FC<Props> = ({ width = "24", height = "24", className, color }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const ExternalLinkIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color = "black",
|
||||
}) => (
|
||||
export const ExternalLinkIcon: React.FC<Props> = ({ width = "24", height = "24", className, color = "black" }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -84,4 +84,4 @@ export * from "./clock-icon";
|
|||
export * from "./bell-icon";
|
||||
export * from "./single-comment-icon";
|
||||
export * from "./related-icon";
|
||||
export * from "./module-icon";
|
||||
export * from "./module-icon";
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@ type Props = {
|
|||
color?: string;
|
||||
};
|
||||
|
||||
export const ModuleCancelledIcon: React.FC<Props> = ({
|
||||
width = "20",
|
||||
height = "20",
|
||||
className,
|
||||
}) => (
|
||||
export const ModuleCancelledIcon: React.FC<Props> = ({ width = "20", height = "20", className }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@ type Props = {
|
|||
color?: string;
|
||||
};
|
||||
|
||||
export const ModuleCompletedIcon: React.FC<Props> = ({
|
||||
width = "20",
|
||||
height = "20",
|
||||
className,
|
||||
}) => (
|
||||
export const ModuleCompletedIcon: React.FC<Props> = ({ width = "20", height = "20", className }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@ type Props = {
|
|||
color?: string;
|
||||
};
|
||||
|
||||
export const ModuleInProgressIcon: React.FC<Props> = ({
|
||||
width = "20",
|
||||
height = "20",
|
||||
className,
|
||||
}) => (
|
||||
export const ModuleInProgressIcon: React.FC<Props> = ({ width = "20", height = "20", className }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
@ -23,10 +19,7 @@ export const ModuleInProgressIcon: React.FC<Props> = ({
|
|||
<g id="Layer_1-2" data-name="Layer 1">
|
||||
<path fill="#f7b964" d="M0,111.14c.63.7.21,1.53.3,2.29-.07.26-.17.28-.3,0Z" />
|
||||
<path fill="#f6ab3e" d="M0,119.46a3.11,3.11,0,0,1,.3,2q-.19.33-.3,0Z" />
|
||||
<path
|
||||
fill="#facf96"
|
||||
d="M.27,123.16c0,.66.38,1.38-.27,2v-2C.13,122.89.22,122.91.27,123.16Z"
|
||||
/>
|
||||
<path fill="#facf96" d="M.27,123.16c0,.66.38,1.38-.27,2v-2C.13,122.89.22,122.91.27,123.16Z" />
|
||||
<path fill="#f5a939" d="M0,113.47l.3,0a2.39,2.39,0,0,1-.3,1.71Z" />
|
||||
<path fill="#f8ba67" d="M.27,123.16a.63.63,0,0,1-.27,0v-1.66l.3,0Z" />
|
||||
<path
|
||||
|
|
|
|||
|
|
@ -17,21 +17,12 @@ type Props = {
|
|||
width?: string;
|
||||
};
|
||||
|
||||
export const ModuleStatusIcon: React.FC<Props> = ({
|
||||
status,
|
||||
className,
|
||||
height = "12px",
|
||||
width = "12px",
|
||||
}) => {
|
||||
if (status === "backlog")
|
||||
return <ModuleBacklogIcon className={className} height={height} width={width} />;
|
||||
else if (status === "cancelled")
|
||||
return <ModuleCancelledIcon className={className} height={height} width={width} />;
|
||||
else if (status === "completed")
|
||||
return <ModuleCompletedIcon className={className} height={height} width={width} />;
|
||||
export const ModuleStatusIcon: React.FC<Props> = ({ status, className, height = "12px", width = "12px" }) => {
|
||||
if (status === "backlog") return <ModuleBacklogIcon className={className} height={height} width={width} />;
|
||||
else if (status === "cancelled") return <ModuleCancelledIcon className={className} height={height} width={width} />;
|
||||
else if (status === "completed") return <ModuleCompletedIcon className={className} height={height} width={width} />;
|
||||
else if (status === "in-progress")
|
||||
return <ModuleInProgressIcon className={className} height={height} width={width} />;
|
||||
else if (status === "paused")
|
||||
return <ModulePausedIcon className={className} height={height} width={width} />;
|
||||
else if (status === "paused") return <ModulePausedIcon className={className} height={height} width={width} />;
|
||||
else return <ModulePlannedIcon className={className} height={height} width={width} />;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,19 +2,8 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const PencilScribbleIcon: React.FC<Props> = ({
|
||||
width = "20",
|
||||
height = "20",
|
||||
className,
|
||||
color = "#000000",
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 96 960 960"
|
||||
>
|
||||
export const PencilScribbleIcon: React.FC<Props> = ({ width = "20", height = "20", className, color = "#000000" }) => (
|
||||
<svg width={width} height={height} className={className} xmlns="http://www.w3.org/2000/svg" viewBox="0 96 960 960">
|
||||
<path
|
||||
d="M560 936q-12 0-21-9t-9-21q0-13 9-21.5t21-8.5q59 0 99.5-24t40.5-56q0-23-29.5-45T591 717l47-47q63 19 92.5 52.5T760 796q0 67-61 103.5T560 936ZM240 642q-64-14-92-44t-28-62q0-35 26-63t120-62q66-24 85-39t19-35q0-25-22-43t-68-18q-27 0-46 7t-34 22q-8 8-20.5 9.5T157 308q-11-8-11.5-20t7.5-21q17-22 51-36.5t76-14.5q68 0 109 32.5t41 88.5q0 41-28.5 69.5T290 466q-67 25-88.5 39.5T180 536q0 16 27 30.5t81 27.5l-48 48Zm496-154L608 360l45-45q18-18 40-18t40 18l48 48q18 18 18 40t-18 40l-45 45ZM220 876h42l345-345-42-42-345 345v42Zm-60 60V808l405-405 128 128-405 405H160Zm405-447 42 42-42-42Z"
|
||||
fill={color}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const QuestionMarkCircleIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
}) => (
|
||||
export const QuestionMarkCircleIcon: React.FC<Props> = ({ width = "24", height = "24", className }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const SingleCommentCard: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color,
|
||||
}) => (
|
||||
export const SingleCommentCard: React.FC<Props> = ({ width = "24", height = "24", className, color }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const TagIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color = "black",
|
||||
}) => (
|
||||
export const TagIcon: React.FC<Props> = ({ width = "24", height = "24", className, color = "black" }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const TriangleExclamationIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
}) => (
|
||||
export const TriangleExclamationIcon: React.FC<Props> = ({ width = "24", height = "24", className }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const UpcomingCycleIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color = "black",
|
||||
}) => (
|
||||
export const UpcomingCycleIcon: React.FC<Props> = ({ width = "24", height = "24", className, color = "black" }) => (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height={height} width={width} className={className}>
|
||||
<path
|
||||
d="M28.3 44v-3H39V19.5H9v11H6V10q0-1.2.9-2.1Q7.8 7 9 7h3.25V4h3.25v3h17V4h3.25v3H39q1.2 0 2.1.9.9.9.9 2.1v31q0 1.2-.9 2.1-.9.9-2.1.9ZM16 47.3l-2.1-2.1 5.65-5.7H2.5v-3h17.05l-5.65-5.7 2.1-2.1 9.3 9.3ZM9 16.5h30V10H9Zm0 0V10v6.5Z"
|
||||
|
|
|
|||
|
|
@ -2,12 +2,7 @@ import React from "react";
|
|||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const UserGroupIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
className,
|
||||
color,
|
||||
}) => (
|
||||
export const UserGroupIcon: React.FC<Props> = ({ width = "24", height = "24", className, color }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
|
|||
|
||||
const editorRef = useRef<any>(null);
|
||||
|
||||
const editorSuggestion = useEditorSuggestions()
|
||||
const editorSuggestion = useEditorSuggestions();
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, inboxId } = router.query;
|
||||
|
|
|
|||
|
|
@ -37,9 +37,7 @@ export const JiraConfirmImport: React.FC = () => {
|
|||
<p className="text-sm text-custom-text-200">Labels</p>
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="mb-2 text-lg font-semibold">
|
||||
{watch("data.users").filter((user) => user.import).length}
|
||||
</h4>
|
||||
<h4 className="mb-2 text-lg font-semibold">{watch("data.users").filter((user) => user.import).length}</h4>
|
||||
<p className="text-sm text-custom-text-200">User</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { X } from "lucide-react";
|
|||
// helpers
|
||||
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
|
||||
// types
|
||||
import { IIssueFilterOptions, IIssueLabels, IProject, IStateResponse, IUserLite } from "types";
|
||||
import { IIssueFilterOptions, IIssueLabels, IProject, IState, IUserLite } from "types";
|
||||
|
||||
type Props = {
|
||||
appliedFilters: IIssueFilterOptions;
|
||||
|
|
@ -24,7 +24,7 @@ type Props = {
|
|||
labels?: IIssueLabels[] | undefined;
|
||||
members?: IUserLite[] | undefined;
|
||||
projects?: IProject[] | undefined;
|
||||
states?: IStateResponse | undefined;
|
||||
states?: IState[] | undefined;
|
||||
};
|
||||
|
||||
const membersFilters = ["assignees", "mentions", "created_by", "subscriber"];
|
||||
|
|
@ -70,7 +70,7 @@ export const AppliedFiltersList: React.FC<Props> = observer((props) => {
|
|||
{filterKey === "priority" && (
|
||||
<AppliedPriorityFilters handleRemove={(val) => handleRemoveFilter("priority", val)} values={value} />
|
||||
)}
|
||||
{filterKey === "state" && (
|
||||
{filterKey === "state" && states && (
|
||||
<AppliedStateFilters
|
||||
handleRemove={(val) => handleRemoveFilter("state", val)}
|
||||
states={states}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { archivedIssueFilters: archivedIssueFiltersStore, project: projectStore } = useMobxStore();
|
||||
const {
|
||||
archivedIssueFilters: archivedIssueFiltersStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const userFilters = archivedIssueFiltersStore.userFilters;
|
||||
|
||||
|
|
@ -74,7 +78,7 @@ export const ArchivedIssueAppliedFiltersRoot: React.FC = observer(() => {
|
|||
handleRemoveFilter={handleRemoveFilter}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""]}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useRouter } from "next/router";
|
||||
import { observer } from "mobx-react-lite";
|
||||
|
||||
// mobx store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// components
|
||||
|
|
@ -12,7 +11,11 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, cycleId } = router.query;
|
||||
|
||||
const { project: projectStore, cycleIssueFilter: cycleIssueFilterStore } = useMobxStore();
|
||||
const {
|
||||
project: projectStore,
|
||||
cycleIssueFilter: cycleIssueFilterStore,
|
||||
projectState: projectStateStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const userFilters = cycleIssueFilterStore.cycleFilters;
|
||||
|
||||
|
|
@ -70,7 +73,7 @@ export const CycleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
handleRemoveFilter={handleRemoveFilter}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""]}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, moduleId } = router.query;
|
||||
|
||||
const { project: projectStore, moduleFilter: moduleFilterStore } = useMobxStore();
|
||||
const { project: projectStore, moduleFilter: moduleFilterStore, projectState: projectStateStore } = useMobxStore();
|
||||
|
||||
const userFilters = moduleFilterStore.moduleFilters;
|
||||
|
||||
|
|
@ -70,7 +70,7 @@ export const ModuleAppliedFiltersRoot: React.FC = observer(() => {
|
|||
handleRemoveFilter={handleRemoveFilter}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""]}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
const { issueFilter: issueFilterStore, project: projectStore } = useMobxStore();
|
||||
const { issueFilter: issueFilterStore, project: projectStore, projectState: projectStateStore } = useMobxStore();
|
||||
|
||||
const userFilters = issueFilterStore.userFilters;
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ export const ProjectAppliedFiltersRoot: React.FC = observer(() => {
|
|||
handleRemoveFilter={handleRemoveFilter}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""]}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
projectViews: projectViewsStore,
|
||||
projectViewFilters: projectViewFiltersStore,
|
||||
} = useMobxStore();
|
||||
|
|
@ -99,7 +100,7 @@ export const ProjectViewAppliedFiltersRoot: React.FC = observer(() => {
|
|||
handleRemoveFilter={handleRemoveFilter}
|
||||
labels={projectStore.labels?.[projectId?.toString() ?? ""] ?? []}
|
||||
members={projectStore.members?.[projectId?.toString() ?? ""]?.map((m) => m.member)}
|
||||
states={projectStore.states?.[projectId?.toString() ?? ""]}
|
||||
states={projectStateStore.states?.[projectId?.toString() ?? ""]}
|
||||
/>
|
||||
{storedFilters && viewDetails && areFiltersDifferent(storedFilters, viewDetails.query_data ?? {}) && (
|
||||
<Button variant="primary" size="sm" onClick={handleUpdateView}>
|
||||
|
|
|
|||
|
|
@ -3,26 +3,22 @@ import { observer } from "mobx-react-lite";
|
|||
// icons
|
||||
import { StateGroupIcon } from "@plane/ui";
|
||||
import { X } from "lucide-react";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// types
|
||||
import { IStateResponse } from "types";
|
||||
import { IState } from "types";
|
||||
|
||||
type Props = {
|
||||
handleRemove: (val: string) => void;
|
||||
states: IStateResponse | undefined;
|
||||
states: IState[];
|
||||
values: string[];
|
||||
};
|
||||
|
||||
export const AppliedStateFilters: React.FC<Props> = observer((props) => {
|
||||
const { handleRemove, states, values } = props;
|
||||
|
||||
const statesList = getStatesList(states);
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1 flex-wrap">
|
||||
{values.map((stateId) => {
|
||||
const stateDetails = statesList?.find((s) => s.id === stateId);
|
||||
const stateDetails = states?.find((s) => s.id === stateId);
|
||||
|
||||
if (!stateDetails) return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
FilterTargetDate,
|
||||
} from "components/issues";
|
||||
// types
|
||||
import { IIssueFilterOptions, IIssueLabels, IProject, IStateResponse, IUserLite } from "types";
|
||||
import { IIssueFilterOptions, IIssueLabels, IProject, IState, IUserLite } from "types";
|
||||
// constants
|
||||
import { ILayoutDisplayFiltersOptions } from "constants/issue";
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ type Props = {
|
|||
labels?: IIssueLabels[] | undefined;
|
||||
members?: IUserLite[] | undefined;
|
||||
projects?: IProject[] | undefined;
|
||||
states?: IStateResponse | undefined;
|
||||
states?: IState[] | undefined;
|
||||
};
|
||||
|
||||
export const FilterSelection: React.FC<Props> = observer((props) => {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
import React, { useState } from "react";
|
||||
|
||||
// components
|
||||
import { FilterHeader, FilterOption } from "components/issues";
|
||||
// ui
|
||||
import { Loader, StateGroupIcon } from "@plane/ui";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// types
|
||||
import { IStateResponse } from "types";
|
||||
import { IState } from "types";
|
||||
|
||||
type Props = {
|
||||
appliedFilters: string[] | null;
|
||||
handleUpdate: (val: string) => void;
|
||||
searchQuery: string;
|
||||
states: IStateResponse | undefined;
|
||||
states: IState[] | undefined;
|
||||
};
|
||||
|
||||
export const FilterState: React.FC<Props> = (props) => {
|
||||
|
|
@ -22,11 +19,9 @@ export const FilterState: React.FC<Props> = (props) => {
|
|||
const [itemsToRender, setItemsToRender] = useState(5);
|
||||
const [previewEnabled, setPreviewEnabled] = useState(true);
|
||||
|
||||
const statesList = getStatesList(states);
|
||||
|
||||
const appliedFiltersCount = appliedFilters?.length ?? 0;
|
||||
|
||||
const filteredOptions = statesList?.filter((s) => s.name.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
const filteredOptions = states?.filter((s) => s.name.toLowerCase().includes(searchQuery.toLowerCase()));
|
||||
|
||||
const handleViewToggle = () => {
|
||||
if (!filteredOptions) return;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
|||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
cycleIssue: cycleIssueStore,
|
||||
issueFilter: issueFilterStore,
|
||||
cycleIssueKanBanView: cycleIssueKanBanViewStore,
|
||||
|
|
@ -98,7 +99,7 @@ export const CycleKanBanLayout: React.FC = observer(() => {
|
|||
cycleIssueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import { KanBanSwimLanes } from "../swimlanes";
|
|||
import { KanBan } from "../default";
|
||||
import { ModuleIssueQuickActions } from "components/issues";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// helpers
|
||||
import { orderArrayBy } from "helpers/array.helper";
|
||||
// types
|
||||
import { IIssue } from "types";
|
||||
// constants
|
||||
|
|
@ -24,6 +22,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
|||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
moduleIssue: moduleIssueStore,
|
||||
issueFilter: issueFilterStore,
|
||||
moduleIssueKanBanView: moduleIssueKanBanViewStore,
|
||||
|
|
@ -96,7 +95,7 @@ export const ModuleKanBanLayout: React.FC = observer(() => {
|
|||
moduleIssueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
|||
const {
|
||||
workspace: workspaceStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
profileIssues: profileIssuesStore,
|
||||
profileIssueFilters: profileIssueFiltersStore,
|
||||
issueKanBanView: issueKanBanViewStore,
|
||||
|
|
@ -85,7 +86,7 @@ export const ProfileIssuesKanBanLayout: FC = observer(() => {
|
|||
issueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = workspaceStore.workspaceLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ export const KanBanLayout: React.FC = observer(() => {
|
|||
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
issue: issueStore,
|
||||
issueFilter: issueFilterStore,
|
||||
issueKanBanView: issueKanBanViewStore,
|
||||
|
|
@ -88,7 +89,7 @@ export const KanBanLayout: React.FC = observer(() => {
|
|||
issueKanBanViewStore.handleKanBanToggle(toggle, value);
|
||||
};
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import React from "react";
|
||||
// react beautiful dnd
|
||||
import { DragDropContext } from "@hello-pangea/dnd";
|
||||
// mobx
|
||||
import { observer } from "mobx-react-lite";
|
||||
// components
|
||||
import { KanBanSwimLanes } from "../swimlanes";
|
||||
|
|
@ -17,6 +15,7 @@ export interface IViewKanBanLayout {}
|
|||
export const ProjectViewKanBanLayout: React.FC = observer(() => {
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
issue: issueStore,
|
||||
issueFilter: issueFilterStore,
|
||||
issueKanBanView: issueKanBanViewStore,
|
||||
|
|
@ -54,12 +53,12 @@ export const ProjectViewKanBanLayout: React.FC = observer(() => {
|
|||
issueStore.updateIssueStructure(group_by, sub_group_by, issue);
|
||||
};
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = projectStore?.projectStates || null;
|
||||
const projects = projectStateStore?.projectStates || null;
|
||||
const estimates = null;
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ export const ArchivedIssueListLayout: FC = observer(() => {
|
|||
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
archivedIssues: archivedIssueStore,
|
||||
archivedIssueFilters: archivedIssueFiltersStore,
|
||||
} = useMobxStore();
|
||||
|
|
@ -38,7 +39,7 @@ export const ArchivedIssueListLayout: FC = observer(() => {
|
|||
|
||||
const projectDetails = projectId ? projectStore.project_details[projectId.toString()] : null;
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export const CycleListLayout: React.FC = observer(() => {
|
|||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
issueFilter: issueFilterStore,
|
||||
cycleIssue: cycleIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
|
|
@ -55,7 +56,7 @@ export const CycleListLayout: React.FC = observer(() => {
|
|||
[cycleIssueStore, issueDetailStore, cycleId, workspaceSlug]
|
||||
);
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export const ModuleListLayout: React.FC = observer(() => {
|
|||
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
issueFilter: issueFilterStore,
|
||||
moduleIssue: moduleIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
|
|
@ -55,7 +56,7 @@ export const ModuleListLayout: React.FC = observer(() => {
|
|||
[moduleIssueStore, issueDetailStore, moduleId, workspaceSlug]
|
||||
);
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export interface IProfileIssuesListLayout {}
|
|||
export const ProfileIssuesListLayout: FC = observer(() => {
|
||||
const {
|
||||
workspace: workspaceStore,
|
||||
projectState: projectStateStore,
|
||||
project: projectStore,
|
||||
profileIssueFilters: profileIssueFiltersStore,
|
||||
profileIssues: profileIssuesStore,
|
||||
|
|
@ -44,7 +45,7 @@ export const ProfileIssuesListLayout: FC = observer(() => {
|
|||
[profileIssuesStore, issueDetailStore, workspaceSlug]
|
||||
);
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = workspaceStore.workspaceLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const ListLayout: FC = observer(() => {
|
|||
// store
|
||||
const {
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
issue: issueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
issueFilter: issueFilterStore,
|
||||
|
|
@ -45,7 +46,7 @@ export const ListLayout: FC = observer(() => {
|
|||
[issueStore, issueDetailStore, workspaceSlug]
|
||||
);
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,12 @@ import { ISSUE_STATE_GROUPS, ISSUE_PRIORITIES } from "constants/issue";
|
|||
export interface IViewListLayout {}
|
||||
|
||||
export const ProjectViewListLayout: React.FC = observer(() => {
|
||||
const { project: projectStore, issue: issueStore, issueFilter: issueFilterStore }: RootStore = useMobxStore();
|
||||
const {
|
||||
project: projectStore,
|
||||
issue: issueStore,
|
||||
issueFilter: issueFilterStore,
|
||||
projectState: projectStateStore,
|
||||
}: RootStore = useMobxStore();
|
||||
|
||||
const issues = issueStore?.getIssues;
|
||||
|
||||
|
|
@ -23,12 +28,12 @@ export const ProjectViewListLayout: React.FC = observer(() => {
|
|||
issueStore.updateIssueStructure(group_by, null, issue);
|
||||
};
|
||||
|
||||
const states = projectStore?.projectStates || null;
|
||||
const states = projectStateStore?.projectStates || null;
|
||||
const priorities = ISSUE_PRIORITIES || null;
|
||||
const labels = projectStore?.projectLabels || null;
|
||||
const members = projectStore?.projectMembers || null;
|
||||
const stateGroups = ISSUE_STATE_GROUPS || null;
|
||||
const projects = projectStore?.projectStates || null;
|
||||
const projects = projectStateStore?.projectStates || null;
|
||||
const estimates = null;
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -100,14 +100,12 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
|
|||
{(projectLabels ? projectLabels : [])
|
||||
?.filter((l) => value.includes(l.id))
|
||||
.map((label) => (
|
||||
<Tooltip
|
||||
position="top"
|
||||
tooltipHeading="Labels"
|
||||
tooltipContent={label.name ?? ''}
|
||||
>
|
||||
<Tooltip position="top" tooltipHeading="Labels" tooltipContent={label.name ?? ""}>
|
||||
<div
|
||||
key={label.id}
|
||||
className={`overflow-hidden flex hover:bg-custom-background-80 ${!disabled && "cursor-pointer"} items-center flex-shrink-0 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs h-full max-w-full`}
|
||||
className={`overflow-hidden flex hover:bg-custom-background-80 ${
|
||||
!disabled && "cursor-pointer"
|
||||
} items-center flex-shrink-0 rounded border-[0.5px] border-custom-border-300 px-2.5 py-1 text-xs h-full max-w-full`}
|
||||
>
|
||||
<div className="overflow-hidden flex items-center gap-1.5 text-custom-text-200 max-w-full">
|
||||
<span
|
||||
|
|
@ -116,9 +114,7 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
|
|||
backgroundColor: label?.color ?? "#000000",
|
||||
}}
|
||||
/>
|
||||
<div className="truncate line-clamp-1 inline-block w-auto max-w-[100px]">
|
||||
{label.name}
|
||||
</div>
|
||||
<div className="truncate line-clamp-1 inline-block w-auto max-w-[100px]">{label.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
|
@ -143,8 +139,9 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
|
|||
)
|
||||
) : (
|
||||
<div
|
||||
className={`h-full flex items-center justify-center text-xs rounded px-2.5 py-1 hover:bg-custom-background-80 ${noLabelBorder ? "" : "border-[0.5px] border-custom-border-300"
|
||||
}`}
|
||||
className={`h-full flex items-center justify-center text-xs rounded px-2.5 py-1 hover:bg-custom-background-80 ${
|
||||
noLabelBorder ? "" : "border-[0.5px] border-custom-border-300"
|
||||
}`}
|
||||
>
|
||||
Select labels
|
||||
</div>
|
||||
|
|
@ -165,12 +162,13 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
|
|||
<button
|
||||
ref={setReferenceElement}
|
||||
type="button"
|
||||
className={`flex items-center justify-between gap-1 w-full text-xs ${disabled
|
||||
? "cursor-not-allowed text-custom-text-200"
|
||||
: value.length <= maxRender
|
||||
className={`flex items-center justify-between gap-1 w-full text-xs ${
|
||||
disabled
|
||||
? "cursor-not-allowed text-custom-text-200"
|
||||
: value.length <= maxRender
|
||||
? "cursor-pointer"
|
||||
: "cursor-pointer hover:bg-custom-background-80"
|
||||
} ${buttonClassName}`}
|
||||
} ${buttonClassName}`}
|
||||
onClick={() => !projectLabels && fetchProjectLabels()}
|
||||
>
|
||||
{label}
|
||||
|
|
@ -204,19 +202,19 @@ export const IssuePropertyLabels: React.FC<IIssuePropertyLabels> = observer((pro
|
|||
key={option.value}
|
||||
value={option.value}
|
||||
className={({ active, selected }) =>
|
||||
`flex items-center justify-between gap-2 cursor-pointer select-none truncate rounded px-1 py-1.5 ${active ? "bg-custom-background-80" : ""
|
||||
`flex items-center justify-between gap-2 cursor-pointer select-none truncate rounded px-1 py-1.5 ${
|
||||
active ? "bg-custom-background-80" : ""
|
||||
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
|
||||
}
|
||||
>
|
||||
{({ selected }) => (
|
||||
<>
|
||||
{option.content}
|
||||
{selected &&
|
||||
{selected && (
|
||||
<div className="flex-shrink-0">
|
||||
|
||||
<Check className={`h-3.5 w-3.5`} />
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Combobox.Option>
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
|
|||
placement,
|
||||
} = props;
|
||||
|
||||
const { workspace: workspaceStore, project: projectStore }: RootStore = useMobxStore();
|
||||
const { workspace: workspaceStore, projectState: projectStateStore }: RootStore = useMobxStore();
|
||||
const workspaceSlug = workspaceStore?.workspaceSlug;
|
||||
|
||||
const [query, setQuery] = useState("");
|
||||
|
|
@ -50,7 +50,7 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
|
|||
const [isLoading, setIsLoading] = useState<Boolean>(false);
|
||||
|
||||
const projectStates: IState[] = [];
|
||||
const projectStatesByGroup = projectId && projectStore?.states?.[projectId];
|
||||
const projectStatesByGroup = projectStateStore.groupedProjectStates;
|
||||
if (projectStatesByGroup)
|
||||
for (const group in projectStatesByGroup) projectStates.push(...projectStatesByGroup[group]);
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ export const IssuePropertyState: React.FC<IIssuePropertyState> = observer((props
|
|||
if (workspaceSlug && projectId)
|
||||
workspaceSlug &&
|
||||
projectId &&
|
||||
projectStore.fetchProjectStates(workspaceSlug, projectId).then(() => setIsLoading(false));
|
||||
projectStateStore.fetchProjectStates(workspaceSlug, projectId).then(() => setIsLoading(false));
|
||||
};
|
||||
|
||||
const dropdownOptions = projectStates?.map((state) => ({
|
||||
|
|
|
|||
|
|
@ -2,14 +2,7 @@ import { observer } from "mobx-react-lite";
|
|||
// components
|
||||
import { SpreadsheetColumn } from "components/issues";
|
||||
// types
|
||||
import {
|
||||
IIssue,
|
||||
IIssueDisplayFilterOptions,
|
||||
IIssueDisplayProperties,
|
||||
IIssueLabels,
|
||||
IStateResponse,
|
||||
IUserLite,
|
||||
} from "types";
|
||||
import { IIssue, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueLabels, IState, IUserLite } from "types";
|
||||
|
||||
type Props = {
|
||||
displayFilters: IIssueDisplayFilterOptions;
|
||||
|
|
@ -21,7 +14,7 @@ type Props = {
|
|||
issues: IIssue[] | undefined;
|
||||
members?: IUserLite[] | undefined;
|
||||
labels?: IIssueLabels[] | undefined;
|
||||
states?: IStateResponse | undefined;
|
||||
states?: IState[] | undefined;
|
||||
};
|
||||
|
||||
export const SpreadsheetColumnsList: React.FC<Props> = observer((props) => {
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@ import { IssuePropertyState } from "../../properties";
|
|||
// hooks
|
||||
import useSubIssue from "hooks/use-sub-issue";
|
||||
// types
|
||||
import { IIssue, IStateResponse } from "types";
|
||||
import { IIssue, IState } from "types";
|
||||
|
||||
type Props = {
|
||||
issue: IIssue;
|
||||
onChange: (data: Partial<IIssue>) => void;
|
||||
states: IStateResponse | undefined;
|
||||
states: IState[] | undefined;
|
||||
expandedIssues: string[];
|
||||
disabled: boolean;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const CycleSpreadsheetLayout: React.FC = observer(() => {
|
|||
cycleIssue: cycleIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const issues = cycleIssueStore.getIssues;
|
||||
|
|
@ -60,7 +61,7 @@ export const CycleSpreadsheetLayout: React.FC = observer(() => {
|
|||
issues={issues as IIssueUnGroupedStructure}
|
||||
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined}
|
||||
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
|
||||
states={projectId ? projectStore.states?.[projectId.toString()] : undefined}
|
||||
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
|
||||
handleIssueAction={() => {}}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
disableUserActions={false}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const ModuleSpreadsheetLayout: React.FC = observer(() => {
|
|||
moduleIssue: moduleIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const issues = moduleIssueStore.getIssues;
|
||||
|
|
@ -60,7 +61,7 @@ export const ModuleSpreadsheetLayout: React.FC = observer(() => {
|
|||
issues={issues as IIssueUnGroupedStructure}
|
||||
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined}
|
||||
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
|
||||
states={projectId ? projectStore.states?.[projectId.toString()] : undefined}
|
||||
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
|
||||
handleIssueAction={() => {}}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
disableUserActions={false}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const ProjectSpreadsheetLayout: React.FC = observer(() => {
|
|||
issueFilter: issueFilterStore,
|
||||
issueDetail: issueDetailStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
user: userStore,
|
||||
} = useMobxStore();
|
||||
|
||||
|
|
@ -62,7 +63,7 @@ export const ProjectSpreadsheetLayout: React.FC = observer(() => {
|
|||
issues={issues as IIssueUnGroupedStructure}
|
||||
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined}
|
||||
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
|
||||
states={projectId ? projectStore.states?.[projectId.toString()] : undefined}
|
||||
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
|
||||
handleIssueAction={() => {}}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
disableUserActions={false}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const ProjectViewSpreadsheetLayout: React.FC = observer(() => {
|
|||
projectViewIssues: projectViewIssueStore,
|
||||
issueDetail: issueDetailStore,
|
||||
project: projectStore,
|
||||
projectState: projectStateStore,
|
||||
} = useMobxStore();
|
||||
|
||||
const issues = projectViewIssueStore.getIssues;
|
||||
|
|
@ -60,7 +61,7 @@ export const ProjectViewSpreadsheetLayout: React.FC = observer(() => {
|
|||
issues={issues as IIssueUnGroupedStructure}
|
||||
members={projectId ? projectStore.members?.[projectId.toString()]?.map((m) => m.member) : undefined}
|
||||
labels={projectId ? projectStore.labels?.[projectId.toString()] ?? undefined : undefined}
|
||||
states={projectId ? projectStore.states?.[projectId.toString()] : undefined}
|
||||
states={projectId ? projectStateStore.states?.[projectId.toString()] : undefined}
|
||||
handleIssueAction={() => {}}
|
||||
handleUpdateIssue={handleUpdateIssue}
|
||||
disableUserActions={false}
|
||||
|
|
|
|||
|
|
@ -27,14 +27,7 @@ import {
|
|||
// ui
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
// types
|
||||
import {
|
||||
IIssue,
|
||||
IIssueDisplayFilterOptions,
|
||||
IIssueLabels,
|
||||
IStateResponse,
|
||||
IUserLite,
|
||||
TIssueOrderByOptions,
|
||||
} from "types";
|
||||
import { IIssue, IIssueDisplayFilterOptions, IIssueLabels, IState, IUserLite, TIssueOrderByOptions } from "types";
|
||||
// constants
|
||||
import { SPREADSHEET_PROPERTY_DETAILS } from "constants/spreadsheet";
|
||||
|
||||
|
|
@ -48,7 +41,7 @@ type Props = {
|
|||
property: string;
|
||||
members?: IUserLite[] | undefined;
|
||||
labels?: IIssueLabels[] | undefined;
|
||||
states?: IStateResponse | undefined;
|
||||
states?: IState[] | undefined;
|
||||
};
|
||||
|
||||
export const SpreadsheetColumn: React.FC<Props> = (props) => {
|
||||
|
|
|
|||
|
|
@ -6,14 +6,7 @@ import { SpreadsheetColumnsList, SpreadsheetIssuesColumn, SpreadsheetInlineCreat
|
|||
import { IssuePeekOverview } from "components/issues/issue-peek-overview";
|
||||
import { Spinner } from "@plane/ui";
|
||||
// types
|
||||
import {
|
||||
IIssue,
|
||||
IIssueDisplayFilterOptions,
|
||||
IIssueDisplayProperties,
|
||||
IIssueLabels,
|
||||
IStateResponse,
|
||||
IUserLite,
|
||||
} from "types";
|
||||
import { IIssue, IIssueDisplayFilterOptions, IIssueDisplayProperties, IIssueLabels, IState, IUserLite } from "types";
|
||||
|
||||
type Props = {
|
||||
displayProperties: IIssueDisplayProperties;
|
||||
|
|
@ -22,7 +15,7 @@ type Props = {
|
|||
issues: IIssue[] | undefined;
|
||||
members?: IUserLite[] | undefined;
|
||||
labels?: IIssueLabels[] | undefined;
|
||||
states?: IStateResponse | undefined;
|
||||
states?: IState[] | undefined;
|
||||
handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void;
|
||||
handleUpdateIssue: (issue: IIssue, data: Partial<IIssue>) => void;
|
||||
openIssuesListModal?: (() => void) | null;
|
||||
|
|
|
|||
|
|
@ -251,7 +251,9 @@ export const IssueView: FC<IIssueView> = observer((props) => {
|
|||
<div className="absolute top-0 left-0 h-full w-full z-[999] flex items-center justify-center bg-custom-background-100 opacity-60" />
|
||||
)}
|
||||
{isLoading && !issue ? (
|
||||
<div className="h-full w-full flex items-center justify-center"><Spinner/></div>
|
||||
<div className="h-full w-full flex items-center justify-center">
|
||||
<Spinner />
|
||||
</div>
|
||||
) : (
|
||||
issue && (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -18,8 +18,11 @@ export const IssueReaction: React.FC<Props> = (props) => {
|
|||
|
||||
const { user } = useUserAuth();
|
||||
|
||||
const { reactions, groupedReactions, handleReactionCreate, handleReactionDelete } =
|
||||
useIssueReaction(workspaceSlug, projectId, issueId);
|
||||
const { reactions, groupedReactions, handleReactionCreate, handleReactionDelete } = useIssueReaction(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId
|
||||
);
|
||||
|
||||
const handleReactionClick = (reaction: string) => {
|
||||
if (!workspaceSlug || !projectId || !issueId) return;
|
||||
|
|
@ -38,9 +41,7 @@ export const IssueReaction: React.FC<Props> = (props) => {
|
|||
<ReactionSelector
|
||||
size="md"
|
||||
position="top"
|
||||
value={
|
||||
reactions?.filter((reaction) => reaction.actor === user?.id).map((r) => r.reaction) || []
|
||||
}
|
||||
value={reactions?.filter((reaction) => reaction.actor === user?.id).map((r) => r.reaction) || []}
|
||||
onSelect={handleReactionClick}
|
||||
/>
|
||||
|
||||
|
|
|
|||
|
|
@ -10,12 +10,7 @@ type Props = {
|
|||
workspaceSlug: string;
|
||||
};
|
||||
|
||||
export const PeekOverviewIssueDetails: React.FC<Props> = ({
|
||||
handleUpdateIssue,
|
||||
issue,
|
||||
readOnly,
|
||||
workspaceSlug,
|
||||
}) => (
|
||||
export const PeekOverviewIssueDetails: React.FC<Props> = ({ handleUpdateIssue, issue, readOnly, workspaceSlug }) => (
|
||||
<div className="space-y-2">
|
||||
<h6 className="font-medium text-custom-text-200">
|
||||
{issue.project_detail.identifier}-{issue.sequence_id}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { Fragment, useState } from "react";
|
||||
import { Fragment, useState, FC } from "react";
|
||||
import { usePopper } from "react-popper";
|
||||
import { Popover, Transition } from "@headlessui/react";
|
||||
import { CalendarDays, X } from "lucide-react";
|
||||
|
|
@ -15,9 +15,9 @@ type Props = {
|
|||
value: string | null;
|
||||
};
|
||||
|
||||
export const IssueDateSelect: React.FC<Props> = ({ label, maxDate, minDate, onChange, value }) => {
|
||||
const [referenceElement, setReferenceElement] = React.useState<HTMLDivElement | null>(null);
|
||||
const [popperElement, setPopperElement] = React.useState<HTMLDivElement | null>(null);
|
||||
export const IssueDateSelect: FC<Props> = ({ label, maxDate, minDate, onChange, value }) => {
|
||||
const [referenceElement, setReferenceElement] = useState<HTMLDivElement | null>(null);
|
||||
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
|
||||
|
||||
const { styles, attributes } = usePopper(referenceElement, popperElement, {
|
||||
placement: "bottom-start",
|
||||
|
|
@ -50,7 +50,7 @@ export const IssueDateSelect: React.FC<Props> = ({ label, maxDate, minDate, onCh
|
|||
</Popover.Button>
|
||||
|
||||
<Transition
|
||||
as={React.Fragment}
|
||||
as={Fragment}
|
||||
enter="transition ease-out duration-200"
|
||||
enterFrom="opacity-0 translate-y-1"
|
||||
enterTo="opacity-100 translate-y-0"
|
||||
|
|
|
|||
|
|
@ -1,17 +1,12 @@
|
|||
import React from "react";
|
||||
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
import useSWR from "swr";
|
||||
|
||||
// services
|
||||
import { ProjectStateService } from "services/project";
|
||||
// ui
|
||||
import { CustomSearchSelect, DoubleCircleIcon, StateGroupIcon } from "@plane/ui";
|
||||
// icons
|
||||
import { Plus } from "lucide-react";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
// fetch keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
|
||||
|
|
@ -30,11 +25,10 @@ export const IssueStateSelect: React.FC<Props> = ({ setIsOpen, value, onChange,
|
|||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
|
||||
const { data: stateGroups } = useSWR(
|
||||
const { data: states } = useSWR(
|
||||
workspaceSlug && projectId ? STATES_LIST(projectId) : null,
|
||||
workspaceSlug && projectId ? () => projectStateService.getStates(workspaceSlug as string, projectId) : null
|
||||
);
|
||||
const states = getStatesList(stateGroups);
|
||||
|
||||
const options = states?.map((state) => ({
|
||||
value: state.id,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import { ProjectStateService } from "services/project";
|
|||
// ui
|
||||
import { CustomSearchSelect, StateGroupIcon } from "@plane/ui";
|
||||
// helpers
|
||||
import { getStatesList } from "helpers/state.helper";
|
||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
// constants
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
|
|
@ -27,11 +26,10 @@ export const SidebarStateSelect: React.FC<Props> = ({ value, onChange, disabled
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId, inboxIssueId } = router.query;
|
||||
|
||||
const { data: stateGroups } = useSWR(
|
||||
const { data: states } = useSWR(
|
||||
workspaceSlug && projectId ? STATES_LIST(projectId as string) : null,
|
||||
workspaceSlug && projectId ? () => stateService.getStates(workspaceSlug as string, projectId as string) : null
|
||||
);
|
||||
const states = getStatesList(stateGroups);
|
||||
|
||||
const selectedOption = states?.find((s) => s.id === value);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,7 @@ export const ProfileStateDistribution: React.FC<Props> = ({ stateDistribution, u
|
|||
colors={(datum) => datum.data.color}
|
||||
tooltip={(datum) => (
|
||||
<div className="flex items-center gap-2 rounded-md border border-custom-border-200 bg-custom-background-90 p-2 text-xs">
|
||||
<span className="text-custom-text-200 capitalize">
|
||||
{datum.datum.label} issues:
|
||||
</span>{" "}
|
||||
<span className="text-custom-text-200 capitalize">{datum.datum.label} issues:</span>{" "}
|
||||
{datum.datum.value}
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -59,10 +57,7 @@ export const ProfileStateDistribution: React.FC<Props> = ({ stateDistribution, u
|
|||
<div className="flex items-center">
|
||||
<div className="space-y-4 w-full">
|
||||
{stateDistribution.map((group) => (
|
||||
<div
|
||||
key={group.state_group}
|
||||
className="flex items-center justify-between gap-2 text-xs"
|
||||
>
|
||||
<div key={group.state_group} className="flex items-center justify-between gap-2 text-xs">
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div
|
||||
className="h-2.5 w-2.5 rounded-sm"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
import { useState } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
// store
|
||||
import { observer } from "mobx-react-lite";
|
||||
// store
|
||||
import { useMobxStore } from "lib/mobx/store-provider";
|
||||
// ui
|
||||
import { Tooltip, StateGroupIcon } from "@plane/ui";
|
||||
// icons
|
||||
import { Pencil, X, ArrowDown, ArrowUp } from "lucide-react";
|
||||
|
||||
// helpers
|
||||
import { addSpaceIfCamelCase } from "helpers/string.helper";
|
||||
// types
|
||||
|
|
@ -30,7 +28,9 @@ export const ProjectSettingListItem: React.FC<Props> = observer((props) => {
|
|||
const { workspaceSlug, projectId } = router.query;
|
||||
|
||||
// store
|
||||
const { projectState: projectStateStore } = useMobxStore();
|
||||
const {
|
||||
projectState: { markStateAsDefault, moveStatePosition },
|
||||
} = useMobxStore();
|
||||
|
||||
// states
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
|
|
@ -41,18 +41,15 @@ export const ProjectSettingListItem: React.FC<Props> = observer((props) => {
|
|||
|
||||
const handleMakeDefault = () => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
setIsSubmitting(true);
|
||||
|
||||
projectStateStore.markStateAsDefault(workspaceSlug.toString(), projectId.toString(), state.id).finally(() => {
|
||||
markStateAsDefault(workspaceSlug.toString(), projectId.toString(), state.id).finally(() => {
|
||||
setIsSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleMove = (state: IState, direction: "up" | "down") => {
|
||||
if (!workspaceSlug || !projectId) return;
|
||||
|
||||
projectStateStore.moveStatePosition(workspaceSlug.toString(), projectId.toString(), state.id, direction, index);
|
||||
moveStatePosition(workspaceSlug.toString(), projectId.toString(), state.id, direction, index);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import { Loader } from "@plane/ui";
|
|||
// icons
|
||||
import { Plus } from "lucide-react";
|
||||
// helpers
|
||||
import { getStatesList, orderStateGroups } from "helpers/state.helper";
|
||||
import { orderStateGroups } from "helpers/state.helper";
|
||||
import { sortByField } from "helpers/array.helper";
|
||||
// fetch-keys
|
||||
import { STATES_LIST } from "constants/fetch-keys";
|
||||
|
||||
|
|
@ -20,41 +21,99 @@ export const ProjectSettingStateList: React.FC = observer(() => {
|
|||
const router = useRouter();
|
||||
const { workspaceSlug, projectId } = router.query;
|
||||
// store
|
||||
const { project: projectStore } = useMobxStore();
|
||||
const { currentProjectDetails } = projectStore;
|
||||
const {
|
||||
projectState: { groupedProjectStates, projectStates, fetchProjectStates },
|
||||
} = useMobxStore();
|
||||
// state
|
||||
const [activeGroup, setActiveGroup] = useState<StateGroup>(null);
|
||||
const [selectedState, setSelectedState] = useState<string | null>(null);
|
||||
const [selectDeleteState, setSelectDeleteState] = useState<string | null>(null);
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? "PROJECT_DETAILS" : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectDetails(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
);
|
||||
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? STATES_LIST(projectId.toString()) : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectStates(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchProjectStates(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
|
||||
// derived values
|
||||
const states = projectStore.projectStatesByGroups;
|
||||
const orderedStateGroups = orderStateGroups(states!);
|
||||
const statesList = getStatesList(orderedStateGroups);
|
||||
const orderedStateGroups = orderStateGroups(groupedProjectStates!);
|
||||
|
||||
console.log("groupedStates", groupedProjectStates);
|
||||
console.log("orderedStateGroups", orderedStateGroups);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DeleteStateModal
|
||||
isOpen={!!selectDeleteState}
|
||||
onClose={() => setSelectDeleteState(null)}
|
||||
data={statesList?.find((s) => s.id === selectDeleteState) ?? null}
|
||||
data={projectStates?.find((s) => s.id === selectDeleteState) ?? null}
|
||||
/>
|
||||
|
||||
<div className="space-y-8 py-6">
|
||||
{orderedStateGroups ? (
|
||||
<>
|
||||
{Object.keys(orderedStateGroups).map((group) => (
|
||||
<div key={group} className="flex flex-col gap-2">
|
||||
<div className="flex w-full justify-between">
|
||||
<h4 className="text-base font-medium text-custom-text-200 capitalize">{group}</h4>
|
||||
<button
|
||||
type="button"
|
||||
className="flex items-center gap-2 text-custom-primary-100 px-2 hover:text-custom-primary-200 outline-none"
|
||||
onClick={() => setActiveGroup(group as keyof StateGroup)}
|
||||
>
|
||||
<Plus className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 rounded">
|
||||
{group === activeGroup && (
|
||||
<CreateUpdateStateInline
|
||||
data={null}
|
||||
groupLength={orderedStateGroups[group].length}
|
||||
onClose={() => {
|
||||
setActiveGroup(null);
|
||||
setSelectedState(null);
|
||||
}}
|
||||
selectedGroup={group as keyof StateGroup}
|
||||
/>
|
||||
)}
|
||||
{sortByField(orderedStateGroups[group], "sequence").map((state, index) =>
|
||||
state.id !== selectedState ? (
|
||||
<ProjectSettingListItem
|
||||
key={state.id}
|
||||
index={index}
|
||||
state={state}
|
||||
statesList={projectStates ?? []}
|
||||
handleEditState={() => setSelectedState(state.id)}
|
||||
handleDeleteState={() => setSelectDeleteState(state.id)}
|
||||
/>
|
||||
) : (
|
||||
<div className="border-b-[0.5px] border-custom-border-200 last:border-b-0" key={state.id}>
|
||||
<CreateUpdateStateInline
|
||||
onClose={() => {
|
||||
setActiveGroup(null);
|
||||
setSelectedState(null);
|
||||
}}
|
||||
groupLength={orderedStateGroups[group].length}
|
||||
data={projectStates?.find((state) => state.id === selectedState) ?? null}
|
||||
selectedGroup={group as keyof StateGroup}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<Loader className="space-y-5 md:w-2/3">
|
||||
<Loader.Item height="40px" />
|
||||
<Loader.Item height="40px" />
|
||||
<Loader.Item height="40px" />
|
||||
<Loader.Item height="40px" />
|
||||
</Loader>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* <div className="space-y-8 py-6">
|
||||
{states && currentProjectDetails && orderedStateGroups ? (
|
||||
Object.keys(orderedStateGroups || {}).map((key) => {
|
||||
if (orderedStateGroups[key].length !== 0)
|
||||
|
|
@ -118,7 +177,7 @@ export const ProjectSettingStateList: React.FC = observer(() => {
|
|||
<Loader.Item height="40px" />
|
||||
</Loader>
|
||||
)}
|
||||
</div>
|
||||
</div> */}
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -73,9 +73,7 @@ const ContextMenu = ({ clickEvent, children, title, isOpen, setIsOpen }: Props)
|
|||
className={`fixed z-50 flex min-w-[8rem] flex-col items-stretch gap-1 rounded-md border border-custom-border-200 bg-custom-background-90 p-2 text-xs shadow-lg`}
|
||||
>
|
||||
{title && (
|
||||
<h4 className="border-b border-custom-border-200 px-1 py-1 pb-2 text-[0.8rem] font-medium">
|
||||
{title}
|
||||
</h4>
|
||||
<h4 className="border-b border-custom-border-200 px-1 py-1 pb-2 text-[0.8rem] font-medium">{title}</h4>
|
||||
)}
|
||||
{children}
|
||||
</div>
|
||||
|
|
@ -92,14 +90,7 @@ type MenuItemProps = {
|
|||
Icon?: any;
|
||||
};
|
||||
|
||||
const MenuItem: React.FC<MenuItemProps> = ({
|
||||
children,
|
||||
renderAs,
|
||||
href = "",
|
||||
onClick,
|
||||
className = "",
|
||||
Icon,
|
||||
}) => (
|
||||
const MenuItem: React.FC<MenuItemProps> = ({ children, renderAs, href = "", onClick, className = "", Icon }) => (
|
||||
<>
|
||||
{renderAs === "a" ? (
|
||||
<Link href={href}>
|
||||
|
|
|
|||
|
|
@ -32,9 +32,7 @@ export const BarGraph: React.FC<Props & TGraph & Omit<BarSvgProps<any>, "height"
|
|||
axisLeft={{
|
||||
tickSize: 0,
|
||||
tickPadding: 10,
|
||||
tickValues: customYAxisTickValues
|
||||
? generateYAxisTickValues(customYAxisTickValues)
|
||||
: undefined,
|
||||
tickValues: customYAxisTickValues ? generateYAxisTickValues(customYAxisTickValues) : undefined,
|
||||
}}
|
||||
axisBottom={{
|
||||
tickSize: 0,
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@ export const LineGraph: React.FC<Props & TGraph & LineSvgProps> = ({
|
|||
axisLeft={{
|
||||
tickSize: 0,
|
||||
tickPadding: 10,
|
||||
tickValues: customYAxisTickValues
|
||||
? generateYAxisTickValues(customYAxisTickValues)
|
||||
: undefined,
|
||||
tickValues: customYAxisTickValues ? generateYAxisTickValues(customYAxisTickValues) : undefined,
|
||||
}}
|
||||
theme={{ ...CHARTS_THEME, ...(theme ?? {}) }}
|
||||
animate
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@ import { TGraph } from "./types";
|
|||
// constants
|
||||
import { CHARTS_THEME, DEFAULT_MARGIN } from "constants/graph";
|
||||
|
||||
export const ScatterPlotGraph: React.FC<
|
||||
TGraph & Omit<ScatterPlotSvgProps<any>, "height" | "width">
|
||||
> = ({ height = "400px", width = "100%", margin, theme, ...rest }) => (
|
||||
export const ScatterPlotGraph: React.FC<TGraph & Omit<ScatterPlotSvgProps<any>, "height" | "width">> = ({
|
||||
height = "400px",
|
||||
width = "100%",
|
||||
margin,
|
||||
theme,
|
||||
...rest
|
||||
}) => (
|
||||
<div style={{ height, width }}>
|
||||
<ResponsiveScatterPlot
|
||||
margin={{ ...DEFAULT_MARGIN, ...(margin ?? {}) }}
|
||||
|
|
|
|||
|
|
@ -41,9 +41,7 @@ const HeadingSecondary: CustomComponent = ({ children }) => (
|
|||
<h3 className="text-base font-semibold text-custom-text-100">{children}</h3>
|
||||
);
|
||||
|
||||
const Paragraph: CustomComponent = ({ children }) => (
|
||||
<p className="text-sm text-custom-text-200">{children}</p>
|
||||
);
|
||||
const Paragraph: CustomComponent = ({ children }) => <p className="text-sm text-custom-text-200">{children}</p>;
|
||||
|
||||
const OrderedList: CustomComponent = ({ children }) => (
|
||||
<ol className="ml-8 mb-4 list-decimal text-sm text-custom-text-200">{children}</ol>
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ export const ProgressBar: React.FC<Props> = ({
|
|||
const DIRECTION = -1;
|
||||
// Rotation Calc
|
||||
const primaryRotationAngle = (maxValue - 1) * (360 / maxValue);
|
||||
const rotationAngle =
|
||||
-1 * DIRECTION * primaryRotationAngle + i * DIRECTION * primaryRotationAngle;
|
||||
const rotationAngle = -1 * DIRECTION * primaryRotationAngle + i * DIRECTION * primaryRotationAngle;
|
||||
const rotationTransformation = `rotate(${rotationAngle}, ${radius}, ${radius})`;
|
||||
const pieValue = calculatePieValue(maxValue);
|
||||
const dValue = generatePie(pieValue);
|
||||
|
|
|
|||
|
|
@ -74,9 +74,7 @@ export const TextArea: React.FC<Props> = ({
|
|||
: mode === "transparent"
|
||||
? "rounded border-none bg-transparent ring-0 transition-all focus:ring-1 focus:ring-theme"
|
||||
: ""
|
||||
} ${error ? "border-red-500" : ""} ${
|
||||
error && mode === "primary" ? "bg-red-100" : ""
|
||||
} ${className}`}
|
||||
} ${error ? "border-red-500" : ""} ${error && mode === "primary" ? "bg-red-100" : ""} ${className}`}
|
||||
{...rest}
|
||||
/>
|
||||
{error?.message && <div className="text-sm text-red-500">{error.message}</div>}
|
||||
|
|
|
|||
|
|
@ -30,11 +30,7 @@ export const ToggleSwitch: React.FC<Props> = (props) => {
|
|||
size === "sm" ? "h-2 w-2" : size === "md" ? "h-3 w-3" : "h-4 w-4"
|
||||
} transform rounded-full shadow ring-0 transition duration-200 ease-in-out ${
|
||||
value
|
||||
? (size === "sm"
|
||||
? "translate-x-3"
|
||||
: size === "md"
|
||||
? "translate-x-4"
|
||||
: "translate-x-5") + " bg-white"
|
||||
? (size === "sm" ? "translate-x-3" : size === "md" ? "translate-x-4" : "translate-x-5") + " bg-white"
|
||||
: "translate-x-0.5 bg-custom-background-90"
|
||||
} ${disabled ? "cursor-not-allowed" : ""}`}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const defaultValues: Partial<IProjectView> = {
|
|||
};
|
||||
|
||||
export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, handleClose, data, preLoadedData }) => {
|
||||
const { project: projectStore } = useMobxStore();
|
||||
const { project: projectStore, projectState: projectStateStore } = useMobxStore();
|
||||
|
||||
const {
|
||||
control,
|
||||
|
|
@ -138,7 +138,7 @@ export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, ha
|
|||
layoutDisplayFiltersOptions={ISSUE_DISPLAY_FILTERS_BY_LAYOUT.issues.list}
|
||||
labels={projectStore.projectLabels ?? undefined}
|
||||
members={projectStore.projectMembers?.map((m) => m.member) ?? undefined}
|
||||
states={projectStore.projectStatesByGroups ?? undefined}
|
||||
states={projectStateStore.projectStates ?? undefined}
|
||||
/>
|
||||
</FiltersDropdown>
|
||||
)}
|
||||
|
|
@ -152,7 +152,7 @@ export const ProjectViewForm: React.FC<Props> = observer(({ handleFormSubmit, ha
|
|||
handleRemoveFilter={() => {}}
|
||||
labels={projectStore.projectLabels ?? undefined}
|
||||
members={projectStore.projectMembers?.map((m) => m.member) ?? undefined}
|
||||
states={projectStore.projectStatesByGroups ?? undefined}
|
||||
states={projectStateStore.projectStates ?? undefined}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ export const IssuesPieChart: React.FC<Props> = ({ groupedIssues }) => (
|
|||
colors={(datum) => datum.data.color}
|
||||
tooltip={(datum) => (
|
||||
<div className="flex items-center gap-2 rounded-md border border-custom-border-200 bg-custom-background-90 p-2 text-xs">
|
||||
<span className="text-custom-text-200 capitalize">{datum.datum.label} issues:</span>{" "}
|
||||
{datum.datum.value}
|
||||
<span className="text-custom-text-200 capitalize">{datum.datum.label} issues:</span> {datum.datum.value}
|
||||
</div>
|
||||
)}
|
||||
margin={{
|
||||
|
|
@ -53,10 +52,7 @@ export const IssuesPieChart: React.FC<Props> = ({ groupedIssues }) => (
|
|||
<div className="flex sm:block items-center gap-3 flex-wrap justify-center sm:space-y-2 sm:self-end sm:justify-self-end sm:px-8 sm:pb-8">
|
||||
{groupedIssues?.map((cell) => (
|
||||
<div key={cell.state_group} className="flex items-center gap-2">
|
||||
<div
|
||||
className="h-2 w-2"
|
||||
style={{ backgroundColor: STATE_GROUP_COLORS[cell.state_group] }}
|
||||
/>
|
||||
<div className="h-2 w-2" style={{ backgroundColor: STATE_GROUP_COLORS[cell.state_group] }} />
|
||||
<div className="capitalize text-custom-text-200 text-xs whitespace-nowrap">
|
||||
{cell.state_group}- {cell.state_count}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,11 +9,7 @@ type Props = {
|
|||
handleInvitation: any;
|
||||
};
|
||||
|
||||
const SingleInvitation: React.FC<Props> = ({
|
||||
invitation,
|
||||
invitationsRespond,
|
||||
handleInvitation,
|
||||
}) => (
|
||||
const SingleInvitation: React.FC<Props> = ({ invitation, invitationsRespond, handleInvitation }) => (
|
||||
<li>
|
||||
<label
|
||||
className={`group relative flex cursor-pointer items-start space-x-3 border-2 border-transparent py-4`}
|
||||
|
|
@ -53,10 +49,7 @@ const SingleInvitation: React.FC<Props> = ({
|
|||
: "bg-custom-primary text-white"
|
||||
} text-sm px-4 py-2 border border-custom-border-200 rounded-3xl`}
|
||||
onClick={() => {
|
||||
handleInvitation(
|
||||
invitation,
|
||||
invitationsRespond.includes(invitation.id) ? "withdraw" : "accepted"
|
||||
);
|
||||
handleInvitation(invitation, invitationsRespond.includes(invitation.id) ? "withdraw" : "accepted");
|
||||
}}
|
||||
>
|
||||
{invitationsRespond.includes(invitation.id) ? "Invitation Accepted" : "Accept Invitation"}
|
||||
|
|
|
|||
|
|
@ -3,12 +3,7 @@ import { createContext, useCallback, useReducer } from "react";
|
|||
// components
|
||||
import ToastAlert from "components/toast-alert";
|
||||
// types
|
||||
import {
|
||||
IIssueFilterOptions,
|
||||
Properties,
|
||||
IWorkspaceViewProps,
|
||||
IIssueDisplayFilterOptions,
|
||||
} from "types";
|
||||
import { IIssueFilterOptions, Properties, IWorkspaceViewProps, IIssueDisplayFilterOptions } from "types";
|
||||
|
||||
export const profileIssuesContext = createContext<ContextType>({} as ContextType);
|
||||
|
||||
|
|
@ -117,9 +112,7 @@ export const reducer: ReducerFunctionType = (state, action) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const ProfileIssuesContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
export const ProfileIssuesContextProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [state, dispatch] = useReducer(reducer, initialState);
|
||||
|
||||
const setDisplayFilters = useCallback(
|
||||
|
|
@ -133,11 +126,7 @@ export const ProfileIssuesContextProvider: React.FC<{ children: React.ReactNode
|
|||
},
|
||||
});
|
||||
|
||||
if (
|
||||
displayFilter.layout &&
|
||||
displayFilter.layout === "kanban" &&
|
||||
state.display_filters?.group_by === null
|
||||
) {
|
||||
if (displayFilter.layout && displayFilter.layout === "kanban" && state.display_filters?.group_by === null) {
|
||||
dispatch({
|
||||
type: "SET_DISPLAY_FILTERS",
|
||||
payload: {
|
||||
|
|
@ -154,8 +143,7 @@ export const ProfileIssuesContextProvider: React.FC<{ children: React.ReactNode
|
|||
const setFilters = useCallback(
|
||||
(property: Partial<IIssueFilterOptions>) => {
|
||||
Object.keys(property).forEach((key) => {
|
||||
if (property[key as keyof typeof property]?.length === 0)
|
||||
property[key as keyof typeof property] = null;
|
||||
if (property[key as keyof typeof property]?.length === 0) property[key as keyof typeof property] = null;
|
||||
});
|
||||
|
||||
dispatch({
|
||||
|
|
|
|||
|
|
@ -72,11 +72,7 @@ export const ToastContextProvider: React.FC<{ children: React.ReactNode }> = ({
|
|||
}, []);
|
||||
|
||||
const setToastAlert = useCallback(
|
||||
(data: {
|
||||
title: string;
|
||||
type?: "success" | "error" | "warning" | "info";
|
||||
message?: string;
|
||||
}) => {
|
||||
(data: { title: string; type?: "success" | "error" | "warning" | "info"; message?: string }) => {
|
||||
const id = uuid();
|
||||
const { title, type, message } = data;
|
||||
dispatch({
|
||||
|
|
|
|||
|
|
@ -7,11 +7,7 @@ export const groupBy = (array: any[], key: string) => {
|
|||
}, {});
|
||||
};
|
||||
|
||||
export const orderArrayBy = (
|
||||
orgArray: any[],
|
||||
key: string,
|
||||
ordering: "ascending" | "descending" = "ascending"
|
||||
) => {
|
||||
export const orderArrayBy = (orgArray: any[], key: string, ordering: "ascending" | "descending" = "ascending") => {
|
||||
if (!orgArray || !Array.isArray(orgArray) || orgArray.length === 0) return [];
|
||||
|
||||
const array = [...orgArray];
|
||||
|
|
@ -53,3 +49,28 @@ export const checkIfArraysHaveSameElements = (arr1: any[] | null, arr2: any[] |
|
|||
|
||||
return arr1.length === arr2.length && arr1.every((e) => arr2.includes(e));
|
||||
};
|
||||
|
||||
type GroupedItems<T> = { [key: string]: T[] };
|
||||
|
||||
export const groupByField = <T>(array: T[], field: keyof T): GroupedItems<T> =>
|
||||
array.reduce((grouped: GroupedItems<T>, item: T) => {
|
||||
const key = String(item[field]);
|
||||
grouped[key] = (grouped[key] || []).concat(item);
|
||||
return grouped;
|
||||
}, {});
|
||||
|
||||
export const sortByField = (array: any[], field: string): any[] =>
|
||||
array.sort((a, b) => (a[field] < b[field] ? -1 : a[field] > b[field] ? 1 : 0));
|
||||
|
||||
export const orderGroupedDataByField = <T>(groupedData: GroupedItems<T>, orderBy: keyof T): GroupedItems<T> => {
|
||||
for (const key in groupedData) {
|
||||
if (groupedData.hasOwnProperty(key)) {
|
||||
groupedData[key] = groupedData[key].sort((a, b) => {
|
||||
if (a[orderBy] < b[orderBy]) return -1;
|
||||
if (a[orderBy] > b[orderBy]) return 1;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
return groupedData;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
export const getFileExtension = (filename: string) =>
|
||||
filename.slice(((filename.lastIndexOf(".") - 1) >>> 0) + 2);
|
||||
export const getFileExtension = (filename: string) => filename.slice(((filename.lastIndexOf(".") - 1) >>> 0) + 2);
|
||||
|
||||
export const getFileName = (fileName: string) => {
|
||||
const dotIndex = fileName.lastIndexOf(".");
|
||||
|
|
|
|||
|
|
@ -17,6 +17,4 @@ export const debounce = (func: any, wait: number, immediate: boolean = false) =>
|
|||
};
|
||||
};
|
||||
|
||||
export const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL
|
||||
? process.env.NEXT_PUBLIC_API_BASE_URL
|
||||
: "";
|
||||
export const API_BASE_URL = process.env.NEXT_PUBLIC_API_BASE_URL ? process.env.NEXT_PUBLIC_API_BASE_URL : "";
|
||||
|
|
|
|||
|
|
@ -41,13 +41,16 @@ export const groupReactions: (reactions: any[], key: string) => { [key: string]:
|
|||
reactions: any,
|
||||
key: string
|
||||
) => {
|
||||
const groupedReactions = reactions.reduce((acc: any, reaction: any) => {
|
||||
if (!acc[reaction[key]]) {
|
||||
acc[reaction[key]] = [];
|
||||
}
|
||||
acc[reaction[key]].push(reaction);
|
||||
return acc;
|
||||
}, {} as { [key: string]: any[] });
|
||||
const groupedReactions = reactions.reduce(
|
||||
(acc: any, reaction: any) => {
|
||||
if (!acc[reaction[key]]) {
|
||||
acc[reaction[key]] = [];
|
||||
}
|
||||
acc[reaction[key]].push(reaction);
|
||||
return acc;
|
||||
},
|
||||
{} as { [key: string]: any[] }
|
||||
);
|
||||
|
||||
return groupedReactions;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,27 +1,7 @@
|
|||
// types
|
||||
import { IState, IStateResponse } from "types";
|
||||
import { IStateResponse } from "types";
|
||||
|
||||
export const orderStateGroups = (
|
||||
unorderedStateGroups: IStateResponse | undefined
|
||||
): IStateResponse | undefined => {
|
||||
export const orderStateGroups = (unorderedStateGroups: IStateResponse | undefined): IStateResponse | undefined => {
|
||||
if (!unorderedStateGroups) return undefined;
|
||||
|
||||
return Object.assign(
|
||||
{ backlog: [], unstarted: [], started: [], completed: [], cancelled: [] },
|
||||
unorderedStateGroups
|
||||
);
|
||||
};
|
||||
|
||||
export const getStatesList = (stateGroups: IStateResponse | undefined): IState[] | undefined => {
|
||||
if (!stateGroups) return undefined;
|
||||
|
||||
// order the unordered state groups first
|
||||
const orderedStateGroups = orderStateGroups(stateGroups);
|
||||
|
||||
if (!orderedStateGroups) return undefined;
|
||||
|
||||
// extract states from the groups and return them
|
||||
return Object.keys(orderedStateGroups)
|
||||
.map((group) => [...orderedStateGroups[group].map((state: IState) => state)])
|
||||
.flat();
|
||||
return Object.assign({ backlog: [], unstarted: [], started: [], completed: [], cancelled: [] }, unorderedStateGroups);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
|||
const { children } = props;
|
||||
// store
|
||||
const {
|
||||
user: userStore,
|
||||
project: projectStore,
|
||||
cycle: cycleStore,
|
||||
module: moduleStore,
|
||||
projectViews: projectViewsStore,
|
||||
inbox: inboxStore,
|
||||
commandPalette: commandPaletteStore,
|
||||
user: { fetchUserProjectInfo, projectMemberInfo, hasPermissionToProject },
|
||||
project: { fetchProjectDetails, fetchProjectLabels, fetchProjectMembers, fetchProjectEstimates, workspaceProjects },
|
||||
projectState: { fetchProjectStates },
|
||||
cycle: { fetchCycles },
|
||||
module: { fetchModules },
|
||||
projectViews: { fetchAllViews },
|
||||
inbox: { fetchInboxesList, isInboxEnabled },
|
||||
commandPalette: { toggleCreateProjectModal },
|
||||
} = useMobxStore();
|
||||
// router
|
||||
const router = useRouter();
|
||||
|
|
@ -34,70 +35,54 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
|||
// fetching project details
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_DETAILS_${workspaceSlug.toString()}_${projectId.toString()}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectDetails(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchProjectDetails(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching user project member information
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_MEMBERS_ME_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => userStore.fetchUserProjectInfo(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchUserProjectInfo(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching project labels
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_LABELS_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectLabels(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchProjectLabels(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching project members
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_MEMBERS_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectMembers(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchProjectMembers(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching project states
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_STATES_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectStates(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchProjectStates(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching project estimates
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_ESTIMATES_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectStore.fetchProjectEstimates(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchProjectEstimates(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching project cycles
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_ALL_CYCLES_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => cycleStore.fetchCycles(workspaceSlug.toString(), projectId.toString(), "all")
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchCycles(workspaceSlug.toString(), projectId.toString(), "all") : null
|
||||
);
|
||||
// fetching project modules
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_MODULES_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId ? () => moduleStore.fetchModules(workspaceSlug.toString(), projectId.toString()) : null
|
||||
workspaceSlug && projectId ? () => fetchModules(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// fetching project views
|
||||
useSWR(
|
||||
workspaceSlug && projectId ? `PROJECT_VIEWS_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId
|
||||
? () => projectViewsStore.fetchAllViews(workspaceSlug.toString(), projectId.toString())
|
||||
: null
|
||||
workspaceSlug && projectId ? () => fetchAllViews(workspaceSlug.toString(), projectId.toString()) : null
|
||||
);
|
||||
// TODO: fetching project pages
|
||||
// fetching project inboxes if inbox is enabled
|
||||
useSWR(
|
||||
workspaceSlug && projectId && inboxStore.isInboxEnabled ? `PROJECT_INBOXES_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId && inboxStore.isInboxEnabled
|
||||
? () => inboxStore.fetchInboxesList(workspaceSlug.toString(), projectId.toString())
|
||||
workspaceSlug && projectId && isInboxEnabled ? `PROJECT_INBOXES_${workspaceSlug}_${projectId}` : null,
|
||||
workspaceSlug && projectId && isInboxEnabled
|
||||
? () => fetchInboxesList(workspaceSlug.toString(), projectId.toString())
|
||||
: null,
|
||||
{
|
||||
revalidateOnFocus: false,
|
||||
|
|
@ -105,11 +90,11 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
|||
}
|
||||
);
|
||||
|
||||
const projectsList = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : null;
|
||||
const projectsList = workspaceSlug ? workspaceProjects : null;
|
||||
const projectExists = projectId ? projectsList?.find((project) => project.id === projectId.toString()) : null;
|
||||
|
||||
// check if the project member apis is loading
|
||||
if (!userStore.projectMemberInfo && projectId && userStore.hasPermissionToProject[projectId.toString()] === null)
|
||||
if (!projectMemberInfo && projectId && hasPermissionToProject[projectId.toString()] === null)
|
||||
return (
|
||||
<div className="grid h-screen place-items-center p-4 bg-custom-background-100">
|
||||
<div className="flex flex-col items-center gap-3 text-center">
|
||||
|
|
@ -119,11 +104,10 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
|||
);
|
||||
|
||||
// check if the user don't have permission to access the project
|
||||
if (projectExists && projectId && userStore.hasPermissionToProject[projectId.toString()] === false)
|
||||
return <JoinProject />;
|
||||
if (projectExists && projectId && hasPermissionToProject[projectId.toString()] === false) return <JoinProject />;
|
||||
|
||||
// check if the project info is not found.
|
||||
if (!projectExists && projectId && userStore.hasPermissionToProject[projectId.toString()] === false)
|
||||
if (!projectExists && projectId && hasPermissionToProject[projectId.toString()] === false)
|
||||
return (
|
||||
<div className="container grid h-screen place-items-center bg-custom-background-100">
|
||||
<EmptyState
|
||||
|
|
@ -132,7 +116,7 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
|
|||
image={emptyProject}
|
||||
primaryButton={{
|
||||
text: "Create Project",
|
||||
onClick: () => commandPaletteStore.toggleCreateProjectModal(true),
|
||||
onClick: () => toggleCreateProjectModal(true),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -76,15 +76,12 @@ export const requiredWorkspaceAdmin = async (workspaceSlug: string, cookie?: str
|
|||
let memberDetail: IWorkspaceMember | null = null;
|
||||
|
||||
try {
|
||||
const data = await fetch(
|
||||
`${API_BASE_URL}/api/workspaces/${workspaceSlug}/workspace-members/me/`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
const data = await fetch(`${API_BASE_URL}/api/workspaces/${workspaceSlug}/workspace-members/me/`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
})
|
||||
.then((res) => res.json())
|
||||
.then((data) => data);
|
||||
|
||||
|
|
@ -143,9 +140,7 @@ export const homePageRedirect = async (cookie?: string) => {
|
|||
};
|
||||
}
|
||||
|
||||
const lastActiveWorkspace = workspaces.find(
|
||||
(workspace) => workspace.id === user.last_workspace_id
|
||||
);
|
||||
const lastActiveWorkspace = workspaces.find((workspace) => workspace.id === user.last_workspace_id);
|
||||
|
||||
if (lastActiveWorkspace) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ import Script from "next/script";
|
|||
|
||||
class MyDocument extends Document {
|
||||
render() {
|
||||
const isSessionRecorderEnabled = parseInt(
|
||||
process.env.NEXT_PUBLIC_ENABLE_SESSION_RECORDER || "0"
|
||||
);
|
||||
const isSessionRecorderEnabled = parseInt(process.env.NEXT_PUBLIC_ENABLE_SESSION_RECORDER || "0");
|
||||
|
||||
return (
|
||||
<Html>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue