fix: project states fixes (#2731)

* fix: project states fixes

* fix: states fixes

* fix: formating all files
This commit is contained in:
sriram veeraghanta 2023-11-08 20:31:46 +05:30 committed by GitHub
parent bd1a850f35
commit 20fb79567f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
156 changed files with 1585 additions and 1758 deletions

View file

@ -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);
}, []);

View file

@ -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>

View file

@ -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}`

View file

@ -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 ? (

View file

@ -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);

View file

@ -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) => {

View file

@ -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]));

View file

@ -231,7 +231,7 @@ export const CyclesListItem: FC<TCyclesListItem> = (props) => {
</button>
)}
<CustomMenu width="auto" ellipsis >
<CustomMenu width="auto" ellipsis>
{!isCompleted && (
<>
<CustomMenu.MenuItem onClick={handleEditCycle}>

View file

@ -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 && (

View file

@ -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;
};

View file

@ -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);

View file

@ -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);

View file

@ -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;
};

View file

@ -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);

View file

@ -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

View file

@ -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 = [];

View file

@ -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);

View file

@ -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">

View file

@ -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">

View file

@ -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">

View file

@ -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">

View file

@ -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">

View file

@ -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"

View file

@ -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"

View file

@ -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}

View file

@ -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}

View file

@ -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";

View file

@ -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}

View file

@ -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}

View file

@ -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

View file

@ -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} />;
};

View file

@ -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}

View file

@ -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}

View file

@ -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}

View file

@ -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}

View file

@ -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}

View file

@ -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"

View file

@ -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}

View file

@ -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;

View file

@ -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>

View file

@ -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}

View file

@ -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>
);

View file

@ -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>
);

View file

@ -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>
);

View file

@ -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>
);

View file

@ -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}>

View file

@ -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;

View file

@ -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) => {

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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>

View file

@ -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) => ({

View file

@ -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) => {

View file

@ -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;
};

View file

@ -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}

View file

@ -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}

View file

@ -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}

View file

@ -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}

View file

@ -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) => {

View file

@ -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;

View file

@ -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 && (
<>

View file

@ -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}
/>

View file

@ -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}

View file

@ -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"

View file

@ -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,

View file

@ -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);

View file

@ -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"

View file

@ -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 (

View file

@ -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> */}
</>
);
});

View file

@ -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}>

View file

@ -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,

View file

@ -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

View file

@ -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 ?? {}) }}

View file

@ -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>

View file

@ -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);

View file

@ -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>}

View file

@ -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" : ""}`}
/>

View file

@ -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>
)}

View file

@ -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>

View file

@ -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"}

View file

@ -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({

View file

@ -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({

View file

@ -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;
};

View file

@ -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(".");

View file

@ -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 : "";

View file

@ -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;
};

View file

@ -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);
};

View file

@ -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>

View file

@ -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 {

View file

@ -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