From 3b1233270433f12166748c83688805164f8c36fd Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Mon, 11 Dec 2023 22:23:20 +0530 Subject: [PATCH 1/9] fix: issue with clear filter option not working for filter groups in create view modal. (#3081) --- web/components/views/form.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/components/views/form.tsx b/web/components/views/form.tsx index e3e693869..525a7281f 100644 --- a/web/components/views/form.tsx +++ b/web/components/views/form.tsx @@ -54,7 +54,14 @@ export const ProjectViewForm: React.FC = observer(({ handleFormSubmit, ha // for removing filters from a key const handleRemoveFilter = (key: keyof IIssueFilterOptions, value: string | null) => { - if (!value) return; + // If value is null then remove all the filters of that key + if (!value) { + setValue("query_data", { + ...selectedFilters, + [key]: null, + }); + return; + } const newValues = selectedFilters?.[key] ?? []; From 472a5d8047c203e1da47da90feec658b6c13e3bf Mon Sep 17 00:00:00 2001 From: Lakhan Baheti <94619783+1akhanBaheti@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:23:49 +0530 Subject: [PATCH 2/9] fix: spreadsheet layout alignment (#3080) --- .../issue-layouts/spreadsheet/columns/assignee-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/attachment-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/created-on-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/due-date-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/estimate-column.tsx | 2 +- .../issues/issue-layouts/spreadsheet/columns/label-column.tsx | 2 +- .../issues/issue-layouts/spreadsheet/columns/link-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/priority-column.tsx | 4 ++-- .../issue-layouts/spreadsheet/columns/start-date-column.tsx | 2 +- .../issues/issue-layouts/spreadsheet/columns/state-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/sub-issue-column.tsx | 2 +- .../issue-layouts/spreadsheet/columns/updated-on-column.tsx | 2 +- .../issues/issue-layouts/spreadsheet/spreadsheet-column.tsx | 4 ++-- 13 files changed, 15 insertions(+), 15 deletions(-) diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx index 14ec310d9..6a5732a13 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/assignee-column.tsx @@ -27,7 +27,7 @@ export const SpreadsheetAssigneeColumn: React.FC = ({ issue, members, onC value={issue.assignees} defaultOptions={issue?.assignee_details ? issue.assignee_details : []} onChange={(data) => onChange({ assignees: data })} - className="h-11 w-full" + className="h-11 w-full border-b-[0.5px] border-custom-border-200" buttonClassName="!shadow-none !border-0 h-full w-full px-2.5 py-1 " noLabelBorder hideDropdownArrow diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx index 60cb627e2..8c1788a9a 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx @@ -18,7 +18,7 @@ export const SpreadsheetAttachmentColumn: React.FC = (props) => { return ( <> -
+
{issue.attachment_count} {issue.attachment_count === 1 ? "attachment" : "attachments"}
diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx index fa40551e0..4360cee11 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/created-on-column.tsx @@ -19,7 +19,7 @@ export const SpreadsheetCreatedOnColumn: React.FC = ({ issue, expandedIss return ( <> -
+
{renderLongDetailDateFormat(issue.created_at)}
diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx index 0387cb950..1c151cc47 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/due-date-column.tsx @@ -24,7 +24,7 @@ export const SpreadsheetDueDateColumn: React.FC = ({ issue, onChange, exp onChange({ target_date: val })} - className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1" + className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1 border-b-[0.5px] border-custom-border-200" noBorder disabled={disabled} /> diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx index b2bea0483..f0042db8e 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/estimate-column.tsx @@ -25,7 +25,7 @@ export const SpreadsheetEstimateColumn: React.FC = (props) => { projectId={issue.project_detail?.id ?? null} value={issue.estimate_point} onChange={(data) => onChange({ estimate_point: data })} - className="h-11 w-full" + className="h-11 w-full border-b-[0.5px] border-custom-border-200" buttonClassName="h-full w-full px-2.5 py-1 !shadow-none !border-0" hideDropdownArrow disabled={disabled} diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx index 91c9af5b7..0fa2abee1 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/label-column.tsx @@ -29,7 +29,7 @@ export const SpreadsheetLabelColumn: React.FC = (props) => { value={issue.labels} defaultOptions={issue?.label_details ? issue.label_details : []} onChange={(data) => onChange({ labels: data })} - className="h-11 w-full" + className="h-11 w-full border-b-[0.5px] border-custom-border-200" buttonClassName="px-2.5 h-full" hideDropdownArrow maxRender={1} diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx index 6f9523e0a..aa9337e75 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx @@ -18,7 +18,7 @@ export const SpreadsheetLinkColumn: React.FC = (props) => { return ( <> -
+
{issue.link_count} {issue.link_count === 1 ? "link" : "links"}
diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx index c4df4bfbe..09e9c53a0 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/priority-column.tsx @@ -24,8 +24,8 @@ export const SpreadsheetPriorityColumn: React.FC = ({ issue, onChange, ex onChange({ priority: data })} - className="h-11 w-full" - buttonClassName="!shadow-none !border-0 h-full w-full px-2.5 py-1 " + className="h-11 w-full border-b-[0.5px] border-custom-border-200" + buttonClassName="!shadow-none !border-0 h-full w-full px-2.5 py-1" showTitle highlightUrgentPriority={false} hideDropdownArrow diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx index d2817a429..f3dc3d5b0 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/start-date-column.tsx @@ -24,7 +24,7 @@ export const SpreadsheetStartDateColumn: React.FC = ({ issue, onChange, e onChange({ start_date: val })} - className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1" + className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1 border-b-[0.5px] border-custom-border-200" noBorder disabled={disabled} /> diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx index 964afce98..af935f1d6 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/state-column.tsx @@ -29,7 +29,7 @@ export const SpreadsheetStateColumn: React.FC = (props) => { value={issue.state} defaultOptions={issue?.state_detail ? [issue.state_detail] : []} onChange={(data) => onChange({ state: data.id, state_detail: data })} - className="w-full !h-11" + className="w-full !h-11 border-b-[0.5px] border-custom-border-200" buttonClassName="!shadow-none !border-0 h-full w-full" hideDropdownArrow disabled={disabled} diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx index 2fe1d43e2..2122a674f 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx @@ -18,7 +18,7 @@ export const SpreadsheetSubIssueColumn: React.FC = (props) => { return ( <> -
+
{issue.sub_issues_count} {issue.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx index 275bcd854..f2c49c279 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/updated-on-column.tsx @@ -21,7 +21,7 @@ export const SpreadsheetUpdatedOnColumn: React.FC = (props) => { return ( <> -
+
{renderLongDetailDateFormat(issue.updated_at)}
diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx index 120e0fb16..8b5c8c7a2 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx @@ -159,13 +159,13 @@ export const SpreadsheetColumn: React.FC = (props) => {
-
+
{issues?.map((issue) => { const disableUserActions = !canEditProperties(issue.project); return (
From ae2e1a4b64a57099c66d87c24b377ac568935cbd Mon Sep 17 00:00:00 2001 From: Lakhan Baheti <94619783+1akhanBaheti@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:24:41 +0530 Subject: [PATCH 3/9] fix: delete issue mutation & toast (#3079) * fix: delete issue mutation * fix: toast on delete issue * fix: activity to issue detail redirection --- web/components/issues/delete-issue-modal.tsx | 20 +++++++++++++++++- .../issue-layouts/kanban/base-kanban-root.tsx | 21 ++++--------------- .../spreadsheet/spreadsheet-view.tsx | 13 +++++++----- web/pages/profile/activity.tsx | 4 +++- .../project-issues/cycle/issue.store.ts | 1 + .../project-issues/module/issue.store.ts | 1 + .../project-issues/project/issue.store.ts | 1 + 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/web/components/issues/delete-issue-modal.tsx b/web/components/issues/delete-issue-modal.tsx index 50f53911d..2f53a825f 100644 --- a/web/components/issues/delete-issue-modal.tsx +++ b/web/components/issues/delete-issue-modal.tsx @@ -3,6 +3,8 @@ import { Dialog, Transition } from "@headlessui/react"; import { AlertTriangle } from "lucide-react"; // ui import { Button } from "@plane/ui"; +// hooks +import useToast from "hooks/use-toast"; // types import type { IIssue } from "types"; @@ -18,6 +20,8 @@ export const DeleteIssueModal: React.FC = (props) => { const [isDeleteLoading, setIsDeleteLoading] = useState(false); + const { setToastAlert } = useToast(); + useEffect(() => { setIsDeleteLoading(false); }, [isOpen]); @@ -31,7 +35,21 @@ export const DeleteIssueModal: React.FC = (props) => { setIsDeleteLoading(true); if (onSubmit) await onSubmit() - .then(() => onClose()) + .then(() => { + setToastAlert({ + title: "Success", + type: "success", + message: "Issue deleted successfully", + }); + onClose(); + }) + .catch(() => { + setToastAlert({ + title: "Error", + type: "error", + message: "Failed to delete issue", + }); + }) .finally(() => setIsDeleteLoading(false)); }; diff --git a/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx b/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx index 57ab8418c..05799f728 100644 --- a/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx +++ b/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx @@ -195,25 +195,12 @@ export const BaseKanBanRoot: React.FC = observer((props: IBas const handleDeleteIssue = async () => { if (!handleDragDrop) return; - await handleDragDrop(dragState.source, dragState.destination, sub_group_by, group_by, issues, issueIds) - .then(() => { - setToastAlert({ - title: "Success", - type: "success", - message: "Issue deleted successfully", - }); - }) - .catch(() => { - setToastAlert({ - title: "Error", - type: "error", - message: "Failed to delete issue", - }); - }) - .finally(() => { + await handleDragDrop(dragState.source, dragState.destination, sub_group_by, group_by, issues, issueIds).finally( + () => { setDeleteIssueModal(false); setDragState({}); - }); + } + ); }; const handleKanBanToggle = (toggle: "groupByHeaderMinMax" | "subgroupByIssuesVisibility", value: string) => { diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx index ef6215003..69ac625e8 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx @@ -77,6 +77,13 @@ export const SpreadsheetView: React.FC = observer((props) => { }; }, []); + if (!issues || issues.length === 0) + return ( +
+ +
+ ); + return (
@@ -84,7 +91,7 @@ export const SpreadsheetView: React.FC = observer((props) => { ref={containerRef} className="horizontal-scroll-enable flex divide-x-[0.5px] divide-custom-border-200 overflow-y-auto" > - {issues && issues.length > 0 ? ( + {issues && issues.length > 0 && ( <>
= observer((props) => { states={states} /> - ) : ( -
- -
)}
{/* empty div to show right most border */}
diff --git a/web/pages/profile/activity.tsx b/web/pages/profile/activity.tsx index 744ecae64..02317799f 100644 --- a/web/pages/profile/activity.tsx +++ b/web/pages/profile/activity.tsx @@ -100,7 +100,9 @@ const ProfileActivityPage: NextPageWithLayout = () => { activityItem.field !== "estimate" ? ( created{" "} - + this issue. diff --git a/web/store/issues/project-issues/cycle/issue.store.ts b/web/store/issues/project-issues/cycle/issue.store.ts index ed1bdcfeb..7d5355010 100644 --- a/web/store/issues/project-issues/cycle/issue.store.ts +++ b/web/store/issues/project-issues/cycle/issue.store.ts @@ -257,6 +257,7 @@ export class CycleIssuesStore extends IssueBaseStore implements ICycleIssuesStor if (!_issues) _issues = {}; if (!_issues[cycleId]) _issues[cycleId] = {}; delete _issues?.[cycleId]?.[issueId]; + _issues[cycleId] = { ..._issues[cycleId] }; runInAction(() => { this.issues = _issues; diff --git a/web/store/issues/project-issues/module/issue.store.ts b/web/store/issues/project-issues/module/issue.store.ts index 1f1d1c190..8135eacaa 100644 --- a/web/store/issues/project-issues/module/issue.store.ts +++ b/web/store/issues/project-issues/module/issue.store.ts @@ -250,6 +250,7 @@ export class ModuleIssuesStore extends IssueBaseStore implements IModuleIssuesSt if (!_issues) _issues = {}; if (!_issues[moduleId]) _issues[moduleId] = {}; delete _issues?.[moduleId]?.[issueId]; + _issues[moduleId] = { ..._issues[moduleId] }; runInAction(() => { this.issues = _issues; diff --git a/web/store/issues/project-issues/project/issue.store.ts b/web/store/issues/project-issues/project/issue.store.ts index e2c2b8ad6..9b1b83801 100644 --- a/web/store/issues/project-issues/project/issue.store.ts +++ b/web/store/issues/project-issues/project/issue.store.ts @@ -175,6 +175,7 @@ export class ProjectIssuesStore extends IssueBaseStore implements IProjectIssues if (!_issues) _issues = {}; if (!_issues[projectId]) _issues[projectId] = {}; delete _issues?.[projectId]?.[issueId]; + _issues[projectId] = { ..._issues[projectId] }; runInAction(() => { this.issues = _issues; From 0f752f93b6c94159b72e7dc7a5672199ec5397da Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:25:14 +0530 Subject: [PATCH 4/9] fix: pre-fill cycle and module details when editing an issue (#3070) * fix: prefill cycle and module when editing an issue * chore: remove console.log --- .../issue-layouts/quick-action-dropdowns/cycle-issue.tsx | 7 +++++-- .../issue-layouts/quick-action-dropdowns/module-issue.tsx | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx index ecf938ab3..de9257834 100644 --- a/web/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx +++ b/web/components/issues/issue-layouts/quick-action-dropdowns/cycle-issue.tsx @@ -17,7 +17,7 @@ export const CycleIssueQuickActions: React.FC = (props) => { const { issue, handleDelete, handleUpdate, handleRemoveFromView, customActionButton } = props; const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, cycleId } = router.query; // states const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); @@ -75,7 +75,10 @@ export const CycleIssueQuickActions: React.FC = (props) => { onClick={(e) => { e.preventDefault(); e.stopPropagation(); - setIssueToEdit(issue); + setIssueToEdit({ + ...issue, + cycle: cycleId?.toString() ?? null, + }); setCreateUpdateIssueModal(true); }} > diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx index 9145fb870..93ccc49ba 100644 --- a/web/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx +++ b/web/components/issues/issue-layouts/quick-action-dropdowns/module-issue.tsx @@ -17,7 +17,7 @@ export const ModuleIssueQuickActions: React.FC = (props) => { const { issue, handleDelete, handleUpdate, handleRemoveFromView, customActionButton } = props; const router = useRouter(); - const { workspaceSlug } = router.query; + const { workspaceSlug, moduleId } = router.query; // states const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); @@ -75,7 +75,7 @@ export const ModuleIssueQuickActions: React.FC = (props) => { onClick={(e) => { e.preventDefault(); e.stopPropagation(); - setIssueToEdit(issue); + setIssueToEdit({ ...issue, module: moduleId?.toString() ?? null }); setCreateUpdateIssueModal(true); }} > From f119d702c707081577562d5940c3f66ffcf2df9c Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:25:48 +0530 Subject: [PATCH 5/9] chore: set an expiry of 30 days for the access and refresh tokens (#3071) --- web/services/api.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/services/api.service.ts b/web/services/api.service.ts index 621bac767..23be79929 100644 --- a/web/services/api.service.ts +++ b/web/services/api.service.ts @@ -10,7 +10,7 @@ export abstract class APIService { } setRefreshToken(token: string) { - Cookies.set("refreshToken", token); + Cookies.set("refreshToken", token, { expires: 30 }); } getRefreshToken() { @@ -22,7 +22,7 @@ export abstract class APIService { } setAccessToken(token: string) { - Cookies.set("accessToken", token); + Cookies.set("accessToken", token, { expires: 30 }); } getAccessToken() { From c33cfeb2270b34521c5bc0a5a1441a9c723433f5 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:26:29 +0530 Subject: [PATCH 6/9] chore: issue link mobx integration (#3072) * chore: issue link mobx integration * chore: issue link code refactor and build fix --- web/components/core/modals/link-modal.tsx | 10 +- .../issues/peek-overview/properties.tsx | 101 ++--------------- web/components/issues/peek-overview/root.tsx | 15 ++- web/components/issues/peek-overview/view.tsx | 14 ++- web/components/issues/sidebar.tsx | 86 +++----------- web/services/issue/issue.service.ts | 18 +-- web/services/module.service.ts | 6 +- web/store/issue/issue_detail.store.ts | 106 +++++++++++++++++- web/store/module/modules.store.ts | 15 +-- 9 files changed, 172 insertions(+), 199 deletions(-) diff --git a/web/components/core/modals/link-modal.tsx b/web/components/core/modals/link-modal.tsx index 67ba17a7d..f80b58d33 100644 --- a/web/components/core/modals/link-modal.tsx +++ b/web/components/core/modals/link-modal.tsx @@ -14,8 +14,8 @@ type Props = { handleClose: () => void; data?: ILinkDetails | null; status: boolean; - createIssueLink: (formData: IIssueLink | ModuleLink) => Promise; - updateIssueLink: (formData: IIssueLink | ModuleLink, linkId: string) => Promise; + createIssueLink: (formData: IIssueLink | ModuleLink) => Promise | Promise | void; + updateIssueLink: (formData: IIssueLink | ModuleLink, linkId: string) => Promise | Promise | void; }; const defaultValues: IIssueLink | ModuleLink = { @@ -31,7 +31,7 @@ export const LinkModal: FC = (props) => { handleSubmit, control, reset, - } = useForm({ + } = useForm({ defaultValues, }); @@ -158,8 +158,8 @@ export const LinkModal: FC = (props) => { ? "Updating Link..." : "Update Link" : isSubmitting - ? "Adding Link..." - : "Add Link"} + ? "Adding Link..." + : "Add Link"}
diff --git a/web/components/issues/peek-overview/properties.tsx b/web/components/issues/peek-overview/properties.tsx index 7fa50e07c..25aaf2f88 100644 --- a/web/components/issues/peek-overview/properties.tsx +++ b/web/components/issues/peek-overview/properties.tsx @@ -1,5 +1,5 @@ import { FC, useState } from "react"; -import { mutate } from "swr"; + import { useRouter } from "next/router"; import { observer } from "mobx-react-lite"; // mobx store @@ -17,30 +17,25 @@ import { SidebarPrioritySelect, SidebarStateSelect, } from "../sidebar-select"; -// services -import { IssueService } from "services/issue"; -// hooks -import useToast from "hooks/use-toast"; // components import { CustomDatePicker } from "components/ui"; import { LinkModal, LinksList } from "components/core"; // types -import { IIssue, IIssueLink, TIssuePriorities, ILinkDetails } from "types"; -// fetch-keys -import { ISSUE_DETAILS } from "constants/fetch-keys"; +import { IIssue, TIssuePriorities, ILinkDetails, IIssueLink } from "types"; // constants import { EUserWorkspaceRoles } from "constants/workspace"; interface IPeekOverviewProperties { issue: IIssue; issueUpdate: (issue: Partial) => void; + issueLinkCreate: (data: IIssueLink) => Promise; + issueLinkUpdate: (data: IIssueLink, linkId: string) => Promise; + issueLinkDelete: (linkId: string) => Promise; disableUserActions: boolean; } -const issueService = new IssueService(); - export const PeekOverviewProperties: FC = observer((props) => { - const { issue, issueUpdate, disableUserActions } = props; + const { issue, issueUpdate, issueLinkCreate, issueLinkUpdate, issueLinkDelete, disableUserActions } = props; // states const [linkModal, setLinkModal] = useState(false); const [selectedLinkToUpdate, setSelectedLinkToUpdate] = useState(null); @@ -54,8 +49,6 @@ export const PeekOverviewProperties: FC = observer((pro const router = useRouter(); const { workspaceSlug, projectId } = router.query; - const { setToastAlert } = useToast(); - const handleState = (_state: string) => { issueUpdate({ ...issue, state: _state }); }; @@ -81,61 +74,6 @@ export const PeekOverviewProperties: FC = observer((pro issueUpdate({ ...issue, ...formData }); }; - const handleCreateLink = async (formData: IIssueLink) => { - if (!workspaceSlug || !projectId || !issue) return; - - const payload = { metadata: {}, ...formData }; - - await issueService - .createIssueLink(workspaceSlug as string, projectId as string, issue.id, payload) - .then(() => mutate(ISSUE_DETAILS(issue.id))) - .catch((err) => { - if (err.status === 400) - setToastAlert({ - type: "error", - title: "Error!", - message: "This URL already exists for this issue.", - }); - else - setToastAlert({ - type: "error", - title: "Error!", - message: "Something went wrong. Please try again.", - }); - }); - }; - - const handleUpdateLink = async (formData: IIssueLink, linkId: string) => { - if (!workspaceSlug || !projectId || !issue) return; - - const payload = { metadata: {}, ...formData }; - - const updatedLinks = issue.issue_link.map((l) => - l.id === linkId - ? { - ...l, - title: formData.title, - url: formData.url, - } - : l - ); - - mutate( - ISSUE_DETAILS(issue.id), - (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), - false - ); - - await issueService - .updateIssueLink(workspaceSlug as string, projectId as string, issue.id, linkId, payload) - .then(() => { - mutate(ISSUE_DETAILS(issue.id)); - }) - .catch((err) => { - console.log(err); - }); - }; - const handleCycleOrModuleChange = async () => { if (!workspaceSlug || !projectId) return; @@ -147,27 +85,6 @@ export const PeekOverviewProperties: FC = observer((pro setLinkModal(true); }; - const handleDeleteLink = async (linkId: string) => { - if (!workspaceSlug || !projectId || !issue) return; - - const updatedLinks = issue.issue_link.filter((l) => l.id !== linkId); - - mutate( - ISSUE_DETAILS(issue.id), - (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), - false - ); - - await issueService - .deleteIssueLink(workspaceSlug as string, projectId as string, issue.id, linkId) - .then(() => { - mutate(ISSUE_DETAILS(issue.id)); - }) - .catch((err) => { - console.log(err); - }); - }; - const projectDetails = workspaceSlug ? getProjectById(workspaceSlug.toString(), issue.project) : null; const isEstimateEnabled = projectDetails?.estimate; @@ -187,8 +104,8 @@ export const PeekOverviewProperties: FC = observer((pro }} data={selectedLinkToUpdate} status={selectedLinkToUpdate ? true : false} - createIssueLink={handleCreateLink} - updateIssueLink={handleUpdateLink} + createIssueLink={issueLinkCreate} + updateIssueLink={issueLinkUpdate} />
@@ -373,7 +290,7 @@ export const PeekOverviewProperties: FC = observer((pro {issue?.issue_link && issue.issue_link.length > 0 ? ( = observer((props) => { removeIssueReaction, createIssueSubscription, removeIssueSubscription, + createIssueLink, + updateIssueLink, + deleteIssueLink, getIssue, loader, fetchPeekIssueDetails, @@ -121,6 +124,13 @@ export const IssuePeekOverview: FC = observer((props) => { const issueSubscriptionRemove = () => removeIssueSubscription(workspaceSlug, projectId, issueId); + const issueLinkCreate = (formData: IIssueLink) => createIssueLink(workspaceSlug, projectId, issueId, formData); + + const issueLinkUpdate = (formData: IIssueLink, linkId: string) => + updateIssueLink(workspaceSlug, projectId, issueId, linkId, formData); + + const issueLinkDelete = (linkId: string) => deleteIssueLink(workspaceSlug, projectId, issueId, linkId); + const handleDeleteIssue = async () => { if (isArchived) await deleteArchivedIssue(workspaceSlug, projectId, issue!); else removeIssueFromStructure(workspaceSlug, projectId, issue!); @@ -159,6 +169,9 @@ export const IssuePeekOverview: FC = observer((props) => { issueCommentReactionRemove={issueCommentReactionRemove} issueSubscriptionCreate={issueSubscriptionCreate} issueSubscriptionRemove={issueSubscriptionRemove} + issueLinkCreate={issueLinkCreate} + issueLinkUpdate={issueLinkUpdate} + issueLinkDelete={issueLinkDelete} handleDeleteIssue={handleDeleteIssue} disableUserActions={[5, 10].includes(userRole)} showCommentAccessSpecifier={currentProjectDetails?.is_deployed} diff --git a/web/components/issues/peek-overview/view.tsx b/web/components/issues/peek-overview/view.tsx index 33ea1bcfb..8294784f8 100644 --- a/web/components/issues/peek-overview/view.tsx +++ b/web/components/issues/peek-overview/view.tsx @@ -17,7 +17,7 @@ import { // ui import { Button, CenterPanelIcon, CustomSelect, FullScreenPanelIcon, SidePanelIcon, Spinner } from "@plane/ui"; // types -import { IIssue } from "types"; +import { IIssue, IIssueLink, ILinkDetails } from "types"; interface IIssueView { workspaceSlug: string; @@ -38,6 +38,9 @@ interface IIssueView { issueCommentReactionRemove: (commentId: string, reaction: string) => void; issueSubscriptionCreate: () => void; issueSubscriptionRemove: () => void; + issueLinkCreate: (formData: IIssueLink) => Promise; + issueLinkUpdate: (formData: IIssueLink, linkId: string) => Promise; + issueLinkDelete: (linkId: string) => Promise; handleDeleteIssue: () => Promise; children: ReactNode; disableUserActions?: boolean; @@ -84,6 +87,9 @@ export const IssueView: FC = observer((props) => { issueCommentReactionRemove, issueSubscriptionCreate, issueSubscriptionRemove, + issueLinkCreate, + issueLinkUpdate, + issueLinkDelete, handleDeleteIssue, children, disableUserActions = false, @@ -286,6 +292,9 @@ export const IssueView: FC = observer((props) => { @@ -342,6 +351,9 @@ export const IssueView: FC = observer((props) => {
diff --git a/web/components/issues/sidebar.tsx b/web/components/issues/sidebar.tsx index 60b6106e3..f002b6dda 100644 --- a/web/components/issues/sidebar.tsx +++ b/web/components/issues/sidebar.tsx @@ -84,6 +84,7 @@ export const IssueDetailsSidebar: React.FC = observer((props) => { user: { currentUser, currentProjectRole }, projectState: { states }, projectIssues: { removeIssue }, + issueDetail: { createIssueLink, updateIssueLink, deleteIssueLink }, } = useMobxStore(); const router = useRouter(); @@ -129,80 +130,19 @@ export const IssueDetailsSidebar: React.FC = observer((props) => { [workspaceSlug, projectId, issueId, issueDetail, currentUser] ); - const handleCreateLink = async (formData: IIssueLink) => { - if (!workspaceSlug || !projectId || !issueDetail) return; - - const payload = { metadata: {}, ...formData }; - - await issueService - .createIssueLink(workspaceSlug as string, projectId as string, issueDetail.id, payload) - .then(() => mutate(ISSUE_DETAILS(issueDetail.id))) - .catch((err) => { - if (err.status === 400) - setToastAlert({ - type: "error", - title: "Error!", - message: "This URL already exists for this issue.", - }); - else - setToastAlert({ - type: "error", - title: "Error!", - message: "Something went wrong. Please try again.", - }); - }); + const issueLinkCreate = (formData: IIssueLink) => { + if (!workspaceSlug || !projectId || !issueId) return; + createIssueLink(workspaceSlug.toString(), projectId.toString(), issueId.toString(), formData); }; - const handleUpdateLink = async (formData: IIssueLink, linkId: string) => { - if (!workspaceSlug || !projectId || !issueDetail) return; - - const payload = { metadata: {}, ...formData }; - - const updatedLinks = issueDetail.issue_link.map((l) => - l.id === linkId - ? { - ...l, - title: formData.title, - url: formData.url, - } - : l - ); - - mutate( - ISSUE_DETAILS(issueDetail.id), - (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), - false - ); - - await issueService - .updateIssueLink(workspaceSlug as string, projectId as string, issueDetail.id, linkId, payload) - .then(() => { - mutate(ISSUE_DETAILS(issueDetail.id)); - }) - .catch((err) => { - console.log(err); - }); + const issueLinkUpdate = (formData: IIssueLink, linkId: string) => { + if (!workspaceSlug || !projectId || !issueId) return; + updateIssueLink(workspaceSlug.toString(), projectId.toString(), issueId.toString(), linkId, formData); }; - const handleDeleteLink = async (linkId: string) => { - if (!workspaceSlug || !projectId || !issueDetail) return; - - const updatedLinks = issueDetail.issue_link.filter((l) => l.id !== linkId); - - mutate( - ISSUE_DETAILS(issueDetail.id), - (prevData) => ({ ...(prevData as IIssue), issue_link: updatedLinks }), - false - ); - - await issueService - .deleteIssueLink(workspaceSlug as string, projectId as string, issueDetail.id, linkId) - .then(() => { - mutate(ISSUE_DETAILS(issueDetail.id)); - }) - .catch((err) => { - console.log(err); - }); + const issueLinkDelete = (linkId: string) => { + if (!workspaceSlug || !projectId || !issueId) return; + deleteIssueLink(workspaceSlug.toString(), projectId.toString(), issueId.toString(), linkId); }; const handleCopyText = () => { @@ -264,8 +204,8 @@ export const IssueDetailsSidebar: React.FC = observer((props) => { }} data={selectedLinkToUpdate} status={selectedLinkToUpdate ? true : false} - createIssueLink={handleCreateLink} - updateIssueLink={handleUpdateLink} + createIssueLink={issueLinkCreate} + updateIssueLink={issueLinkUpdate} /> {workspaceSlug && projectId && issueDetail && ( = observer((props) => { { { + data: IIssueLink + ): Promise { return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/`, data) .then((response) => response?.data) .catch((error) => { @@ -202,12 +198,8 @@ export class IssueService extends APIService { projectId: string, issueId: string, linkId: string, - data: { - metadata: any; - title: string; - url: string; - } - ): Promise { + data: IIssueLink + ): Promise { return this.patch( `/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/issue-links/${linkId}/`, data diff --git a/web/services/module.service.ts b/web/services/module.service.ts index c2db73a9b..9f8e73c54 100644 --- a/web/services/module.service.ts +++ b/web/services/module.service.ts @@ -1,7 +1,7 @@ // services import { APIService } from "services/api.service"; // types -import type { IModule, IIssue, ILinkDetails } from "types"; +import type { IModule, IIssue, ILinkDetails, ModuleLink } from "types"; import { IIssueResponse } from "store/issues/types"; import { API_BASE_URL } from "helpers/common.helper"; @@ -132,7 +132,7 @@ export class ModuleService extends APIService { workspaceSlug: string, projectId: string, moduleId: string, - data: Partial + data: ModuleLink ): Promise { return this.post(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/`, data) .then((response) => response?.data) @@ -146,7 +146,7 @@ export class ModuleService extends APIService { projectId: string, moduleId: string, linkId: string, - data: Partial + data: ModuleLink ): Promise { return this.patch( `/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/module-links/${linkId}/`, diff --git a/web/store/issue/issue_detail.store.ts b/web/store/issue/issue_detail.store.ts index 07e7f0c78..fa4651be7 100644 --- a/web/store/issue/issue_detail.store.ts +++ b/web/store/issue/issue_detail.store.ts @@ -4,7 +4,7 @@ import { IssueService, IssueReactionService, IssueCommentService } from "service import { NotificationService } from "services/notification.service"; // types import { RootStore } from "../root"; -import type { IIssue, IIssueActivity } from "types"; +import type { IIssue, IIssueActivity, IIssueLink, ILinkDetails } from "types"; // constants import { groupReactionEmojis } from "constants/issue"; @@ -51,6 +51,21 @@ export interface IIssueDetailStore { createIssueReaction: (workspaceSlug: string, projectId: string, issueId: string, reaction: string) => Promise; removeIssueReaction: (workspaceSlug: string, projectId: string, issueId: string, reaction: string) => Promise; + createIssueLink: ( + workspaceSlug: string, + projectId: string, + issueId: string, + data: IIssueLink + ) => Promise; + updateIssueLink: ( + workspaceSlug: string, + projectId: string, + issueId: string, + linkId: string, + data: IIssueLink + ) => Promise; + deleteIssueLink: (workspaceSlug: string, projectId: string, issueId: string, linkId: string) => Promise; + fetchIssueActivity: (workspaceSlug: string, projectId: string, issueId: string) => Promise; createIssueComment: (workspaceSlug: string, projectId: string, issueId: string, data: any) => Promise; updateIssueComment: ( @@ -147,6 +162,10 @@ export class IssueDetailStore implements IIssueDetailStore { createIssueReaction: action, removeIssueReaction: action, + createIssueLink: action, + updateIssueLink: action, + deleteIssueLink: action, + fetchIssueActivity: action, createIssueComment: action, updateIssueComment: action, @@ -590,6 +609,91 @@ export class IssueDetailStore implements IIssueDetailStore { } }; + createIssueLink = async (workspaceSlug: string, projectId: string, issueId: string, data: IIssueLink) => { + try { + const response = await this.issueService.createIssueLink(workspaceSlug, projectId, issueId, data); + + runInAction(() => { + this.issues = { + ...this.issues, + [issueId]: { + ...this.issues[issueId], + issue_link: [response, ...this.issues[issueId].issue_link], + }, + }; + }); + + return response; + } catch (error) { + console.error("Failed to create link in store", error); + + this.fetchIssueDetails(workspaceSlug, projectId, issueId); + + runInAction(() => { + this.error = error; + }); + + throw error; + } + }; + + updateIssueLink = async ( + workspaceSlug: string, + projectId: string, + issueId: string, + linkId: string, + data: IIssueLink + ) => { + try { + const response = await this.issueService.updateIssueLink(workspaceSlug, projectId, issueId, linkId, data); + + runInAction(() => { + this.issues = { + ...this.issues, + [issueId]: { + ...this.issues[issueId], + issue_link: this.issues[issueId].issue_link.map((link) => (link.id === linkId ? response : link)), + }, + }; + }); + + return response; + } catch (error) { + console.error("Failed to update link in issue store", error); + + this.fetchIssueDetails(workspaceSlug, projectId, issueId); + + runInAction(() => { + this.error = error; + }); + + throw error; + } + }; + + deleteIssueLink = async (workspaceSlug: string, projectId: string, issueId: string, linkId: string) => { + try { + runInAction(() => { + this.issues = { + ...this.issues, + [issueId]: { + ...this.issues[issueId], + issue_link: this.issues[issueId].issue_link.filter((link) => link.id !== linkId), + }, + }; + }); + await this.issueService.deleteIssueLink(workspaceSlug, projectId, issueId, linkId); + } catch (error) { + console.error("Failed to delete link in issue store", error); + + runInAction(() => { + this.error = error; + }); + + throw error; + } + }; + // subscriptions fetchIssueSubscription = async (workspaceSlug: string, projectId: string, issueId: string) => { try { diff --git a/web/store/module/modules.store.ts b/web/store/module/modules.store.ts index beec12ee0..359cdb2da 100644 --- a/web/store/module/modules.store.ts +++ b/web/store/module/modules.store.ts @@ -4,7 +4,7 @@ import { ProjectService } from "services/project"; import { ModuleService } from "services/module.service"; // types import { RootStore } from "../root"; -import { IIssue, IModule, ILinkDetails } from "types"; +import { IIssue, IModule, ILinkDetails, ModuleLink } from "types"; import { IIssueGroupWithSubGroupsStructure, IIssueGroupedStructure, @@ -54,14 +54,14 @@ export interface IModuleStore { workspaceSlug: string, projectId: string, moduleId: string, - data: Partial + data: ModuleLink ) => Promise; updateModuleLink: ( workspaceSlug: string, projectId: string, moduleId: string, linkId: string, - data: Partial + data: ModuleLink ) => Promise; deleteModuleLink: (workspaceSlug: string, projectId: string, moduleId: string, linkId: string) => Promise; @@ -309,12 +309,7 @@ export class ModuleStore implements IModuleStore { } }; - createModuleLink = async ( - workspaceSlug: string, - projectId: string, - moduleId: string, - data: Partial - ) => { + createModuleLink = async (workspaceSlug: string, projectId: string, moduleId: string, data: ModuleLink) => { try { const response = await this.moduleService.createModuleLink(workspaceSlug, projectId, moduleId, data); @@ -354,7 +349,7 @@ export class ModuleStore implements IModuleStore { projectId: string, moduleId: string, linkId: string, - data: Partial + data: ModuleLink ) => { try { const response = await this.moduleService.updateModuleLink(workspaceSlug, projectId, moduleId, linkId, data); From 07c15fcc1fb04238cd2215115f8312ce5c590a04 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:26:57 +0530 Subject: [PATCH 7/9] fix: gantt issues not getting updated (#3075) --- .../issue-layouts/gantt/base-gantt-root.tsx | 28 +++++++++---------- .../issues/issue-layouts/gantt/cycle-root.tsx | 10 +++++-- .../issue-layouts/gantt/module-root.tsx | 10 +++++-- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx index c0b93ce31..f467df208 100644 --- a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx +++ b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx @@ -54,20 +54,19 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan const issues = issueIds.map((id) => issuesResponse?.[id]); - const updateIssue = async (issue: IIssue, payload: IBlockUpdateData) => { + const updateIssueBlockStructure = async (issue: IIssue, data: IBlockUpdateData) => { if (!workspaceSlug) return; - //Todo fix sort order in the structure - await issueStore.updateIssue( - workspaceSlug.toString(), - issue.project, - issue.id, - { - start_date: payload.start_date, - target_date: payload.target_date, - }, - viewId - ); + const payload: any = { ...data }; + if (data.sort_order) payload.sort_order = data.sort_order.newSortOrder; + + await issueStore.updateIssue(workspaceSlug.toString(), issue.project, issue.id, payload, viewId); + }; + + const updateIssue = async (projectId: string, issueId: string, payload: Partial) => { + if (!workspaceSlug) return; + + await issueStore.updateIssue(workspaceSlug.toString(), projectId, issueId, payload, viewId); }; const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; @@ -80,7 +79,7 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan title="Issues" loaderTitle="Issues" blocks={issues ? renderIssueBlocksStructure(issues as IIssueUnGroupedStructure) : null} - blockUpdateHandler={updateIssue} + blockUpdateHandler={updateIssueBlockStructure} blockToRender={(data: IIssue) => } sidebarToRender={(props) => ( = observer((props: IBaseGan projectId={peekProjectId.toString()} issueId={peekIssueId.toString()} handleIssue={async (issueToUpdate) => { - // TODO: update the logic here - await updateIssue(issueToUpdate as IIssue, {}); + await updateIssue(peekProjectId.toString(), peekIssueId.toString(), issueToUpdate); }} /> )} diff --git a/web/components/issues/issue-layouts/gantt/cycle-root.tsx b/web/components/issues/issue-layouts/gantt/cycle-root.tsx index 70f92a933..536650694 100644 --- a/web/components/issues/issue-layouts/gantt/cycle-root.tsx +++ b/web/components/issues/issue-layouts/gantt/cycle-root.tsx @@ -7,9 +7,15 @@ import { useRouter } from "next/router"; export const CycleGanttLayout: React.FC = observer(() => { const router = useRouter(); - const { cycleId } = router.query as { cycleId: string }; + const { cycleId } = router.query; const { cycleIssues: cycleIssueStore, cycleIssuesFilter: cycleIssueFilterStore } = useMobxStore(); - return ; + return ( + + ); }); diff --git a/web/components/issues/issue-layouts/gantt/module-root.tsx b/web/components/issues/issue-layouts/gantt/module-root.tsx index 49467c558..79d1996dc 100644 --- a/web/components/issues/issue-layouts/gantt/module-root.tsx +++ b/web/components/issues/issue-layouts/gantt/module-root.tsx @@ -7,9 +7,15 @@ import { useRouter } from "next/router"; export const ModuleGanttLayout: React.FC = observer(() => { const router = useRouter(); - const { moduleId } = router.query as { moduleId: string }; + const { moduleId } = router.query; const { moduleIssues: moduleIssueStore, moduleIssuesFilter: moduleIssueFilterStore } = useMobxStore(); - return ; + return ( + + ); }); From 1d3745157db136bfa5f9dba8c4ee817e1b636eea Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:27:28 +0530 Subject: [PATCH 8/9] style: cycle and module sidebar improvement (#3076) * style: cycle and module sidebar improvement * chore: issue attachment error message updated --- web/components/cycles/sidebar.tsx | 10 +++++----- .../issues/attachment/attachment-upload.tsx | 6 +++--- web/components/modules/sidebar.tsx | 16 ++++++++++------ 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/web/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx index 834f20397..4ae5c9d8b 100644 --- a/web/components/cycles/sidebar.tsx +++ b/web/components/cycles/sidebar.tsx @@ -281,10 +281,10 @@ export const CycleDetailsSidebar: React.FC = observer((props) => { cycleDetails.total_issues === 0 ? "0 Issue" : cycleDetails.total_issues === cycleDetails.completed_issues - ? cycleDetails.total_issues > 1 - ? `${cycleDetails.total_issues}` - : `${cycleDetails.total_issues}` - : `${cycleDetails.completed_issues}/${cycleDetails.total_issues}`; + ? cycleDetails.total_issues > 1 + ? `${cycleDetails.total_issues}` + : `${cycleDetails.total_issues}` + : `${cycleDetails.completed_issues}/${cycleDetails.total_issues}`; return ( <> @@ -468,7 +468,7 @@ export const CycleDetailsSidebar: React.FC = observer((props) => {
{progressPercentage ? ( - + {progressPercentage ? `${progressPercentage}%` : ""} ) : ( diff --git a/web/components/issues/attachment/attachment-upload.tsx b/web/components/issues/attachment/attachment-upload.tsx index b1608eacb..c1b323e74 100644 --- a/web/components/issues/attachment/attachment-upload.tsx +++ b/web/components/issues/attachment/attachment-upload.tsx @@ -84,10 +84,10 @@ export const IssueAttachmentUpload: React.FC = observer((props) => { disabled: isLoading || disabled, }); + const maxFileSize = envConfig?.file_size_limit ?? MAX_FILE_SIZE; + const fileError = - fileRejections.length > 0 - ? `Invalid file type or size (max ${envConfig?.file_size_limit ?? MAX_FILE_SIZE / 1024 / 1024} MB)` - : null; + fileRejections.length > 0 ? `Invalid file type or size (max ${maxFileSize / 1024 / 1024} MB)` : null; return (
= observer((props) => { moduleDetails.total_issues === 0 ? "0 Issue" : moduleDetails.total_issues === moduleDetails.completed_issues - ? moduleDetails.total_issues > 1 - ? `${moduleDetails.total_issues}` - : `${moduleDetails.total_issues}` - : `${moduleDetails.completed_issues}/${moduleDetails.total_issues}`; + ? moduleDetails.total_issues > 1 + ? `${moduleDetails.total_issues}` + : `${moduleDetails.total_issues}` + : `${moduleDetails.completed_issues}/${moduleDetails.total_issues}`; return ( <> @@ -311,7 +311,11 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => { {moduleStatus?.label ?? "Backlog"} @@ -459,7 +463,7 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => {
{progressPercentage ? ( - + {progressPercentage ? `${progressPercentage}%` : ""} ) : ( From de24b02a0a4856c496c3bf800e6f41807c5e3697 Mon Sep 17 00:00:00 2001 From: Nikhil <118773738+pablohashescobar@users.noreply.github.com> Date: Mon, 11 Dec 2023 22:44:37 +0530 Subject: [PATCH 9/9] fix: user login after account deactivation (#3073) --- apiserver/plane/app/views/authentication.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apiserver/plane/app/views/authentication.py b/apiserver/plane/app/views/authentication.py index 811eeb959..256446313 100644 --- a/apiserver/plane/app/views/authentication.py +++ b/apiserver/plane/app/views/authentication.py @@ -343,13 +343,6 @@ class MagicSignInEndpoint(BaseAPIView): if str(token) == str(user_token): user = User.objects.get(email=email) - if not user.is_active: - return Response( - { - "error": "Your account has been deactivated. Please contact your site administrator." - }, - status=status.HTTP_403_FORBIDDEN, - ) # Send event auth_events.delay( user=user.id,