= ({ actionButton, type }) => {
{user ? (
You have signed in as {user.email}.
-
+
Sign in
{" "}
with different account that has access to this page.
@@ -52,7 +47,7 @@ export const NotAuthorizedView: React.FC = ({ actionButton, type }) => {
) : (
You need to{" "}
-
+
Sign in
{" "}
with an account that has access to this page.
diff --git a/apps/app/components/auth-screens/workspace/not-a-member.tsx b/apps/app/components/auth-screens/workspace/not-a-member.tsx
index 9627143ba..12bb3d850 100644
--- a/apps/app/components/auth-screens/workspace/not-a-member.tsx
+++ b/apps/app/components/auth-screens/workspace/not-a-member.tsx
@@ -1,44 +1,34 @@
import Link from "next/link";
-import { useRouter } from "next/router";
// layouts
import DefaultLayout from "layouts/default-layout";
// ui
import { PrimaryButton, SecondaryButton } from "components/ui";
-export const NotAWorkspaceMember = () => {
- const router = useRouter();
-
- return (
-
-
-
-
-
Not Authorized!
-
- You{"'"}re not a member of this workspace. Please contact the workspace admin to get
- an invitation or check your pending invitations.
-
-
-
+export const NotAWorkspaceMember = () => (
+
+
+
+
+
Not Authorized!
+
+ You{"'"}re not a member of this workspace. Please contact the workspace admin to get an
+ invitation or check your pending invitations.
+
+
+
-
- );
-};
+
+
+);
diff --git a/apps/app/components/breadcrumbs/index.tsx b/apps/app/components/breadcrumbs/index.tsx
index 98944fe37..240faefa2 100644
--- a/apps/app/components/breadcrumbs/index.tsx
+++ b/apps/app/components/breadcrumbs/index.tsx
@@ -3,6 +3,7 @@ import { useRouter } from "next/router";
import Link from "next/link";
// icons
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
+import { Icon } from "components/ui";
type BreadcrumbsProps = {
children: any;
@@ -16,10 +17,13 @@ const Breadcrumbs = ({ children }: BreadcrumbsProps) => {
{children}
diff --git a/apps/app/components/command-palette/change-issue-assignee.tsx b/apps/app/components/command-palette/change-issue-assignee.tsx
index 09f597e2e..56351335e 100644
--- a/apps/app/components/command-palette/change-issue-assignee.tsx
+++ b/apps/app/components/command-palette/change-issue-assignee.tsx
@@ -7,7 +7,7 @@ import { Command } from "cmdk";
// services
import issuesService from "services/issues.service";
// types
-import { IIssue } from "types";
+import { ICurrentUserResponse, IIssue } from "types";
// constants
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY, PROJECT_MEMBERS } from "constants/fetch-keys";
// icons
@@ -18,9 +18,10 @@ import { Avatar } from "components/ui";
type Props = {
setIsPaletteOpen: Dispatch
>;
issue: IIssue;
+ user: ICurrentUserResponse | undefined;
};
-export const ChangeIssueAssignee: React.FC = ({ setIsPaletteOpen, issue }) => {
+export const ChangeIssueAssignee: React.FC = ({ setIsPaletteOpen, issue, user }) => {
const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query;
@@ -57,18 +58,21 @@ export const ChangeIssueAssignee: React.FC = ({ setIsPaletteOpen, issue }
async (formData: Partial) => {
if (!workspaceSlug || !projectId || !issueId) return;
- mutate(
+ mutate(
ISSUE_DETAILS(issueId as string),
- (prevData: IIssue) => ({
- ...prevData,
- ...formData,
- }),
+ async (prevData) => {
+ if (!prevData) return prevData;
+ return {
+ ...prevData,
+ ...formData,
+ };
+ },
false
);
const payload = { ...formData };
await issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
.then(() => {
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
})
@@ -80,7 +84,7 @@ export const ChangeIssueAssignee: React.FC = ({ setIsPaletteOpen, issue }
);
const handleIssueAssignees = (assignee: string) => {
- const updatedAssignees = issue.assignees ?? [];
+ const updatedAssignees = issue.assignees_list ?? [];
if (updatedAssignees.includes(assignee)) {
updatedAssignees.splice(updatedAssignees.indexOf(assignee), 1);
diff --git a/apps/app/components/command-palette/change-issue-priority.tsx b/apps/app/components/command-palette/change-issue-priority.tsx
index b6eca1df8..2db03268d 100644
--- a/apps/app/components/command-palette/change-issue-priority.tsx
+++ b/apps/app/components/command-palette/change-issue-priority.tsx
@@ -7,7 +7,7 @@ import { Command } from "cmdk";
// services
import issuesService from "services/issues.service";
// types
-import { IIssue } from "types";
+import { ICurrentUserResponse, IIssue } from "types";
// constants
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
import { PRIORITIES } from "constants/project";
@@ -17,9 +17,10 @@ import { CheckIcon, getPriorityIcon } from "components/icons";
type Props = {
setIsPaletteOpen: Dispatch>;
issue: IIssue;
+ user: ICurrentUserResponse;
};
-export const ChangeIssuePriority: React.FC = ({ setIsPaletteOpen, issue }) => {
+export const ChangeIssuePriority: React.FC = ({ setIsPaletteOpen, issue, user }) => {
const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query;
@@ -27,18 +28,22 @@ export const ChangeIssuePriority: React.FC = ({ setIsPaletteOpen, issue }
async (formData: Partial) => {
if (!workspaceSlug || !projectId || !issueId) return;
- mutate(
+ mutate(
ISSUE_DETAILS(issueId as string),
- (prevData: IIssue) => ({
- ...prevData,
- ...formData,
- }),
+ async (prevData) => {
+ if (!prevData) return prevData;
+
+ return {
+ ...prevData,
+ ...formData,
+ };
+ },
false
);
const payload = { ...formData };
await issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
.then(() => {
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
})
diff --git a/apps/app/components/command-palette/change-issue-state.tsx b/apps/app/components/command-palette/change-issue-state.tsx
index 30ab68b63..0378df878 100644
--- a/apps/app/components/command-palette/change-issue-state.tsx
+++ b/apps/app/components/command-palette/change-issue-state.tsx
@@ -12,7 +12,7 @@ import { getStatesList } from "helpers/state.helper";
import issuesService from "services/issues.service";
import stateService from "services/state.service";
// types
-import { IIssue } from "types";
+import { ICurrentUserResponse, IIssue } from "types";
// fetch keys
import { ISSUE_DETAILS, PROJECT_ISSUES_ACTIVITY, STATES_LIST } from "constants/fetch-keys";
// icons
@@ -21,9 +21,10 @@ import { CheckIcon, getStateGroupIcon } from "components/icons";
type Props = {
setIsPaletteOpen: Dispatch>;
issue: IIssue;
+ user: ICurrentUserResponse | undefined;
};
-export const ChangeIssueState: React.FC = ({ setIsPaletteOpen, issue }) => {
+export const ChangeIssueState: React.FC = ({ setIsPaletteOpen, issue, user }) => {
const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query;
@@ -39,18 +40,21 @@ export const ChangeIssueState: React.FC = ({ setIsPaletteOpen, issue }) =
async (formData: Partial) => {
if (!workspaceSlug || !projectId || !issueId) return;
- mutate(
+ mutate(
ISSUE_DETAILS(issueId as string),
- (prevData: IIssue) => ({
- ...prevData,
- ...formData,
- }),
+ async (prevData) => {
+ if (!prevData) return prevData;
+ return {
+ ...prevData,
+ ...formData,
+ };
+ },
false
);
const payload = { ...formData };
await issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
.then(() => {
mutateIssueDetails();
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
diff --git a/apps/app/components/command-palette/command-pallette.tsx b/apps/app/components/command-palette/command-pallette.tsx
index bed84f5ad..ff889898e 100644
--- a/apps/app/components/command-palette/command-pallette.tsx
+++ b/apps/app/components/command-palette/command-pallette.tsx
@@ -120,18 +120,23 @@ export const CommandPalette: React.FC = () => {
async (formData: Partial) => {
if (!workspaceSlug || !projectId || !issueId) return;
- mutate(
+ mutate(
ISSUE_DETAILS(issueId as string),
- (prevData: IIssue) => ({
- ...prevData,
- ...formData,
- }),
+
+ (prevData) => {
+ if (!prevData) return prevData;
+
+ return {
+ ...prevData,
+ ...formData,
+ };
+ },
false
);
const payload = { ...formData };
await issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId as string, payload, user)
.then(() => {
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
mutate(ISSUE_DETAILS(issueId as string));
@@ -325,25 +330,33 @@ export const CommandPalette: React.FC = () => {
<>
{workspaceSlug && (
-
+
)}
{projectId && (
<>
setIsCreateCycleModalOpen(false)}
+ user={user}
/>
setIsCreateViewModalOpen(false)}
isOpen={isCreateViewModalOpen}
+ user={user}
/>
setIsCreateUpdatePageModalOpen(false)}
+ user={user}
/>
>
)}
@@ -352,6 +365,7 @@ export const CommandPalette: React.FC = () => {
handleClose={() => setDeleteIssueModal(false)}
isOpen={deleteIssueModal}
data={issueDetails}
+ user={user}
/>
)}
@@ -362,6 +376,7 @@ export const CommandPalette: React.FC = () => {
{
>
)}
@@ -856,12 +872,14 @@ export const CommandPalette: React.FC = () => {
)}
{page === "change-issue-assignee" && issueDetails && (
)}
{page === "change-interface-theme" && (
diff --git a/apps/app/components/core/board-view/all-boards.tsx b/apps/app/components/core/board-view/all-boards.tsx
index 495cee0a5..3e67e86b5 100644
--- a/apps/app/components/core/board-view/all-boards.tsx
+++ b/apps/app/components/core/board-view/all-boards.tsx
@@ -5,7 +5,7 @@ import { SingleBoard } from "components/core/board-view/single-board";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
// types
-import { IIssue, IState, UserAuth } from "types";
+import { ICurrentUserResponse, IIssue, IState, UserAuth } from "types";
import { getStateGroupIcon } from "components/icons";
type Props = {
@@ -19,6 +19,7 @@ type Props = {
handleTrashBox: (isDragging: boolean) => void;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
isCompleted?: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -33,6 +34,7 @@ export const AllBoards: React.FC = ({
handleTrashBox,
removeIssue,
isCompleted = false,
+ user,
userAuth,
}) => {
const {
@@ -65,6 +67,7 @@ export const AllBoards: React.FC = ({
handleTrashBox={handleTrashBox}
removeIssue={removeIssue}
isCompleted={isCompleted}
+ user={user}
userAuth={userAuth}
/>
);
diff --git a/apps/app/components/core/board-view/single-board.tsx b/apps/app/components/core/board-view/single-board.tsx
index 16fe0e887..f7816cd5b 100644
--- a/apps/app/components/core/board-view/single-board.tsx
+++ b/apps/app/components/core/board-view/single-board.tsx
@@ -17,7 +17,7 @@ import { PlusIcon } from "@heroicons/react/24/outline";
// helpers
import { replaceUnderscoreIfSnakeCase } from "helpers/string.helper";
// types
-import { IIssue, IState, UserAuth } from "types";
+import { ICurrentUserResponse, IIssue, IState, UserAuth } from "types";
type Props = {
type?: "issue" | "cycle" | "module";
@@ -31,6 +31,7 @@ type Props = {
handleTrashBox: (isDragging: boolean) => void;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
isCompleted?: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -46,6 +47,7 @@ export const SingleBoard: React.FC = ({
handleTrashBox,
removeIssue,
isCompleted = false,
+ user,
userAuth,
}) => {
// collapse/expand
@@ -129,6 +131,7 @@ export const SingleBoard: React.FC = ({
removeIssue(issue.bridge_id, issue.id);
}}
isCompleted={isCompleted}
+ user={user}
userAuth={userAuth}
/>
)}
diff --git a/apps/app/components/core/board-view/single-issue.tsx b/apps/app/components/core/board-view/single-issue.tsx
index 7f8a89aa2..e2d530153 100644
--- a/apps/app/components/core/board-view/single-issue.tsx
+++ b/apps/app/components/core/board-view/single-issue.tsx
@@ -44,7 +44,7 @@ import { LayerDiagonalIcon } from "components/icons";
import { handleIssuesMutation } from "constants/issue";
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
// types
-import { IIssue, Properties, TIssueGroupByOptions, UserAuth } from "types";
+import { ICurrentUserResponse, IIssue, Properties, TIssueGroupByOptions, UserAuth } from "types";
// fetch-keys
import {
CYCLE_DETAILS,
@@ -69,6 +69,7 @@ type Props = {
handleDeleteIssue: (issue: IIssue) => void;
handleTrashBox: (isDragging: boolean) => void;
isCompleted?: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -87,6 +88,7 @@ export const SingleBoardIssue: React.FC = ({
handleDeleteIssue,
handleTrashBox,
isCompleted = false,
+ user,
userAuth,
}) => {
// context menu
@@ -170,7 +172,7 @@ export const SingleBoardIssue: React.FC = ({
}
issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId, formData)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId, formData, user)
.then(() => {
if (cycleId) {
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
@@ -342,6 +344,7 @@ export const SingleBoardIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
isNotAllowed={isNotAllowed}
+ user={user}
selfPositioned
/>
)}
@@ -350,6 +353,7 @@ export const SingleBoardIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
isNotAllowed={isNotAllowed}
+ user={user}
selfPositioned
/>
)}
@@ -357,6 +361,7 @@ export const SingleBoardIssue: React.FC = ({
)}
@@ -384,6 +389,7 @@ export const SingleBoardIssue: React.FC = ({
partialUpdateIssue={partialUpdateIssue}
isNotAllowed={isNotAllowed}
tooltipPosition="left"
+ user={user}
selfPositioned
/>
)}
@@ -392,6 +398,7 @@ export const SingleBoardIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
isNotAllowed={isNotAllowed}
+ user={user}
selfPositioned
/>
)}
diff --git a/apps/app/components/core/bulk-delete-issues-modal.tsx b/apps/app/components/core/bulk-delete-issues-modal.tsx
index 7fe2181f6..603efe8e3 100644
--- a/apps/app/components/core/bulk-delete-issues-modal.tsx
+++ b/apps/app/components/core/bulk-delete-issues-modal.tsx
@@ -18,7 +18,7 @@ import { DangerButton, SecondaryButton } from "components/ui";
import { MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { LayerDiagonalIcon } from "components/icons";
// types
-import { IIssue } from "types";
+import { ICurrentUserResponse, IIssue } from "types";
// fetch keys
import { PROJECT_ISSUES_LIST } from "constants/fetch-keys";
@@ -29,9 +29,10 @@ type FormInput = {
type Props = {
isOpen: boolean;
setIsOpen: React.Dispatch>;
+ user: ICurrentUserResponse | undefined;
};
-export const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen }) => {
+export const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen, user }) => {
const [query, setQuery] = useState("");
const router = useRouter();
@@ -91,9 +92,14 @@ export const BulkDeleteIssuesModal: React.FC = ({ isOpen, setIsOpen }) =>
if (workspaceSlug && projectId) {
await issuesServices
- .bulkDeleteIssues(workspaceSlug as string, projectId as string, {
- issue_ids: data.delete_issue_ids,
- })
+ .bulkDeleteIssues(
+ workspaceSlug as string,
+ projectId as string,
+ {
+ issue_ids: data.delete_issue_ids,
+ },
+ user
+ )
.then((res) => {
setToastAlert({
title: "Success",
diff --git a/apps/app/components/core/calendar-view/calendar.tsx b/apps/app/components/core/calendar-view/calendar.tsx
index ce453f898..fa29eb9f7 100644
--- a/apps/app/components/core/calendar-view/calendar.tsx
+++ b/apps/app/components/core/calendar-view/calendar.tsx
@@ -24,7 +24,7 @@ import {
formatDate,
} from "helpers/calendar.helper";
// types
-import { ICalendarRange, IIssue, UserAuth } from "types";
+import { ICalendarRange, ICurrentUserResponse, IIssue, UserAuth } from "types";
// fetch-keys
import {
CYCLE_ISSUES_WITH_PARAMS,
@@ -38,6 +38,7 @@ type Props = {
handleDeleteIssue: (issue: IIssue) => void;
addIssueToDate: (date: string) => void;
isCompleted: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -46,6 +47,7 @@ export const CalendarView: React.FC = ({
handleDeleteIssue,
addIssueToDate,
isCompleted = false,
+ user,
userAuth,
}) => {
const [showWeekEnds, setShowWeekEnds] = useState(false);
@@ -134,9 +136,15 @@ export const CalendarView: React.FC = ({
);
issuesService
- .patchIssue(workspaceSlug as string, projectId as string, draggableId, {
- target_date: destination?.droppableId,
- })
+ .patchIssue(
+ workspaceSlug as string,
+ projectId as string,
+ draggableId,
+ {
+ target_date: destination?.droppableId,
+ },
+ user
+ )
.then(() => mutate(fetchKey));
};
@@ -219,6 +227,7 @@ export const CalendarView: React.FC = ({
addIssueToDate={addIssueToDate}
isMonthlyView={isMonthlyView}
showWeekEnds={showWeekEnds}
+ user={user}
isNotAllowed={isNotAllowed}
/>
))}
diff --git a/apps/app/components/core/calendar-view/single-date.tsx b/apps/app/components/core/calendar-view/single-date.tsx
index fd552188c..2dbfe5dfd 100644
--- a/apps/app/components/core/calendar-view/single-date.tsx
+++ b/apps/app/components/core/calendar-view/single-date.tsx
@@ -10,7 +10,7 @@ import { PlusSmallIcon } from "@heroicons/react/24/outline";
// helper
import { formatDate } from "helpers/calendar.helper";
// types
-import { IIssue } from "types";
+import { ICurrentUserResponse, IIssue } from "types";
type Props = {
handleEditIssue: (issue: IIssue) => void;
@@ -23,6 +23,7 @@ type Props = {
addIssueToDate: (date: string) => void;
isMonthlyView: boolean;
showWeekEnds: boolean;
+ user: ICurrentUserResponse | undefined;
isNotAllowed: boolean;
};
@@ -34,6 +35,7 @@ export const SingleCalendarDate: React.FC = ({
addIssueToDate,
isMonthlyView,
showWeekEnds,
+ user,
isNotAllowed,
}) => {
const [showAllIssues, setShowAllIssues] = useState(false);
@@ -72,6 +74,7 @@ export const SingleCalendarDate: React.FC = ({
issue={issue}
handleEditIssue={handleEditIssue}
handleDeleteIssue={handleDeleteIssue}
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
diff --git a/apps/app/components/core/calendar-view/single-issue.tsx b/apps/app/components/core/calendar-view/single-issue.tsx
index 9102f7338..4fa9def3b 100644
--- a/apps/app/components/core/calendar-view/single-issue.tsx
+++ b/apps/app/components/core/calendar-view/single-issue.tsx
@@ -28,7 +28,7 @@ import { LayerDiagonalIcon } from "components/icons";
// helper
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
// type
-import { IIssue } from "types";
+import { ICurrentUserResponse, IIssue } from "types";
// fetch-keys
import {
CYCLE_ISSUES_WITH_PARAMS,
@@ -44,6 +44,7 @@ type Props = {
provided: DraggableProvided;
snapshot: DraggableStateSnapshot;
issue: IIssue;
+ user: ICurrentUserResponse | undefined;
isNotAllowed: boolean;
};
@@ -54,6 +55,7 @@ export const SingleCalendarIssue: React.FC = ({
provided,
snapshot,
issue,
+ user,
isNotAllowed,
}) => {
const router = useRouter();
@@ -95,7 +97,7 @@ export const SingleCalendarIssue: React.FC = ({
);
issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId as string, formData, user)
.then(() => {
mutate(fetchKey);
})
@@ -183,6 +185,7 @@ export const SingleCalendarIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="left"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
@@ -192,6 +195,7 @@ export const SingleCalendarIssue: React.FC = ({
partialUpdateIssue={partialUpdateIssue}
position="left"
isNotAllowed={isNotAllowed}
+ user={user}
/>
)}
@@ -199,6 +203,7 @@ export const SingleCalendarIssue: React.FC = ({
)}
@@ -227,6 +232,7 @@ export const SingleCalendarIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="left"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
@@ -235,6 +241,7 @@ export const SingleCalendarIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="left"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
diff --git a/apps/app/components/core/feeds.tsx b/apps/app/components/core/feeds.tsx
index bd0e4c6bf..cce482da5 100644
--- a/apps/app/components/core/feeds.tsx
+++ b/apps/app/components/core/feeds.tsx
@@ -1,5 +1,6 @@
import React from "react";
-import Image from "next/image";
+
+import Link from "next/link";
// icons
import {
@@ -22,7 +23,6 @@ import { renderShortNumericDateFormat, timeAgo } from "helpers/date-time.helper"
import { addSpaceIfCamelCase } from "helpers/string.helper";
// types
import RemirrorRichTextEditor from "components/rich-text-editor";
-import Link from "next/link";
const activityDetails: {
[key: string]: {
@@ -206,7 +206,7 @@ export const Feeds: React.FC = ({ activities }) => (
{activity.actor_detail.avatar && activity.actor_detail.avatar !== "" ? (
-
= ({ activities }) => (
activityDetails[activity.field as keyof typeof activityDetails]?.icon
) : activity.actor_detail.avatar &&
activity.actor_detail.avatar !== "" ? (
- = ({
const router = useRouter();
const { workspaceSlug } = router.query;
+ const { user } = useUserAuth();
+
const editorRef = useRef(null);
const { setToastAlert } = useToast();
@@ -97,10 +100,15 @@ export const GptAssistantModal: React.FC = ({
}
await aiService
- .createGptTask(workspaceSlug as string, projectId as string, {
- prompt: content && content !== "" ? content : htmlContent ?? "",
- task: formData.task,
- })
+ .createGptTask(
+ workspaceSlug as string,
+ projectId as string,
+ {
+ prompt: content && content !== "" ? content : htmlContent ?? "",
+ task: formData.task,
+ },
+ user
+ )
.then((res) => {
setResponse(res.response_html);
setFocus("task");
@@ -190,10 +198,15 @@ export const GptAssistantModal: React.FC = ({
if (block)
trackEventServices.trackUseGPTResponseEvent(
block,
- "USE_GPT_RESPONSE_IN_PAGE_BLOCK"
+ "USE_GPT_RESPONSE_IN_PAGE_BLOCK",
+ user
);
else if (issue)
- trackEventServices.trackUseGPTResponseEvent(issue, "USE_GPT_RESPONSE_IN_ISSUE");
+ trackEventServices.trackUseGPTResponseEvent(
+ issue,
+ "USE_GPT_RESPONSE_IN_ISSUE",
+ user
+ );
}}
>
Use this response
diff --git a/apps/app/components/core/image-picker-popover.tsx b/apps/app/components/core/image-picker-popover.tsx
index 8b2edf3fb..380c6f356 100644
--- a/apps/app/components/core/image-picker-popover.tsx
+++ b/apps/app/components/core/image-picker-popover.tsx
@@ -1,8 +1,5 @@
import React, { useEffect, useState, useRef } from "react";
-// next
-import Image from "next/image";
-
// swr
import useSWR from "swr";
@@ -107,12 +104,7 @@ export const ImagePickerPopover: React.FC = ({ label, value, onChange })
onChange={(e) => setFormData({ ...formData, search: e.target.value })}
placeholder="Search for images"
/>
- setSearchParams(formData.search)}
- className="bg-indigo-600"
- size="sm"
- >
+ setSearchParams(formData.search)} size="sm">
Search
@@ -123,12 +115,10 @@ export const ImagePickerPopover: React.FC
= ({ label, value, onChange })
key={image.id}
className="relative col-span-2 aspect-video md:col-span-1"
>
- {
setIsOpen(false);
onChange(image.urls.regular);
diff --git a/apps/app/components/core/issues-view.tsx b/apps/app/components/core/issues-view.tsx
index cc0672843..bfa6b9f46 100644
--- a/apps/app/components/core/issues-view.tsx
+++ b/apps/app/components/core/issues-view.tsx
@@ -17,6 +17,7 @@ import { useProjectMyMembership } from "contexts/project-member.context";
// hooks
import useToast from "hooks/use-toast";
import useIssuesView from "hooks/use-issues-view";
+import useUserAuth from "hooks/use-user-auth";
// components
import { AllLists, AllBoards, FilterList, CalendarView, GanttChartView } from "components/core";
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
@@ -89,6 +90,8 @@ export const IssuesView: React.FC = ({
const { memberRole } = useProjectMyMembership();
+ const { user } = useUserAuth();
+
const { setToastAlert } = useToast();
const {
@@ -220,11 +223,17 @@ export const IssuesView: React.FC = ({
// patch request
issuesService
- .patchIssue(workspaceSlug as string, projectId as string, draggedItem.id, {
- priority: draggedItem.priority,
- state: draggedItem.state,
- sort_order: draggedItem.sort_order,
- })
+ .patchIssue(
+ workspaceSlug as string,
+ projectId as string,
+ draggedItem.id,
+ {
+ priority: draggedItem.priority,
+ state: draggedItem.state,
+ sort_order: draggedItem.sort_order,
+ },
+ user
+ )
.then((response) => {
const sourceStateBeforeDrag = states.find((state) => state.name === source.droppableId);
@@ -232,14 +241,17 @@ export const IssuesView: React.FC = ({
sourceStateBeforeDrag?.group !== "completed" &&
response?.state_detail?.group === "completed"
)
- trackEventServices.trackIssueMarkedAsDoneEvent({
- workspaceSlug,
- workspaceId: draggedItem.workspace,
- projectName: draggedItem.project_detail.name,
- projectIdentifier: draggedItem.project_detail.identifier,
- projectId,
- issueId: draggedItem.id,
- });
+ trackEventServices.trackIssueMarkedAsDoneEvent(
+ {
+ workspaceSlug,
+ workspaceId: draggedItem.workspace,
+ projectName: draggedItem.project_detail.name,
+ projectIdentifier: draggedItem.project_detail.identifier,
+ projectId,
+ issueId: draggedItem.id,
+ },
+ user
+ );
if (cycleId) {
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
@@ -419,6 +431,7 @@ export const IssuesView: React.FC = ({
isOpen={createViewModal !== null}
handleClose={() => setCreateViewModal(null)}
preLoadedData={createViewModal}
+ user={user}
/>
= ({
handleClose={() => setDeleteIssueModal(false)}
isOpen={deleteIssueModal}
data={issueToDelete}
+ user={user}
/>
setTransferIssuesModal(false)}
@@ -508,6 +522,7 @@ export const IssuesView: React.FC = ({
: null
}
isCompleted={isCompleted}
+ user={user}
userAuth={memberRole}
/>
) : issueView === "kanban" ? (
@@ -528,6 +543,7 @@ export const IssuesView: React.FC = ({
: null
}
isCompleted={isCompleted}
+ user={user}
userAuth={memberRole}
/>
) : issueView === "calendar" ? (
@@ -536,6 +552,7 @@ export const IssuesView: React.FC = ({
handleDeleteIssue={handleDeleteIssue}
addIssueToDate={addIssueToDate}
isCompleted={isCompleted}
+ user={user}
userAuth={memberRole}
/>
) : (
diff --git a/apps/app/components/core/list-view/all-lists.tsx b/apps/app/components/core/list-view/all-lists.tsx
index d8fa8b9ee..fd063728a 100644
--- a/apps/app/components/core/list-view/all-lists.tsx
+++ b/apps/app/components/core/list-view/all-lists.tsx
@@ -3,7 +3,7 @@ import useIssuesView from "hooks/use-issues-view";
// components
import { SingleList } from "components/core/list-view/single-list";
// types
-import { IIssue, IState, UserAuth } from "types";
+import { ICurrentUserResponse, IIssue, IState, UserAuth } from "types";
// types
type Props = {
@@ -16,6 +16,7 @@ type Props = {
openIssuesListModal?: (() => void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
isCompleted?: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -29,6 +30,7 @@ export const AllLists: React.FC = ({
handleDeleteIssue,
removeIssue,
isCompleted = false,
+ user,
userAuth,
}) => {
const { groupedByIssues, groupByProperty: selectedGroup, showEmptyGroups } = useIssuesView();
@@ -58,6 +60,7 @@ export const AllLists: React.FC = ({
openIssuesListModal={type !== "issue" ? openIssuesListModal : null}
removeIssue={removeIssue}
isCompleted={isCompleted}
+ user={user}
userAuth={userAuth}
/>
);
diff --git a/apps/app/components/core/list-view/single-issue.tsx b/apps/app/components/core/list-view/single-issue.tsx
index 6f6a5ab4f..ea4ebc811 100644
--- a/apps/app/components/core/list-view/single-issue.tsx
+++ b/apps/app/components/core/list-view/single-issue.tsx
@@ -36,7 +36,7 @@ import { LayerDiagonalIcon } from "components/icons";
import { copyTextToClipboard, truncateText } from "helpers/string.helper";
import { handleIssuesMutation } from "constants/issue";
// types
-import { IIssue, Properties, UserAuth } from "types";
+import { ICurrentUserResponse, IIssue, Properties, UserAuth } from "types";
// fetch-keys
import {
CYCLE_DETAILS,
@@ -57,6 +57,7 @@ type Props = {
removeIssue?: (() => void) | null;
handleDeleteIssue: (issue: IIssue) => void;
isCompleted?: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -71,6 +72,7 @@ export const SingleListIssue: React.FC = ({
groupTitle,
handleDeleteIssue,
isCompleted = false,
+ user,
userAuth,
}) => {
// context menu
@@ -141,7 +143,7 @@ export const SingleListIssue: React.FC = ({
);
issuesService
- .patchIssue(workspaceSlug as string, projectId as string, issueId, formData)
+ .patchIssue(workspaceSlug as string, projectId as string, issueId, formData, user)
.then(() => {
if (cycleId) {
mutate(CYCLE_ISSUES_WITH_PARAMS(cycleId as string, params));
@@ -241,6 +243,7 @@ export const SingleListIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="right"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
@@ -249,6 +252,7 @@ export const SingleListIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="right"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
@@ -256,6 +260,7 @@ export const SingleListIssue: React.FC = ({
)}
@@ -284,6 +289,7 @@ export const SingleListIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="right"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
@@ -292,6 +298,7 @@ export const SingleListIssue: React.FC = ({
issue={issue}
partialUpdateIssue={partialUpdateIssue}
position="right"
+ user={user}
isNotAllowed={isNotAllowed}
/>
)}
diff --git a/apps/app/components/core/list-view/single-list.tsx b/apps/app/components/core/list-view/single-list.tsx
index dd5ffb110..a8c6e4a51 100644
--- a/apps/app/components/core/list-view/single-list.tsx
+++ b/apps/app/components/core/list-view/single-list.tsx
@@ -19,7 +19,14 @@ import { getPriorityIcon, getStateGroupIcon } from "components/icons";
// helpers
import { addSpaceIfCamelCase } from "helpers/string.helper";
// types
-import { IIssue, IIssueLabels, IState, TIssueGroupByOptions, UserAuth } from "types";
+import {
+ ICurrentUserResponse,
+ IIssue,
+ IIssueLabels,
+ IState,
+ TIssueGroupByOptions,
+ UserAuth,
+} from "types";
// fetch-keys
import { PROJECT_ISSUE_LABELS, PROJECT_MEMBERS } from "constants/fetch-keys";
@@ -39,6 +46,7 @@ type Props = {
openIssuesListModal?: (() => void) | null;
removeIssue: ((bridgeId: string, issueId: string) => void) | null;
isCompleted?: boolean;
+ user: ICurrentUserResponse | undefined;
userAuth: UserAuth;
};
@@ -56,6 +64,7 @@ export const SingleList: React.FC = ({
openIssuesListModal,
removeIssue,
isCompleted = false,
+ user,
userAuth,
}) => {
const router = useRouter();
@@ -208,6 +217,7 @@ export const SingleList: React.FC = ({
removeIssue(issue.bridge_id, issue.id);
}}
isCompleted={isCompleted}
+ user={user}
userAuth={userAuth}
/>
))
diff --git a/apps/app/components/cycles/active-cycle-details.tsx b/apps/app/components/cycles/active-cycle-details.tsx
index 65c2e8b1b..21f37e5a6 100644
--- a/apps/app/components/cycles/active-cycle-details.tsx
+++ b/apps/app/components/cycles/active-cycle-details.tsx
@@ -1,7 +1,6 @@
import React from "react";
import Link from "next/link";
-import Image from "next/image";
import { useRouter } from "next/router";
import useSWR, { mutate } from "swr";
@@ -40,25 +39,12 @@ import {
} from "helpers/date-time.helper";
import { truncateText } from "helpers/string.helper";
// types
-import {
- CompletedCyclesResponse,
- CurrentAndUpcomingCyclesResponse,
- DraftCyclesResponse,
- ICycle,
- IIssue,
-} from "types";
+import { ICycle, IIssue } from "types";
// fetch-keys
-import {
- CYCLE_COMPLETE_LIST,
- CYCLE_CURRENT_AND_UPCOMING_LIST,
- CYCLE_DETAILS,
- CYCLE_DRAFT_LIST,
- CYCLE_ISSUES,
-} from "constants/fetch-keys";
+import { CURRENT_CYCLE_LIST, CYCLES_LIST, CYCLE_ISSUES_WITH_PARAMS } from "constants/fetch-keys";
type TSingleStatProps = {
cycle: ICycle;
- isCompleted?: boolean;
};
const stateGroups = [
@@ -89,7 +75,7 @@ const stateGroups = [
},
];
-export const ActiveCycleDetails: React.FC = ({ cycle, isCompleted = false }) => {
+export const ActiveCycleDetails: React.FC = ({ cycle }) => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
@@ -111,51 +97,18 @@ export const ActiveCycleDetails: React.FC = ({ cycle, isComple
const handleAddToFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return;
- switch (cycleStatus) {
- case "current":
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => ({
- current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => ({
- completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "draft":
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => ({
- draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- }
+ mutate(
+ CURRENT_CYCLE_LIST(projectId as string),
+ (prevData) =>
+ (prevData ?? []).map((c) => ({
+ ...c,
+ is_favorite: c.id === cycle.id ? true : c.is_favorite,
+ })),
+ false
+ );
+
mutate(
- CYCLE_DETAILS(projectId as string),
+ CYCLES_LIST(projectId as string),
(prevData: any) =>
(prevData ?? []).map((c: any) => ({
...c,
@@ -180,51 +133,18 @@ export const ActiveCycleDetails: React.FC = ({ cycle, isComple
const handleRemoveFromFavorites = () => {
if (!workspaceSlug || !projectId || !cycle) return;
- switch (cycleStatus) {
- case "current":
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => ({
- current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => ({
- completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "draft":
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => ({
- draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- }
+ mutate(
+ CURRENT_CYCLE_LIST(projectId as string),
+ (prevData) =>
+ (prevData ?? []).map((c) => ({
+ ...c,
+ is_favorite: c.id === cycle.id ? false : c.is_favorite,
+ })),
+ false
+ );
+
mutate(
- CYCLE_DETAILS(projectId as string),
+ CYCLES_LIST(projectId as string),
(prevData: any) =>
(prevData ?? []).map((c: any) => ({
...c,
@@ -244,17 +164,20 @@ export const ActiveCycleDetails: React.FC = ({ cycle, isComple
});
};
- const { data: issues } = useSWR(
- workspaceSlug && projectId && cycle.id ? CYCLE_ISSUES(cycle.id as string) : null,
+ const { data: issues } = useSWR(
+ workspaceSlug && projectId && cycle.id
+ ? CYCLE_ISSUES_WITH_PARAMS(cycle.id, { priority: "high" })
+ : null,
workspaceSlug && projectId && cycle.id
? () =>
- cyclesService.getCycleIssues(
+ cyclesService.getCycleIssuesWithParams(
workspaceSlug as string,
projectId as string,
- cycle.id as string
+ cycle.id,
+ { priority: "high" }
)
: null
- );
+ ) as { data: IIssue[] };
const progressIndicatorData = stateGroups.map((group, index) => ({
id: index,
@@ -379,7 +302,7 @@ export const ActiveCycleDetails: React.FC = ({ cycle, isComple
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
-
= ({ issues }) => {
-
-
+ >;
- setSelectedCycle: React.Dispatch>;
- type: "current" | "upcoming" | "draft";
-};
-
-export const AllCyclesBoard: React.FC = ({
- cycles,
- setCreateUpdateCycleModal,
- setSelectedCycle,
- type,
-}) => {
- const [cycleDeleteModal, setCycleDeleteModal] = useState(false);
- const [selectedCycleForDelete, setSelectedCycleForDelete] = useState();
-
- const handleDeleteCycle = (cycle: ICycle) => {
- setSelectedCycleForDelete({ ...cycle, actionType: "delete" });
- setCycleDeleteModal(true);
- };
-
- const handleEditCycle = (cycle: ICycle) => {
- setSelectedCycle({ ...cycle, actionType: "edit" });
- setCreateUpdateCycleModal(true);
- };
-
- return (
- <>
-
- {cycles ? (
- cycles.length > 0 ? (
-
- {cycles.map((cycle) => (
- handleDeleteCycle(cycle)}
- handleEditCycle={() => handleEditCycle(cycle)}
- />
- ))}
-
- ) : type === "current" ? (
-
-
No cycle is present.
-
- ) : (
-
- )
- ) : (
-
-
-
- )}
- >
- );
-};
diff --git a/apps/app/components/cycles/all-cycles-list.tsx b/apps/app/components/cycles/all-cycles-list.tsx
deleted file mode 100644
index 502e13e8e..000000000
--- a/apps/app/components/cycles/all-cycles-list.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import { useState } from "react";
-
-// components
-import { DeleteCycleModal, SingleCycleList } from "components/cycles";
-import { EmptyState, Loader } from "components/ui";
-// image
-import emptyCycle from "public/empty-state/empty-cycle.svg";
-// icon
-import { XMarkIcon } from "@heroicons/react/24/outline";
-// types
-import { ICycle, SelectCycleType } from "types";
-
-type TCycleStatsViewProps = {
- cycles: ICycle[] | undefined;
- setCreateUpdateCycleModal: React.Dispatch>;
- setSelectedCycle: React.Dispatch>;
- type: "current" | "upcoming" | "draft";
-};
-
-export const AllCyclesList: React.FC = ({
- cycles,
- setCreateUpdateCycleModal,
- setSelectedCycle,
- type,
-}) => {
- const [cycleDeleteModal, setCycleDeleteModal] = useState(false);
- const [selectedCycleForDelete, setSelectedCycleForDelete] = useState();
-
- const handleDeleteCycle = (cycle: ICycle) => {
- setSelectedCycleForDelete({ ...cycle, actionType: "delete" });
- setCycleDeleteModal(true);
- };
-
- const handleEditCycle = (cycle: ICycle) => {
- setSelectedCycle({ ...cycle, actionType: "edit" });
- setCreateUpdateCycleModal(true);
- };
-
- return (
- <>
-
- {cycles ? (
- cycles.length > 0 ? (
-
- {cycles.map((cycle) => (
-
-
- handleDeleteCycle(cycle)}
- handleEditCycle={() => handleEditCycle(cycle)}
- />
-
-
- ))}
-
- ) : type === "current" ? (
-
-
No cycle is present.
-
- ) : (
-
- )
- ) : (
-
-
-
- )}
- >
- );
-};
diff --git a/apps/app/components/cycles/completed-cycles.tsx b/apps/app/components/cycles/completed-cycles.tsx
deleted file mode 100644
index 36ef691f5..000000000
--- a/apps/app/components/cycles/completed-cycles.tsx
+++ /dev/null
@@ -1,126 +0,0 @@
-import { useState } from "react";
-
-import { useRouter } from "next/router";
-
-import useSWR from "swr";
-
-// services
-import cyclesService from "services/cycles.service";
-// components
-import { DeleteCycleModal, SingleCycleCard, SingleCycleList } from "components/cycles";
-// icons
-import { ExclamationIcon } from "components/icons";
-// types
-import { ICycle, SelectCycleType } from "types";
-// fetch-keys
-import { CYCLE_COMPLETE_LIST } from "constants/fetch-keys";
-import { EmptyState, Loader } from "components/ui";
-// image
-import emptyCycle from "public/empty-state/empty-cycle.svg";
-
-export interface CompletedCyclesListProps {
- cycleView: string;
- setCreateUpdateCycleModal: React.Dispatch>;
- setSelectedCycle: React.Dispatch>;
-}
-
-export const CompletedCycles: React.FC = ({
- cycleView,
- setCreateUpdateCycleModal,
- setSelectedCycle,
-}) => {
- const [cycleDeleteModal, setCycleDeleteModal] = useState(false);
- const [selectedCycleForDelete, setSelectedCycleForDelete] = useState();
-
- const router = useRouter();
- const { workspaceSlug, projectId } = router.query;
-
- const { data: completedCycles } = useSWR(
- workspaceSlug && projectId ? CYCLE_COMPLETE_LIST(projectId as string) : null,
- workspaceSlug && projectId
- ? () => cyclesService.getCompletedCycles(workspaceSlug as string, projectId as string)
- : null
- );
-
- const handleDeleteCycle = (cycle: ICycle) => {
- setSelectedCycleForDelete({ ...cycle, actionType: "delete" });
- setCycleDeleteModal(true);
- };
-
- const handleEditCycle = (cycle: ICycle) => {
- setSelectedCycle({ ...cycle, actionType: "edit" });
- setCreateUpdateCycleModal(true);
- };
-
- return (
- <>
-
- {completedCycles ? (
- completedCycles.completed_cycles.length > 0 ? (
-
-
-
- Completed cycles are not editable.
-
- {cycleView === "list" && (
-
- {completedCycles.completed_cycles.map((cycle) => (
-
-
- handleDeleteCycle(cycle)}
- handleEditCycle={() => handleEditCycle(cycle)}
- isCompleted
- />
-
-
- ))}
-
- )}
- {cycleView === "board" && (
-
- {completedCycles.completed_cycles.map((cycle) => (
- handleDeleteCycle(cycle)}
- handleEditCycle={() => handleEditCycle(cycle)}
- isCompleted
- />
- ))}
-
- )}
-
- ) : (
-
- )
- ) : (
-
-
-
-
-
- )}
- >
- );
-};
diff --git a/apps/app/components/cycles/cycles-list-gantt-chart.tsx b/apps/app/components/cycles/cycles-list-gantt-chart.tsx
index 9c8e922d2..056872c33 100644
--- a/apps/app/components/cycles/cycles-list-gantt-chart.tsx
+++ b/apps/app/components/cycles/cycles-list-gantt-chart.tsx
@@ -4,6 +4,8 @@ import Link from "next/link";
import { useRouter } from "next/router";
// components
import { GanttChartRoot } from "components/gantt-chart";
+// ui
+import { Tooltip } from "components/ui";
// types
import { ICycle } from "types";
@@ -31,9 +33,11 @@ export const CyclesListGanttChartView: FC = ({ cycles }) => {
-
- {data?.name}
-
+
+
+ {data?.name}
+
+
);
diff --git a/apps/app/components/cycles/cycles-list/all-cycles-list.tsx b/apps/app/components/cycles/cycles-list/all-cycles-list.tsx
new file mode 100644
index 000000000..7ebd92a50
--- /dev/null
+++ b/apps/app/components/cycles/cycles-list/all-cycles-list.tsx
@@ -0,0 +1,29 @@
+import { useRouter } from "next/router";
+
+import useSWR from "swr";
+
+// services
+import cyclesService from "services/cycles.service";
+// components
+import { CyclesView } from "components/cycles";
+// fetch-keys
+import { CYCLES_LIST } from "constants/fetch-keys";
+
+type Props = {
+ viewType: string | null;
+};
+
+export const AllCyclesList: React.FC = ({ viewType }) => {
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { data: allCyclesList } = useSWR(
+ workspaceSlug && projectId ? CYCLES_LIST(projectId.toString()) : null,
+ workspaceSlug && projectId
+ ? () =>
+ cyclesService.getCyclesWithParams(workspaceSlug.toString(), projectId.toString(), "all")
+ : null
+ );
+
+ return ;
+};
diff --git a/apps/app/components/cycles/cycles-list/completed-cycles-list.tsx b/apps/app/components/cycles/cycles-list/completed-cycles-list.tsx
new file mode 100644
index 000000000..79a427d95
--- /dev/null
+++ b/apps/app/components/cycles/cycles-list/completed-cycles-list.tsx
@@ -0,0 +1,33 @@
+import { useRouter } from "next/router";
+
+import useSWR from "swr";
+
+// services
+import cyclesService from "services/cycles.service";
+// components
+import { CyclesView } from "components/cycles";
+// fetch-keys
+import { COMPLETED_CYCLES_LIST } from "constants/fetch-keys";
+
+type Props = {
+ viewType: string | null;
+};
+
+export const CompletedCyclesList: React.FC = ({ viewType }) => {
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { data: completedCyclesList } = useSWR(
+ workspaceSlug && projectId ? COMPLETED_CYCLES_LIST(projectId.toString()) : null,
+ workspaceSlug && projectId
+ ? () =>
+ cyclesService.getCyclesWithParams(
+ workspaceSlug.toString(),
+ projectId.toString(),
+ "completed"
+ )
+ : null
+ );
+
+ return ;
+};
diff --git a/apps/app/components/cycles/cycles-list/draft-cycles-list.tsx b/apps/app/components/cycles/cycles-list/draft-cycles-list.tsx
new file mode 100644
index 000000000..fd2dccc93
--- /dev/null
+++ b/apps/app/components/cycles/cycles-list/draft-cycles-list.tsx
@@ -0,0 +1,29 @@
+import { useRouter } from "next/router";
+
+import useSWR from "swr";
+
+// services
+import cyclesService from "services/cycles.service";
+// components
+import { CyclesView } from "components/cycles";
+// fetch-keys
+import { DRAFT_CYCLES_LIST } from "constants/fetch-keys";
+
+type Props = {
+ viewType: string | null;
+};
+
+export const DraftCyclesList: React.FC = ({ viewType }) => {
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { data: draftCyclesList } = useSWR(
+ workspaceSlug && projectId ? DRAFT_CYCLES_LIST(projectId.toString()) : null,
+ workspaceSlug && projectId
+ ? () =>
+ cyclesService.getCyclesWithParams(workspaceSlug.toString(), projectId.toString(), "draft")
+ : null
+ );
+
+ return ;
+};
diff --git a/apps/app/components/cycles/cycles-list/index.ts b/apps/app/components/cycles/cycles-list/index.ts
new file mode 100644
index 000000000..b4b4fdfb5
--- /dev/null
+++ b/apps/app/components/cycles/cycles-list/index.ts
@@ -0,0 +1,4 @@
+export * from "./all-cycles-list";
+export * from "./completed-cycles-list";
+export * from "./draft-cycles-list";
+export * from "./upcoming-cycles-list";
diff --git a/apps/app/components/cycles/cycles-list/upcoming-cycles-list.tsx b/apps/app/components/cycles/cycles-list/upcoming-cycles-list.tsx
new file mode 100644
index 000000000..140727cb8
--- /dev/null
+++ b/apps/app/components/cycles/cycles-list/upcoming-cycles-list.tsx
@@ -0,0 +1,33 @@
+import { useRouter } from "next/router";
+
+import useSWR from "swr";
+
+// services
+import cyclesService from "services/cycles.service";
+// components
+import { CyclesView } from "components/cycles";
+// fetch-keys
+import { UPCOMING_CYCLES_LIST } from "constants/fetch-keys";
+
+type Props = {
+ viewType: string | null;
+};
+
+export const UpcomingCyclesList: React.FC = ({ viewType }) => {
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { data: upcomingCyclesList } = useSWR(
+ workspaceSlug && projectId ? UPCOMING_CYCLES_LIST(projectId.toString()) : null,
+ workspaceSlug && projectId
+ ? () =>
+ cyclesService.getCyclesWithParams(
+ workspaceSlug.toString(),
+ projectId.toString(),
+ "upcoming"
+ )
+ : null
+ );
+
+ return ;
+};
diff --git a/apps/app/components/cycles/cycles-view.tsx b/apps/app/components/cycles/cycles-view.tsx
index aedd82ba3..261e81018 100644
--- a/apps/app/components/cycles/cycles-view.tsx
+++ b/apps/app/components/cycles/cycles-view.tsx
@@ -1,249 +1,233 @@
-import React, { useEffect } from "react";
-import dynamic from "next/dynamic";
-// headless ui
-import { Tab } from "@headlessui/react";
+import React, { useState } from "react";
+
+import { useRouter } from "next/router";
+
+import { mutate } from "swr";
+
+// services
+import cyclesService from "services/cycles.service";
// hooks
-import useLocalStorage from "hooks/use-local-storage";
+import useToast from "hooks/use-toast";
+import useUserAuth from "hooks/use-user-auth";
// components
import {
- ActiveCycleDetails,
- CompletedCyclesListProps,
- AllCyclesBoard,
- AllCyclesList,
+ CreateUpdateCycleModal,
CyclesListGanttChartView,
+ DeleteCycleModal,
+ SingleCycleCard,
+ SingleCycleList,
} from "components/cycles";
// ui
import { EmptyState, Loader } from "components/ui";
-// icons
-import { ChartBarIcon, ListBulletIcon, Squares2X2Icon } from "@heroicons/react/24/outline";
+// images
import emptyCycle from "public/empty-state/empty-cycle.svg";
+// helpers
+import { getDateRangeStatus } from "helpers/date-time.helper";
// types
+import { ICycle } from "types";
+// fetch-keys
import {
- SelectCycleType,
- ICycle,
- CurrentAndUpcomingCyclesResponse,
- DraftCyclesResponse,
-} from "types";
+ COMPLETED_CYCLES_LIST,
+ CURRENT_CYCLE_LIST,
+ CYCLES_LIST,
+ DRAFT_CYCLES_LIST,
+ UPCOMING_CYCLES_LIST,
+} from "constants/fetch-keys";
type Props = {
- setSelectedCycle: React.Dispatch>;
- setCreateUpdateCycleModal: React.Dispatch>;
- cyclesCompleteList: ICycle[] | undefined;
- currentAndUpcomingCycles: CurrentAndUpcomingCyclesResponse | undefined;
- draftCycles: DraftCyclesResponse | undefined;
+ cycles: ICycle[] | undefined;
+ viewType: string | null;
};
-export const CyclesView: React.FC = ({
- setSelectedCycle,
- setCreateUpdateCycleModal,
- cyclesCompleteList,
- currentAndUpcomingCycles,
- draftCycles,
-}) => {
- const { storedValue: cycleTab, setValue: setCycleTab } = useLocalStorage("cycleTab", "All");
- const { storedValue: cyclesView, setValue: setCyclesView } = useLocalStorage("cycleView", "list");
+export const CyclesView: React.FC = ({ cycles, viewType }) => {
+ const [createUpdateCycleModal, setCreateUpdateCycleModal] = useState(false);
+ const [selectedCycleToUpdate, setSelectedCycleToUpdate] = useState(null);
- const currentTabValue = (tab: string | null) => {
- switch (tab) {
- case "All":
- return 0;
- case "Active":
- return 1;
- case "Upcoming":
- return 2;
- case "Completed":
- return 3;
- case "Drafts":
- return 4;
- default:
- return 0;
- }
+ const [deleteCycleModal, setDeleteCycleModal] = useState(false);
+ const [selectedCycleToDelete, setSelectedCycleToDelete] = useState(null);
+
+ const router = useRouter();
+ const { workspaceSlug, projectId } = router.query;
+
+ const { user } = useUserAuth();
+ const { setToastAlert } = useToast();
+
+ const handleEditCycle = (cycle: ICycle) => {
+ setSelectedCycleToUpdate(cycle);
+ setCreateUpdateCycleModal(true);
};
- const CompletedCycles = dynamic(
- () => import("components/cycles").then((a) => a.CompletedCycles),
- {
- ssr: false,
- loading: () => (
-
-
-
- ),
- }
- );
+ const handleDeleteCycle = (cycle: ICycle) => {
+ setSelectedCycleToDelete(cycle);
+ setDeleteCycleModal(true);
+ };
+
+ const handleAddToFavorites = (cycle: ICycle) => {
+ if (!workspaceSlug || !projectId) return;
+
+ const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date);
+
+ const fetchKey =
+ cycleStatus === "current"
+ ? CURRENT_CYCLE_LIST(projectId as string)
+ : cycleStatus === "upcoming"
+ ? UPCOMING_CYCLES_LIST(projectId as string)
+ : cycleStatus === "completed"
+ ? COMPLETED_CYCLES_LIST(projectId as string)
+ : DRAFT_CYCLES_LIST(projectId as string);
+
+ mutate(
+ fetchKey,
+ (prevData) =>
+ (prevData ?? []).map((c) => ({
+ ...c,
+ is_favorite: c.id === cycle.id ? true : c.is_favorite,
+ })),
+ false
+ );
+
+ mutate(
+ CYCLES_LIST(projectId as string),
+ (prevData: any) =>
+ (prevData ?? []).map((c: any) => ({
+ ...c,
+ is_favorite: c.id === cycle.id ? true : c.is_favorite,
+ })),
+ false
+ );
+
+ cyclesService
+ .addCycleToFavorites(workspaceSlug as string, projectId as string, {
+ cycle: cycle.id,
+ })
+ .catch(() => {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Couldn't add the cycle to favorites. Please try again.",
+ });
+ });
+ };
+
+ const handleRemoveFromFavorites = (cycle: ICycle) => {
+ if (!workspaceSlug || !projectId) return;
+
+ const cycleStatus = getDateRangeStatus(cycle.start_date, cycle.end_date);
+
+ const fetchKey =
+ cycleStatus === "current"
+ ? CURRENT_CYCLE_LIST(projectId as string)
+ : cycleStatus === "upcoming"
+ ? UPCOMING_CYCLES_LIST(projectId as string)
+ : cycleStatus === "completed"
+ ? COMPLETED_CYCLES_LIST(projectId as string)
+ : DRAFT_CYCLES_LIST(projectId as string);
+
+ mutate(
+ fetchKey,
+ (prevData) =>
+ (prevData ?? []).map((c) => ({
+ ...c,
+ is_favorite: c.id === cycle.id ? false : c.is_favorite,
+ })),
+ false
+ );
+
+ mutate(
+ CYCLES_LIST(projectId as string),
+ (prevData: any) =>
+ (prevData ?? []).map((c: any) => ({
+ ...c,
+ is_favorite: c.id === cycle.id ? false : c.is_favorite,
+ })),
+ false
+ );
+
+ cyclesService
+ .removeCycleFromFavorites(workspaceSlug as string, projectId as string, cycle.id)
+ .catch(() => {
+ setToastAlert({
+ type: "error",
+ title: "Error!",
+ message: "Couldn't remove the cycle from favorites. Please try again.",
+ });
+ });
+ };
return (
<>
-
-
Cycles
-
-
-
-
-
-
- {
- switch (i) {
- case 0:
- return setCycleTab("All");
- case 1:
- return setCycleTab("Active");
- case 2:
- return setCycleTab("Upcoming");
- case 3:
- return setCycleTab("Completed");
- case 4:
- return setCycleTab("Drafts");
- default:
- return setCycleTab("All");
- }
- }}
- >
-
-
- {["All", "Active", "Upcoming", "Completed", "Drafts"].map((tab, index) => {
- if (
- cyclesView === "gantt_chart" &&
- (tab === "Active" || tab === "Drafts" || tab === "Completed")
- )
- return null;
-
- return (
-
- `rounded-3xl border px-6 py-1 outline-none ${
- selected
- ? "border-brand-accent bg-brand-accent text-white font-medium"
- : "border-brand-base bg-brand-base hover:bg-brand-surface-2"
- }`
- }
- >
- {tab}
-
- );
- })}
-
-
-
-
- {cyclesView === "list" && (
-
- )}
- {cyclesView === "board" && (
-
- )}
- {cyclesView === "gantt_chart" && (
-
- )}
-
- {cyclesView !== "gantt_chart" && (
-
- {currentAndUpcomingCycles?.current_cycle?.[0] ? (
-
- ) : (
- setCreateUpdateCycleModal(false)}
+ data={selectedCycleToUpdate}
+ user={user}
+ />
+
+ {cycles ? (
+ cycles.length > 0 ? (
+ viewType === "list" ? (
+
+ {cycles.map((cycle) => (
+
+
+ handleDeleteCycle(cycle)}
+ handleEditCycle={() => handleEditCycle(cycle)}
+ handleAddToFavorites={() => handleAddToFavorites(cycle)}
+ handleRemoveFromFavorites={() => handleRemoveFromFavorites(cycle)}
+ />
+
+
+ ))}
+
+ ) : viewType === "board" ? (
+
+ {cycles.map((cycle) => (
+
handleDeleteCycle(cycle)}
+ handleEditCycle={() => handleEditCycle(cycle)}
+ handleAddToFavorites={() => handleAddToFavorites(cycle)}
+ handleRemoveFromFavorites={() => handleRemoveFromFavorites(cycle)}
/>
- )}
-
- )}
-
- {cyclesView === "list" && (
-
- )}
- {cyclesView === "board" && (
-
- )}
- {cyclesView === "gantt_chart" && (
-
- )}
-
-
-
-
- {cyclesView !== "gantt_chart" && (
-
- {cyclesView === "list" && (
-
- )}
- {cyclesView === "board" && (
-
- )}
-
- )}
-
-
+ ))}
+
+ ) : (
+
+ )
+ ) : (
+
+ )
+ ) : viewType === "list" ? (
+
+
+
+
+
+ ) : viewType === "board" ? (
+
+
+
+
+
+ ) : (
+
+
+
+ )}
>
);
};
diff --git a/apps/app/components/cycles/delete-cycle-modal.tsx b/apps/app/components/cycles/delete-cycle-modal.tsx
index 136a9b847..3f2de2913 100644
--- a/apps/app/components/cycles/delete-cycle-modal.tsx
+++ b/apps/app/components/cycles/delete-cycle-modal.tsx
@@ -14,24 +14,20 @@ import { DangerButton, SecondaryButton } from "components/ui";
// icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// types
-import type {
- CompletedCyclesResponse,
- CurrentAndUpcomingCyclesResponse,
- DraftCyclesResponse,
- ICycle,
-} from "types";
+import type { ICurrentUserResponse, ICycle } from "types";
type TConfirmCycleDeletionProps = {
isOpen: boolean;
setIsOpen: React.Dispatch>;
- data?: ICycle;
+ data?: ICycle | null;
+ user: ICurrentUserResponse | undefined;
};
// fetch-keys
import {
- CYCLE_COMPLETE_LIST,
- CYCLE_CURRENT_AND_UPCOMING_LIST,
- CYCLE_DETAILS,
- CYCLE_DRAFT_LIST,
- CYCLE_LIST,
+ COMPLETED_CYCLES_LIST,
+ CURRENT_CYCLE_LIST,
+ CYCLES_LIST,
+ DRAFT_CYCLES_LIST,
+ UPCOMING_CYCLES_LIST,
} from "constants/fetch-keys";
import { getDateRangeStatus } from "helpers/date-time.helper";
@@ -39,6 +35,7 @@ export const DeleteCycleModal: React.FC = ({
isOpen,
setIsOpen,
data,
+ user,
}) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
@@ -58,65 +55,30 @@ export const DeleteCycleModal: React.FC = ({
setIsDeleteLoading(true);
await cycleService
- .deleteCycle(workspaceSlug as string, data.project, data.id)
+ .deleteCycle(workspaceSlug as string, data.project, data.id, user)
.then(() => {
- switch (getDateRangeStatus(data.start_date, data.end_date)) {
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => {
- if (!prevData) return;
+ const cycleType = getDateRangeStatus(data.start_date, data.end_date);
+ const fetchKey =
+ cycleType === "current"
+ ? CURRENT_CYCLE_LIST(projectId as string)
+ : cycleType === "upcoming"
+ ? UPCOMING_CYCLES_LIST(projectId as string)
+ : cycleType === "completed"
+ ? COMPLETED_CYCLES_LIST(projectId as string)
+ : DRAFT_CYCLES_LIST(projectId as string);
- return {
- completed_cycles: prevData.completed_cycles?.filter(
- (cycle) => cycle.id !== data?.id
- ),
- };
- },
- false
- );
- break;
- case "current":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => {
- if (!prevData) return;
- return {
- current_cycle: prevData.current_cycle?.filter((c) => c.id !== data?.id),
- upcoming_cycle: prevData.upcoming_cycle,
- };
- },
- false
- );
- break;
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => {
- if (!prevData) return;
+ mutate(
+ fetchKey,
+ (prevData) => {
+ if (!prevData) return;
+
+ return prevData.filter((cycle) => cycle.id !== data?.id);
+ },
+ false
+ );
- return {
- current_cycle: prevData.current_cycle,
- upcoming_cycle: prevData.upcoming_cycle?.filter((c) => c.id !== data?.id),
- };
- },
- false
- );
- break;
- default:
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => {
- if (!prevData) return;
- return {
- draft_cycles: prevData.draft_cycles?.filter((cycle) => cycle.id !== data?.id),
- };
- },
- false
- );
- }
mutate(
- CYCLE_DETAILS(projectId as string),
+ CYCLES_LIST(projectId as string),
(prevData: any) => {
if (!prevData) return;
return prevData.filter((cycle: any) => cycle.id !== data?.id);
diff --git a/apps/app/components/cycles/empty-cycle.tsx b/apps/app/components/cycles/empty-cycle.tsx
deleted file mode 100644
index af2f12a11..000000000
--- a/apps/app/components/cycles/empty-cycle.tsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React from "react";
-import { LinearProgressIndicator } from "components/ui";
-
-export const EmptyCycle = () => {
- const emptyCycleData = [
- {
- id: 1,
- name: "backlog",
- value: 20,
- color: "#DEE2E6",
- },
- {
- id: 2,
- name: "unstarted",
- value: 14,
- color: "#26B5CE",
- },
- {
- id: 3,
- name: "started",
- value: 27,
- color: "#F7AE59",
- },
- {
- id: 4,
- name: "cancelled",
- value: 15,
- color: "#D687FF",
- },
- {
- id: 5,
- name: "completed",
- value: 14,
- color: "#09A953",
- },
- ];
- return (
-
-
-
-
-
Create New Cycle
-
- Sprint more effectively with Cycles by confining your project
to a fixed amount of
- time. Create new cycle now.
-
-
-
- );
-};
diff --git a/apps/app/components/cycles/form.tsx b/apps/app/components/cycles/form.tsx
index a0bd781ce..5c0b2e080 100644
--- a/apps/app/components/cycles/form.tsx
+++ b/apps/app/components/cycles/form.tsx
@@ -12,7 +12,7 @@ type Props = {
handleFormSubmit: (values: Partial) => Promise;
handleClose: () => void;
status: boolean;
- data?: ICycle;
+ data?: ICycle | null;
};
const defaultValues: Partial = {
@@ -28,7 +28,6 @@ export const CycleForm: React.FC = ({ handleFormSubmit, handleClose, stat
formState: { errors, isSubmitting },
handleSubmit,
control,
- watch,
reset,
} = useForm({
defaultValues,
diff --git a/apps/app/components/cycles/gantt-chart.tsx b/apps/app/components/cycles/gantt-chart.tsx
index 44abc392b..42ecad448 100644
--- a/apps/app/components/cycles/gantt-chart.tsx
+++ b/apps/app/components/cycles/gantt-chart.tsx
@@ -4,6 +4,8 @@ import Link from "next/link";
import { useRouter } from "next/router";
// components
import { GanttChartRoot } from "components/gantt-chart";
+// ui
+import { Tooltip } from "components/ui";
// hooks
import useGanttChartCycleIssues from "hooks/gantt-chart/cycle-issues-view";
@@ -38,9 +40,23 @@ export const CycleIssuesGanttChartView: FC = ({}) => {
className="flex-shrink-0 w-[4px] h-full"
style={{ backgroundColor: data?.state_detail?.color || "#858e96" }}
/>
-
- {data?.name}
-
+
+
+ {data?.name}
+
+
+ {data.infoToggle && (
+
+
+
+ info
+
+
+
+ )}
);
@@ -59,10 +75,20 @@ export const CycleIssuesGanttChartView: FC = ({}) => {
const blockFormat = (blocks: any) =>
blocks && blocks.length > 0
? blocks.map((_block: any) => {
- if (_block?.start_date && _block.target_date) console.log("_block", _block);
+ let startDate = new Date(_block.created_at);
+ let targetDate = new Date(_block.updated_at);
+ let infoToggle = true;
+
+ if (_block?.start_date && _block.target_date) {
+ startDate = _block?.start_date;
+ targetDate = _block.target_date;
+ infoToggle = false;
+ }
+
return {
- start_date: new Date(_block.created_at),
- target_date: new Date(_block.updated_at),
+ start_date: new Date(startDate),
+ target_date: new Date(targetDate),
+ infoToggle: infoToggle,
data: _block,
};
})
diff --git a/apps/app/components/cycles/index.ts b/apps/app/components/cycles/index.ts
index 3151529c5..40355d574 100644
--- a/apps/app/components/cycles/index.ts
+++ b/apps/app/components/cycles/index.ts
@@ -1,18 +1,15 @@
+export * from "./cycles-list";
export * from "./active-cycle-details";
-export * from "./cycles-view";
-export * from "./completed-cycles";
+export * from "./active-cycle-stats";
export * from "./cycles-list-gantt-chart";
-export * from "./all-cycles-board";
-export * from "./all-cycles-list";
+export * from "./cycles-view";
export * from "./delete-cycle-modal";
export * from "./form";
export * from "./gantt-chart";
export * from "./modal";
export * from "./select";
export * from "./sidebar";
-export * from "./single-cycle-list";
export * from "./single-cycle-card";
-export * from "./empty-cycle";
+export * from "./single-cycle-list";
export * from "./transfer-issues-modal";
export * from "./transfer-issues";
-export * from "./active-cycle-stats";
diff --git a/apps/app/components/cycles/modal.tsx b/apps/app/components/cycles/modal.tsx
index b3baacd65..3c1c16506 100644
--- a/apps/app/components/cycles/modal.tsx
+++ b/apps/app/components/cycles/modal.tsx
@@ -15,26 +15,29 @@ import { CycleForm } from "components/cycles";
// helper
import { getDateRangeStatus, isDateGreaterThanToday } from "helpers/date-time.helper";
// types
-import type { ICycle } from "types";
+import type { ICurrentUserResponse, ICycle } from "types";
// fetch keys
import {
- CYCLE_COMPLETE_LIST,
- CYCLE_CURRENT_AND_UPCOMING_LIST,
- CYCLE_DETAILS,
- CYCLE_DRAFT_LIST,
- CYCLE_INCOMPLETE_LIST,
+ COMPLETED_CYCLES_LIST,
+ CURRENT_CYCLE_LIST,
+ CYCLES_LIST,
+ DRAFT_CYCLES_LIST,
+ INCOMPLETE_CYCLES_LIST,
+ UPCOMING_CYCLES_LIST,
} from "constants/fetch-keys";
type CycleModalProps = {
isOpen: boolean;
handleClose: () => void;
- data?: ICycle;
+ data?: ICycle | null;
+ user: ICurrentUserResponse | undefined;
};
export const CreateUpdateCycleModal: React.FC = ({
isOpen,
handleClose,
data,
+ user,
}) => {
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
@@ -42,24 +45,26 @@ export const CreateUpdateCycleModal: React.FC = ({
const { setToastAlert } = useToast();
const createCycle = async (payload: Partial) => {
+ if (!workspaceSlug || !projectId) return;
+
await cycleService
- .createCycle(workspaceSlug as string, projectId as string, payload)
+ .createCycle(workspaceSlug.toString(), projectId.toString(), payload, user)
.then((res) => {
switch (getDateRangeStatus(res.start_date, res.end_date)) {
case "completed":
- mutate(CYCLE_COMPLETE_LIST(projectId as string));
+ mutate(COMPLETED_CYCLES_LIST(projectId.toString()));
break;
case "current":
- mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string));
+ mutate(CURRENT_CYCLE_LIST(projectId.toString()));
break;
case "upcoming":
- mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string));
+ mutate(UPCOMING_CYCLES_LIST(projectId.toString()));
break;
default:
- mutate(CYCLE_DRAFT_LIST(projectId as string));
+ mutate(DRAFT_CYCLES_LIST(projectId.toString()));
}
- mutate(CYCLE_INCOMPLETE_LIST(projectId as string));
- mutate(CYCLE_DETAILS(projectId as string));
+ mutate(INCOMPLETE_CYCLES_LIST(projectId.toString()));
+ mutate(CYCLES_LIST(projectId.toString()));
handleClose();
setToastAlert({
@@ -68,7 +73,7 @@ export const CreateUpdateCycleModal: React.FC = ({
message: "Cycle created successfully.",
});
})
- .catch((err) => {
+ .catch(() => {
setToastAlert({
type: "error",
title: "Error!",
@@ -78,39 +83,41 @@ export const CreateUpdateCycleModal: React.FC = ({
};
const updateCycle = async (cycleId: string, payload: Partial) => {
+ if (!workspaceSlug || !projectId) return;
+
await cycleService
- .updateCycle(workspaceSlug as string, projectId as string, cycleId, payload)
+ .updateCycle(workspaceSlug.toString(), projectId.toString(), cycleId, payload, user)
.then((res) => {
switch (getDateRangeStatus(data?.start_date, data?.end_date)) {
case "completed":
- mutate(CYCLE_COMPLETE_LIST(projectId as string));
+ mutate(COMPLETED_CYCLES_LIST(projectId.toString()));
break;
case "current":
- mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string));
+ mutate(CURRENT_CYCLE_LIST(projectId.toString()));
break;
case "upcoming":
- mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string));
+ mutate(UPCOMING_CYCLES_LIST(projectId.toString()));
break;
default:
- mutate(CYCLE_DRAFT_LIST(projectId as string));
+ mutate(DRAFT_CYCLES_LIST(projectId.toString()));
}
- mutate(CYCLE_DETAILS(projectId as string));
+ mutate(CYCLES_LIST(projectId.toString()));
if (
getDateRangeStatus(data?.start_date, data?.end_date) !=
getDateRangeStatus(res.start_date, res.end_date)
) {
switch (getDateRangeStatus(res.start_date, res.end_date)) {
case "completed":
- mutate(CYCLE_COMPLETE_LIST(projectId as string));
+ mutate(COMPLETED_CYCLES_LIST(projectId.toString()));
break;
case "current":
- mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string));
+ mutate(CURRENT_CYCLE_LIST(projectId.toString()));
break;
case "upcoming":
- mutate(CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string));
+ mutate(UPCOMING_CYCLES_LIST(projectId.toString()));
break;
default:
- mutate(CYCLE_DRAFT_LIST(projectId as string));
+ mutate(DRAFT_CYCLES_LIST(projectId.toString()));
}
}
diff --git a/apps/app/components/cycles/select.tsx b/apps/app/components/cycles/select.tsx
index 971c60ddd..2fdda69b5 100644
--- a/apps/app/components/cycles/select.tsx
+++ b/apps/app/components/cycles/select.tsx
@@ -4,6 +4,7 @@ import { useRouter } from "next/router";
import useSWR from "swr";
+import useUserAuth from "hooks/use-user-auth";
// headless ui
import { Listbox, Transition } from "@headlessui/react";
// icons
@@ -14,7 +15,7 @@ import cycleServices from "services/cycles.service";
// components
import { CreateUpdateCycleModal } from "components/cycles";
// fetch-keys
-import { CYCLE_LIST } from "constants/fetch-keys";
+import { CYCLES_LIST } from "constants/fetch-keys";
export type IssueCycleSelectProps = {
projectId: string;
@@ -35,10 +36,12 @@ export const CycleSelect: React.FC = ({
const router = useRouter();
const { workspaceSlug } = router.query;
+ const { user } = useUserAuth();
+
const { data: cycles } = useSWR(
- workspaceSlug && projectId ? CYCLE_LIST(projectId) : null,
+ workspaceSlug && projectId ? CYCLES_LIST(projectId) : null,
workspaceSlug && projectId
- ? () => cycleServices.getCycles(workspaceSlug as string, projectId)
+ ? () => cycleServices.getCyclesWithParams(workspaceSlug as string, projectId as string, "all")
: null
);
@@ -54,7 +57,11 @@ export const CycleSelect: React.FC = ({
return (
<>
-
+
{({ open }) => (
<>
diff --git a/apps/app/components/cycles/sidebar.tsx b/apps/app/components/cycles/sidebar.tsx
index 494383fc4..03747fc3b 100644
--- a/apps/app/components/cycles/sidebar.tsx
+++ b/apps/app/components/cycles/sidebar.tsx
@@ -1,7 +1,6 @@
import React, { useEffect, useState } from "react";
import { useRouter } from "next/router";
-import Image from "next/image";
import useSWR, { mutate } from "swr";
@@ -39,7 +38,7 @@ import {
renderShortDate,
} from "helpers/date-time.helper";
// types
-import { ICycle, IIssue } from "types";
+import { ICurrentUserResponse, ICycle, IIssue } from "types";
// fetch-keys
import { CYCLE_DETAILS, CYCLE_ISSUES } from "constants/fetch-keys";
@@ -48,6 +47,7 @@ type Props = {
isOpen: boolean;
cycleStatus: string;
isCompleted: boolean;
+ user: ICurrentUserResponse | undefined;
};
export const CycleDetailsSidebar: React.FC = ({
@@ -55,6 +55,7 @@ export const CycleDetailsSidebar: React.FC = ({
isOpen,
cycleStatus,
isCompleted,
+ user,
}) => {
const [cycleDeleteModal, setCycleDeleteModal] = useState(false);
@@ -94,7 +95,7 @@ export const CycleDetailsSidebar: React.FC = ({
);
cyclesService
- .patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data)
+ .patchCycle(workspaceSlug as string, projectId as string, cycleId as string, data, user)
.then(() => mutate(CYCLE_DETAILS(cycleId as string)))
.catch((e) => console.log(e));
};
@@ -294,7 +295,12 @@ export const CycleDetailsSidebar: React.FC = ({
return (
<>
-
+
= ({
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
-
void;
handleDeleteCycle: () => void;
+ handleAddToFavorites: () => void;
+ handleRemoveFromFavorites: () => void;
isCompleted?: boolean;
};
@@ -94,6 +80,8 @@ export const SingleCycleCard: React.FC = ({
cycle,
handleEditCycle,
handleDeleteCycle,
+ handleAddToFavorites,
+ handleRemoveFromFavorites,
isCompleted = false,
}) => {
const router = useRouter();
@@ -105,142 +93,6 @@ export const SingleCycleCard: React.FC = ({
const endDate = new Date(cycle.end_date ?? "");
const startDate = new Date(cycle.start_date ?? "");
- const handleAddToFavorites = () => {
- if (!workspaceSlug || !projectId || !cycle) return;
-
- switch (cycleStatus) {
- case "current":
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => ({
- current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => ({
- completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "draft":
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => ({
- draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- }
- mutate(
- CYCLE_DETAILS(projectId as string),
- (prevData: any) =>
- (prevData ?? []).map((c: any) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- false
- );
-
- cyclesService
- .addCycleToFavorites(workspaceSlug as string, projectId as string, {
- cycle: cycle.id,
- })
- .catch(() => {
- setToastAlert({
- type: "error",
- title: "Error!",
- message: "Couldn't add the cycle to favorites. Please try again.",
- });
- });
- };
-
- const handleRemoveFromFavorites = () => {
- if (!workspaceSlug || !projectId || !cycle) return;
-
- switch (cycleStatus) {
- case "current":
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => ({
- current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => ({
- completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "draft":
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => ({
- draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- }
- mutate(
- CYCLE_DETAILS(projectId as string),
- (prevData: any) =>
- (prevData ?? []).map((c: any) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- false
- );
-
- cyclesService
- .removeCycleFromFavorites(workspaceSlug as string, projectId as string, cycle.id)
- .catch(() => {
- setToastAlert({
- type: "error",
- title: "Error!",
- message: "Couldn't remove the cycle from favorites. Please try again.",
- });
- });
- };
-
const handleCopyText = () => {
const originURL =
typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
@@ -393,7 +245,7 @@ export const SingleCycleCard: React.FC = ({
Creator:
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
-
void;
handleDeleteCycle: () => void;
+ handleAddToFavorites: () => void;
+ handleRemoveFromFavorites: () => void;
isCompleted?: boolean;
};
@@ -128,6 +112,8 @@ export const SingleCycleList: React.FC = ({
cycle,
handleEditCycle,
handleDeleteCycle,
+ handleAddToFavorites,
+ handleRemoveFromFavorites,
isCompleted = false,
}) => {
const router = useRouter();
@@ -139,142 +125,6 @@ export const SingleCycleList: React.FC = ({
const endDate = new Date(cycle.end_date ?? "");
const startDate = new Date(cycle.start_date ?? "");
- const handleAddToFavorites = () => {
- if (!workspaceSlug || !projectId || !cycle) return;
-
- switch (cycleStatus) {
- case "current":
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => ({
- current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => ({
- completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "draft":
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => ({
- draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- }),
- false
- );
- break;
- }
- mutate(
- CYCLE_DETAILS(projectId as string),
- (prevData: any) =>
- (prevData ?? []).map((c: any) => ({
- ...c,
- is_favorite: c.id === cycle.id ? true : c.is_favorite,
- })),
- false
- );
-
- cyclesService
- .addCycleToFavorites(workspaceSlug as string, projectId as string, {
- cycle: cycle.id,
- })
- .catch(() => {
- setToastAlert({
- type: "error",
- title: "Error!",
- message: "Couldn't add the cycle to favorites. Please try again.",
- });
- });
- };
-
- const handleRemoveFromFavorites = () => {
- if (!workspaceSlug || !projectId || !cycle) return;
-
- switch (cycleStatus) {
- case "current":
- case "upcoming":
- mutate(
- CYCLE_CURRENT_AND_UPCOMING_LIST(projectId as string),
- (prevData) => ({
- current_cycle: (prevData?.current_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- upcoming_cycle: (prevData?.upcoming_cycle ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "completed":
- mutate(
- CYCLE_COMPLETE_LIST(projectId as string),
- (prevData) => ({
- completed_cycles: (prevData?.completed_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- case "draft":
- mutate(
- CYCLE_DRAFT_LIST(projectId as string),
- (prevData) => ({
- draft_cycles: (prevData?.draft_cycles ?? []).map((c) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- }),
- false
- );
- break;
- }
- mutate(
- CYCLE_DETAILS(projectId as string),
- (prevData: any) =>
- (prevData ?? []).map((c: any) => ({
- ...c,
- is_favorite: c.id === cycle.id ? false : c.is_favorite,
- })),
- false
- );
-
- cyclesService
- .removeCycleFromFavorites(workspaceSlug as string, projectId as string, cycle.id)
- .catch(() => {
- setToastAlert({
- type: "error",
- title: "Error!",
- message: "Couldn't remove the cycle from favorites. Please try again.",
- });
- });
- };
-
const handleCopyText = () => {
const originURL =
typeof window !== "undefined" && window.location.origin ? window.location.origin : "";
@@ -302,7 +152,7 @@ export const SingleCycleList: React.FC = ({
return (
-
+
@@ -394,7 +244,7 @@ export const SingleCycleList: React.FC
= ({
{cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? (
-
= ({ isOpen, handleClose }) =>
};
const { data: incompleteCycles } = useSWR(
- workspaceSlug && projectId ? CYCLE_INCOMPLETE_LIST(projectId as string) : null,
+ workspaceSlug && projectId ? INCOMPLETE_CYCLES_LIST(projectId as string) : null,
workspaceSlug && projectId
- ? () => cyclesService.getIncompleteCycles(workspaceSlug as string, projectId as string)
+ ? () =>
+ cyclesService.getCyclesWithParams(
+ workspaceSlug as string,
+ projectId as string,
+ "incomplete"
+ )
: null
);
diff --git a/apps/app/components/estimates/create-update-estimate-modal.tsx b/apps/app/components/estimates/create-update-estimate-modal.tsx
index 3b9660e9d..68cbcaaaf 100644
--- a/apps/app/components/estimates/create-update-estimate-modal.tsx
+++ b/apps/app/components/estimates/create-update-estimate-modal.tsx
@@ -17,7 +17,7 @@ import { Input, PrimaryButton, SecondaryButton, TextArea } from "components/ui";
// helpers
import { checkDuplicates } from "helpers/array.helper";
// types
-import { IEstimate, IEstimateFormData } from "types";
+import { ICurrentUserResponse, IEstimate, IEstimateFormData } from "types";
// fetch-keys
import { ESTIMATES_LIST, ESTIMATE_DETAILS } from "constants/fetch-keys";
@@ -25,6 +25,7 @@ type Props = {
isOpen: boolean;
handleClose: () => void;
data?: IEstimate;
+ user: ICurrentUserResponse | undefined;
};
type FormValues = {
@@ -49,7 +50,7 @@ const defaultValues: Partial = {
value6: "",
};
-export const CreateUpdateEstimateModal: React.FC = ({ handleClose, data, isOpen }) => {
+export const CreateUpdateEstimateModal: React.FC = ({ handleClose, data, isOpen, user }) => {
const {
register,
formState: { isSubmitting },
@@ -73,7 +74,7 @@ export const CreateUpdateEstimateModal: React.FC = ({ handleClose, data,
if (!workspaceSlug || !projectId) return;
await estimatesService
- .createEstimate(workspaceSlug as string, projectId as string, payload)
+ .createEstimate(workspaceSlug as string, projectId as string, payload, user)
.then(() => {
mutate(ESTIMATES_LIST(projectId as string));
onClose();
@@ -118,7 +119,13 @@ export const CreateUpdateEstimateModal: React.FC = ({ handleClose, data,
);
await estimatesService
- .patchEstimate(workspaceSlug as string, projectId as string, data?.id as string, payload)
+ .patchEstimate(
+ workspaceSlug as string,
+ projectId as string,
+ data?.id as string,
+ payload,
+ user
+ )
.then(() => {
mutate(ESTIMATES_LIST(projectId.toString()));
mutate(ESTIMATE_DETAILS(data.id));
diff --git a/apps/app/components/estimates/single-estimate.tsx b/apps/app/components/estimates/single-estimate.tsx
index 43dcc45b7..5e331c139 100644
--- a/apps/app/components/estimates/single-estimate.tsx
+++ b/apps/app/components/estimates/single-estimate.tsx
@@ -16,15 +16,17 @@ import { PencilIcon, TrashIcon } from "@heroicons/react/24/outline";
// helpers
import { orderArrayBy } from "helpers/array.helper";
// types
-import { IEstimate } from "types";
+import { ICurrentUserResponse, IEstimate } from "types";
type Props = {
+ user: ICurrentUserResponse | undefined;
estimate: IEstimate;
editEstimate: (estimate: IEstimate) => void;
handleEstimateDelete: (estimateId: string) => void;
};
export const SingleEstimate: React.FC = ({
+ user,
estimate,
editEstimate,
handleEstimateDelete,
@@ -52,7 +54,7 @@ export const SingleEstimate: React.FC = ({
}, false);
await projectService
- .updateProject(workspaceSlug as string, projectId as string, payload)
+ .updateProject(workspaceSlug as string, projectId as string, payload, user)
.catch(() => {
setToastAlert({
type: "error",
diff --git a/apps/app/components/gantt-chart/blocks/index.tsx b/apps/app/components/gantt-chart/blocks/index.tsx
index f2d44b294..d5eadf2a0 100644
--- a/apps/app/components/gantt-chart/blocks/index.tsx
+++ b/apps/app/components/gantt-chart/blocks/index.tsx
@@ -49,7 +49,10 @@ export const GanttChartBlocks: FC<{
width: `${block?.position?.width}px`,
}}
>
- {blockRender({ ...block?.data })}
+ {blockRender({
+ ...block?.data,
+ infoToggle: block?.infoToggle ? true : false,
+ })}
diff --git a/apps/app/components/integration/delete-import-modal.tsx b/apps/app/components/integration/delete-import-modal.tsx
index 8c5ab3803..cd0b12a2a 100644
--- a/apps/app/components/integration/delete-import-modal.tsx
+++ b/apps/app/components/integration/delete-import-modal.tsx
@@ -15,7 +15,7 @@ import { DangerButton, Input, SecondaryButton } from "components/ui";
// icons
import { ExclamationTriangleIcon } from "@heroicons/react/24/outline";
// types
-import { IImporterService } from "types";
+import { ICurrentUserResponse, IImporterService } from "types";
// fetch-keys
import { IMPORTER_SERVICES_LIST } from "constants/fetch-keys";
@@ -23,9 +23,10 @@ type Props = {
isOpen: boolean;
handleClose: () => void;
data: IImporterService | null;
+ user: ICurrentUserResponse | undefined;
};
-export const DeleteImportModal: React.FC
= ({ isOpen, handleClose, data }) => {
+export const DeleteImportModal: React.FC = ({ isOpen, handleClose, data, user }) => {
const [deleteLoading, setDeleteLoading] = useState(false);
const [confirmDeleteImport, setConfirmDeleteImport] = useState(false);
@@ -45,7 +46,7 @@ export const DeleteImportModal: React.FC = ({ isOpen, handleClose, data }
false
);
- IntegrationService.deleteImporterService(workspaceSlug as string, data.service, data.id)
+ IntegrationService.deleteImporterService(workspaceSlug as string, data.service, data.id, user)
.catch(() =>
setToastAlert({
type: "error",
diff --git a/apps/app/components/integration/github/root.tsx b/apps/app/components/integration/github/root.tsx
index b8bfb346b..96ce845c4 100644
--- a/apps/app/components/integration/github/root.tsx
+++ b/apps/app/components/integration/github/root.tsx
@@ -27,7 +27,7 @@ import { ArrowLeftIcon, ListBulletIcon } from "@heroicons/react/24/outline";
// images
import GithubLogo from "public/services/github.png";
// types
-import { IGithubRepoCollaborator, IGithubServiceImportFormData } from "types";
+import { ICurrentUserResponse, IGithubRepoCollaborator, IGithubServiceImportFormData } from "types";
// fetch-keys
import {
APP_INTEGRATIONS,
@@ -89,7 +89,11 @@ const integrationWorkflowData = [
},
];
-export const GithubImporterRoot = () => {
+type Props = {
+ user: ICurrentUserResponse | undefined;
+};
+
+export const GithubImporterRoot: React.FC = ({ user }) => {
const [currentStep, setCurrentStep] = useState({
state: "import-configure",
});
@@ -157,7 +161,7 @@ export const GithubImporterRoot = () => {
project_id: formData.project,
};
- await GithubIntegrationService.createGithubServiceImport(workspaceSlug as string, payload)
+ await GithubIntegrationService.createGithubServiceImport(workspaceSlug as string, payload, user)
.then(() => {
router.push(`/${workspaceSlug}/settings/import-export`);
mutate(IMPORTER_SERVICES_LIST(workspaceSlug as string));
diff --git a/apps/app/components/integration/github/single-user-select.tsx b/apps/app/components/integration/github/single-user-select.tsx
index 53fbce476..b94fc1dbd 100644
--- a/apps/app/components/integration/github/single-user-select.tsx
+++ b/apps/app/components/integration/github/single-user-select.tsx
@@ -1,4 +1,3 @@
-import Image from "next/image";
import { useRouter } from "next/router";
import useSWR from "swr";
@@ -66,11 +65,9 @@ export const SingleUserSelect: React.FC = ({ collaborator, index, users,
-
diff --git a/apps/app/components/integration/guide.tsx b/apps/app/components/integration/guide.tsx
index 06f13b752..2db8ef010 100644
--- a/apps/app/components/integration/guide.tsx
+++ b/apps/app/components/integration/guide.tsx
@@ -6,6 +6,8 @@ import { useRouter } from "next/router";
import useSWR, { mutate } from "swr";
+// hooks
+import useUserAuth from "hooks/use-user-auth";
// services
import IntegrationService from "services/integration";
// components
@@ -35,6 +37,8 @@ const IntegrationGuide = () => {
const router = useRouter();
const { workspaceSlug, provider } = router.query;
+ const { user } = useUserAuth();
+
const { data: importerServices } = useSWR(
workspaceSlug ? IMPORTER_SERVICES_LIST(workspaceSlug as string) : null,
workspaceSlug ? () => IntegrationService.getImporterServicesList(workspaceSlug as string) : null
@@ -51,6 +55,7 @@ const IntegrationGuide = () => {
isOpen={deleteImportModal}
handleClose={() => setDeleteImportModal(false)}
data={importToDelete}
+ user={user}
/>
{!provider && (
@@ -156,8 +161,8 @@ const IntegrationGuide = () => {
>
)}
- {provider && provider === "github" && }
- {provider && provider === "jira" && }
+ {provider && provider === "github" && }
+ {provider && provider === "jira" && }
>
);
diff --git a/apps/app/components/integration/jira/root.tsx b/apps/app/components/integration/jira/root.tsx
index 6ec39a36a..b1098c9cb 100644
--- a/apps/app/components/integration/jira/root.tsx
+++ b/apps/app/components/integration/jira/root.tsx
@@ -35,7 +35,7 @@ import {
import JiraLogo from "public/services/jira.png";
-import { IJiraImporterForm } from "types";
+import { ICurrentUserResponse, IJiraImporterForm } from "types";
const integrationWorkflowData: Array<{
title: string;
@@ -64,7 +64,11 @@ const integrationWorkflowData: Array<{
},
];
-export const JiraImporterRoot = () => {
+type Props = {
+ user: ICurrentUserResponse | undefined;
+};
+
+export const JiraImporterRoot: React.FC
= ({ user }) => {
const [currentStep, setCurrentStep] = useState({
state: "import-configure",
});
@@ -85,7 +89,7 @@ export const JiraImporterRoot = () => {
if (!workspaceSlug) return;
await jiraImporterService
- .createJiraImporter(workspaceSlug.toString(), data)
+ .createJiraImporter(workspaceSlug.toString(), data, user)
.then(() => {
mutate(IMPORTER_SERVICES_LIST(workspaceSlug.toString()));
router.push(`/${workspaceSlug}/settings/import-export`);
diff --git a/apps/app/components/issues/activity.tsx b/apps/app/components/issues/activity.tsx
index 7a3aed4a6..3b9ecc853 100644
--- a/apps/app/components/issues/activity.tsx
+++ b/apps/app/components/issues/activity.tsx
@@ -1,6 +1,7 @@
import React from "react";
+
import { useRouter } from "next/router";
-import Image from "next/image";
+
import useSWR from "swr";
// icons
@@ -27,7 +28,7 @@ import { Loader } from "components/ui";
import { renderShortNumericDateFormat, timeAgo } from "helpers/date-time.helper";
import { addSpaceIfCamelCase } from "helpers/string.helper";
// types
-import { IIssueComment, IIssueLabels } from "types";
+import { ICurrentUserResponse, IIssueComment, IIssueLabels } from "types";
import { PROJECT_ISSUES_ACTIVITY, PROJECT_ISSUE_LABELS } from "constants/fetch-keys";
import useEstimateOption from "hooks/use-estimate-option";
@@ -110,7 +111,11 @@ const activityDetails: {
},
};
-export const IssueActivitySection: React.FC = () => {
+type Props = {
+ user: ICurrentUserResponse | undefined;
+};
+
+export const IssueActivitySection: React.FC = ({ user }) => {
const router = useRouter();
const { workspaceSlug, projectId, issueId } = router.query;
@@ -143,7 +148,8 @@ export const IssueActivitySection: React.FC = () => {
projectId as string,
issueId as string,
comment.id,
- comment
+ comment,
+ user
)
.then((res) => {
mutateIssueActivities();
@@ -160,7 +166,8 @@ export const IssueActivitySection: React.FC = () => {
workspaceSlug as string,
projectId as string,
issueId as string,
- commentId
+ commentId,
+ user
)
.then(() => mutateIssueActivities());
};
@@ -340,7 +347,7 @@ export const IssueActivitySection: React.FC = () => {
?.icon
) : activityItem.actor_detail.avatar &&
activityItem.actor_detail.avatar !== "" ? (
- = {
comment_html: "",
};
-export const AddComment: React.FC = () => {
+type Props = {
+ user: ICurrentUserResponse | undefined;
+};
+
+export const AddComment: React.FC = ({ user }) => {
const {
handleSubmit,
control,
@@ -67,7 +71,13 @@ export const AddComment: React.FC = () => {
)
return;
await issuesServices
- .createIssueComment(workspaceSlug as string, projectId as string, issueId as string, formData)
+ .createIssueComment(
+ workspaceSlug as string,
+ projectId as string,
+ issueId as string,
+ formData,
+ user
+ )
.then(() => {
mutate(PROJECT_ISSUES_ACTIVITY(issueId as string));
reset(defaultValues);
diff --git a/apps/app/components/issues/comment/comment-card.tsx b/apps/app/components/issues/comment/comment-card.tsx
index e632e9ad3..72f6fcae6 100644
--- a/apps/app/components/issues/comment/comment-card.tsx
+++ b/apps/app/components/issues/comment/comment-card.tsx
@@ -1,6 +1,5 @@
import React, { useEffect, useState } from "react";
-import Image from "next/image";
import dynamic from "next/dynamic";
// react-hook-form
@@ -68,12 +67,12 @@ export const CommentCard: React.FC = ({ comment, onSubmit, handleCommentD
{comment.actor_detail.avatar && comment.actor_detail.avatar !== "" ? (
-
) : (
void;
data: IIssue | null;
+ user: ICurrentUserResponse | undefined;
};
-export const DeleteIssueModal: React.FC
= ({ isOpen, handleClose, data }) => {
+export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data, user }) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter();
@@ -57,7 +58,7 @@ export const DeleteIssueModal: React.FC = ({ isOpen, handleClose, data })
if (!workspaceSlug || !projectId || !data) return;
await issueServices
- .deleteIssue(workspaceSlug as string, projectId as string, data.id)
+ .deleteIssue(workspaceSlug as string, projectId as string, data.id, user)
.then(() => {
if (issueView === "calendar") {
const calendarFetchKey = cycleId
diff --git a/apps/app/components/issues/form.tsx b/apps/app/components/issues/form.tsx
index f09e5aedd..894830bd7 100644
--- a/apps/app/components/issues/form.tsx
+++ b/apps/app/components/issues/form.tsx
@@ -39,7 +39,7 @@ import { SparklesIcon, XMarkIcon } from "@heroicons/react/24/outline";
// helpers
import { cosineSimilarity } from "helpers/string.helper";
// types
-import type { IIssue } from "types";
+import type { ICurrentUserResponse, IIssue } from "types";
// rich-text-editor
const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor"), {
ssr: false,
@@ -91,6 +91,7 @@ export interface IssueFormProps {
setCreateMore: React.Dispatch>;
handleClose: () => void;
status: boolean;
+ user: ICurrentUserResponse | undefined;
}
export const IssueForm: FC = ({
@@ -103,6 +104,7 @@ export const IssueForm: FC = ({
setCreateMore,
handleClose,
status,
+ user,
}) => {
// states
const [mostSimilarIssue, setMostSimilarIssue] = useState