From 85a8af5125012df46767128bafd1871b9fd05b0f Mon Sep 17 00:00:00 2001
From: rahulramesha <71900764+rahulramesha@users.noreply.github.com>
Date: Fri, 16 Feb 2024 18:20:44 +0530
Subject: [PATCH 1/4] fix: spreadsheet views sorting (#3683)
* fix sorting in spreadsheet all issues
* removing focus border since it is being handled globally
---
.../issues/issue-layouts/roots/all-issue-layout-root.tsx | 2 +-
.../issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx | 2 +-
.../issues/issue-layouts/spreadsheet/issue-column.tsx | 2 +-
.../issue-layouts/spreadsheet/spreadsheet-header-column.tsx | 2 +-
web/store/issue/helpers/issue-helper.store.ts | 2 +-
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx
index 59cf5b9af..1a77ed5fa 100644
--- a/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx
+++ b/web/components/issues/issue-layouts/roots/all-issue-layout-root.tsx
@@ -159,7 +159,7 @@ export const AllIssueLayoutRoot: React.FC = observer(() => {
globalViewId.toString()
);
},
- [updateFilters, workspaceSlug]
+ [updateFilters, workspaceSlug, globalViewId]
);
const renderQuickActions = useCallback(
diff --git a/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx b/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx
index e4efc5137..a94455a0b 100644
--- a/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx
+++ b/web/components/issues/issue-layouts/spreadsheet/base-spreadsheet-root.tsx
@@ -88,7 +88,7 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => {
viewId
);
},
- [issueFiltersStore, projectId, workspaceSlug, viewId]
+ [issueFiltersStore?.updateFilters, projectId, workspaceSlug, viewId]
);
const renderQuickActions = useCallback(
diff --git a/web/components/issues/issue-layouts/spreadsheet/issue-column.tsx b/web/components/issues/issue-layouts/spreadsheet/issue-column.tsx
index 5d2e62fa5..20dd946df 100644
--- a/web/components/issues/issue-layouts/spreadsheet/issue-column.tsx
+++ b/web/components/issues/issue-layouts/spreadsheet/issue-column.tsx
@@ -38,7 +38,7 @@ export const IssueColumn = observer((props: Props) => {
>
{
shouldRenderProperty={shouldRenderProperty}
>
diff --git a/web/store/issue/helpers/issue-helper.store.ts b/web/store/issue/helpers/issue-helper.store.ts
index ff5dba9dd..3fca8aae8 100644
--- a/web/store/issue/helpers/issue-helper.store.ts
+++ b/web/store/issue/helpers/issue-helper.store.ts
@@ -202,7 +202,7 @@ export class IssueHelperStore implements TIssueHelperStore {
if (!memberMap) break;
for (const dataId of dataIdsArray) {
const member = memberMap[dataId];
- if (memberMap && member.first_name) dataValues.push(member.first_name.toLocaleLowerCase());
+ if (member && member.first_name) dataValues.push(member.first_name.toLocaleLowerCase());
}
break;
}
From 665a07f15ab98b33291dcc3b57b21a76ec43de7a Mon Sep 17 00:00:00 2001
From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Date: Fri, 16 Feb 2024 20:01:58 +0530
Subject: [PATCH 2/4] chore: dropdown and peek overview improvement (#3682)
* chore: dropdown focus state improvement
* fix: peek overview dropdown placement fix
---
web/components/dropdowns/cycle.tsx | 19 ++++++++++---------
web/components/dropdowns/estimate.tsx | 13 ++++++++++---
.../dropdowns/member/project-member.tsx | 13 ++++++++++---
.../dropdowns/member/workspace-member.tsx | 17 ++++++++++-------
web/components/dropdowns/module.tsx | 19 ++++++++++---------
web/components/dropdowns/priority.tsx | 17 ++++++++++-------
web/components/dropdowns/project.tsx | 17 ++++++++++-------
web/components/dropdowns/state.tsx | 13 ++++++++++---
web/components/issues/peek-overview/view.tsx | 14 +++-----------
web/components/issues/select/label.tsx | 11 ++++++++++-
10 files changed, 93 insertions(+), 60 deletions(-)
diff --git a/web/components/dropdowns/cycle.tsx b/web/components/dropdowns/cycle.tsx
index e3aa6df11..5086d2d26 100644
--- a/web/components/dropdowns/cycle.tsx
+++ b/web/components/dropdowns/cycle.tsx
@@ -61,6 +61,7 @@ export const CycleDropdown: React.FC = observer((props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -111,23 +112,15 @@ export const CycleDropdown: React.FC = observer((props) => {
const filteredOptions =
query === "" ? options : options?.filter((o) => o.query.toLowerCase().includes(query.toLowerCase()));
- // fetch cycles of the project if not already present in the store
- useEffect(() => {
- if (!workspaceSlug) return;
-
- if (!cycleIds) fetchAllCycles(workspaceSlug, projectId);
- }, [cycleIds, fetchAllCycles, projectId, workspaceSlug]);
-
const selectedCycle = value ? getCycleById(value) : null;
const onOpen = () => {
- if (referenceElement) referenceElement.focus();
+ if (workspaceSlug && !cycleIds) fetchAllCycles(workspaceSlug, projectId);
};
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
- if (referenceElement) referenceElement.blur();
onClose && onClose();
};
@@ -151,6 +144,12 @@ export const CycleDropdown: React.FC = observer((props) => {
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((props) => {
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/estimate.tsx b/web/components/dropdowns/estimate.tsx
index 48558a683..2674fa902 100644
--- a/web/components/dropdowns/estimate.tsx
+++ b/web/components/dropdowns/estimate.tsx
@@ -1,4 +1,4 @@
-import { Fragment, ReactNode, useRef, useState } from "react";
+import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
@@ -60,6 +60,7 @@ export const EstimateDropdown: React.FC = observer((props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -110,13 +111,11 @@ export const EstimateDropdown: React.FC = observer((props) => {
const onOpen = () => {
if (!activeEstimate && workspaceSlug) fetchProjectEstimates(workspaceSlug, projectId);
- if (referenceElement) referenceElement.focus();
};
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
- if (referenceElement) referenceElement.blur();
onClose && onClose();
};
@@ -140,6 +139,12 @@ export const EstimateDropdown: React.FC = observer((props) => {
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((props) => {
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/member/project-member.tsx b/web/components/dropdowns/member/project-member.tsx
index 44cd3a701..d1f285aa5 100644
--- a/web/components/dropdowns/member/project-member.tsx
+++ b/web/components/dropdowns/member/project-member.tsx
@@ -1,4 +1,4 @@
-import { Fragment, useRef, useState } from "react";
+import { Fragment, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
@@ -50,6 +50,7 @@ export const ProjectMemberDropdown: React.FC = observer((props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -103,13 +104,11 @@ export const ProjectMemberDropdown: React.FC = observer((props) => {
const onOpen = () => {
if (!projectMemberIds && workspaceSlug) fetchProjectMembers(workspaceSlug, projectId);
- if (referenceElement) referenceElement.focus();
};
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
- if (referenceElement) referenceElement.blur();
onClose && onClose();
};
@@ -133,6 +132,12 @@ export const ProjectMemberDropdown: React.FC = observer((props) => {
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((props) => {
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/member/workspace-member.tsx b/web/components/dropdowns/member/workspace-member.tsx
index d126b60f7..7a2628cca 100644
--- a/web/components/dropdowns/member/workspace-member.tsx
+++ b/web/components/dropdowns/member/workspace-member.tsx
@@ -1,4 +1,4 @@
-import { Fragment, useRef, useState } from "react";
+import { Fragment, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
@@ -44,6 +44,7 @@ export const WorkspaceMemberDropdown: React.FC = observer((
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -91,19 +92,13 @@ export const WorkspaceMemberDropdown: React.FC = observer((
};
if (multiple) comboboxProps.multiple = true;
- const onOpen = () => {
- if (referenceElement) referenceElement.focus();
- };
-
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
- if (referenceElement) referenceElement.blur();
onClose && onClose();
};
const toggleDropdown = () => {
- if (!isOpen) onOpen();
setIsOpen((prevIsOpen) => !prevIsOpen);
};
@@ -122,6 +117,12 @@ export const WorkspaceMemberDropdown: React.FC = observer((
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/module.tsx b/web/components/dropdowns/module.tsx
index a9b64c1f1..c05eeb97e 100644
--- a/web/components/dropdowns/module.tsx
+++ b/web/components/dropdowns/module.tsx
@@ -166,6 +166,7 @@ export const ModuleDropdown: React.FC = observer((props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -216,21 +217,13 @@ export const ModuleDropdown: React.FC = observer((props) => {
const filteredOptions =
query === "" ? options : options?.filter((o) => o.query.toLowerCase().includes(query.toLowerCase()));
- // fetch modules of the project if not already present in the store
- useEffect(() => {
- if (!workspaceSlug) return;
-
- if (!moduleIds) fetchModules(workspaceSlug, projectId);
- }, [moduleIds, fetchModules, projectId, workspaceSlug]);
-
const onOpen = () => {
- if (referenceElement) referenceElement.focus();
+ if (!moduleIds && workspaceSlug) fetchModules(workspaceSlug, projectId);
};
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
- if (referenceElement) referenceElement.blur();
onClose && onClose();
};
@@ -261,6 +254,12 @@ export const ModuleDropdown: React.FC = observer((props) => {
};
if (multiple) comboboxProps.multiple = true;
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((props) => {
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/priority.tsx b/web/components/dropdowns/priority.tsx
index 1bab9a21e..d519ad9f1 100644
--- a/web/components/dropdowns/priority.tsx
+++ b/web/components/dropdowns/priority.tsx
@@ -1,4 +1,4 @@
-import { Fragment, ReactNode, useRef, useState } from "react";
+import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
import { Check, ChevronDown, Search } from "lucide-react";
@@ -272,6 +272,7 @@ export const PriorityDropdown: React.FC = (props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -305,19 +306,13 @@ export const PriorityDropdown: React.FC = (props) => {
const filteredOptions =
query === "" ? options : options.filter((o) => o.query.toLowerCase().includes(query.toLowerCase()));
- const onOpen = () => {
- if (referenceElement) referenceElement.focus();
- };
-
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
- if (referenceElement) referenceElement.blur();
onClose && onClose();
};
const toggleDropdown = () => {
- if (!isOpen) onOpen();
setIsOpen((prevIsOpen) => !prevIsOpen);
};
@@ -342,6 +337,12 @@ export const PriorityDropdown: React.FC = (props) => {
? BackgroundButton
: TransparentButton;
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= (props) => {
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/project.tsx b/web/components/dropdowns/project.tsx
index 7991c4402..f6fb9205e 100644
--- a/web/components/dropdowns/project.tsx
+++ b/web/components/dropdowns/project.tsx
@@ -1,4 +1,4 @@
-import { Fragment, ReactNode, useRef, useState } from "react";
+import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
@@ -50,6 +50,7 @@ export const ProjectDropdown: React.FC = observer((props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -94,19 +95,13 @@ export const ProjectDropdown: React.FC = observer((props) => {
const selectedProject = value ? getProjectById(value) : null;
- const onOpen = () => {
- if (referenceElement) referenceElement.focus();
- };
-
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
onClose && onClose();
- if (referenceElement) referenceElement.blur();
};
const toggleDropdown = () => {
- if (!isOpen) onOpen();
setIsOpen((prevIsOpen) => !prevIsOpen);
};
@@ -125,6 +120,12 @@ export const ProjectDropdown: React.FC = observer((props) => {
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((props) => {
setQuery(e.target.value)}
diff --git a/web/components/dropdowns/state.tsx b/web/components/dropdowns/state.tsx
index a7f54adfb..fa068fdd0 100644
--- a/web/components/dropdowns/state.tsx
+++ b/web/components/dropdowns/state.tsx
@@ -1,4 +1,4 @@
-import { Fragment, ReactNode, useRef, useState } from "react";
+import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
@@ -52,6 +52,7 @@ export const StateDropdown: React.FC = observer((props) => {
const [isOpen, setIsOpen] = useState(false);
// refs
const dropdownRef = useRef(null);
+ const inputRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -92,14 +93,12 @@ export const StateDropdown: React.FC = observer((props) => {
const onOpen = () => {
if (!statesList && workspaceSlug) fetchProjectStates(workspaceSlug, projectId);
- if (referenceElement) referenceElement.focus();
};
const handleClose = () => {
if (!isOpen) return;
setIsOpen(false);
onClose && onClose();
- if (referenceElement) referenceElement.blur();
};
const toggleDropdown = () => {
@@ -122,6 +121,12 @@ export const StateDropdown: React.FC = observer((props) => {
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isOpen]);
+
return (
= observer((props) => {
setQuery(e.target.value)}
diff --git a/web/components/issues/peek-overview/view.tsx b/web/components/issues/peek-overview/view.tsx
index 82bda41d5..7b6c851ff 100644
--- a/web/components/issues/peek-overview/view.tsx
+++ b/web/components/issues/peek-overview/view.tsx
@@ -126,7 +126,7 @@ export const IssueView: FC = observer((props) => {
/>
)}
-
+
{issueId && (
= observer((props) => {
disabled={disabled}
/>
-
+
) : (
@@ -250,11 +246,7 @@ export const IssueView: FC = observer((props) => {
setIsSubmitting={(value) => setIsSubmitting(value)}
/>
-
+
= observer((props) => {
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
// refs
const dropdownRef = useRef (null);
+ const inputRef = useRef(null);
// popper
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: "bottom-start",
@@ -76,6 +77,12 @@ export const IssueLabelSelect: React.FC = observer((props) => {
useOutsideClickDetector(dropdownRef, handleClose);
+ useEffect(() => {
+ if (isDropdownOpen && inputRef.current) {
+ inputRef.current.focus();
+ }
+ }, [isDropdownOpen]);
+
return (
= observer((props) => {
setQuery(event.target.value)}
placeholder="Search"
From a94c60703195379ef91f37d3c87b5c4343adc0bc Mon Sep 17 00:00:00 2001
From: guru_sainath
Date: Fri, 16 Feb 2024 20:07:04 +0530
Subject: [PATCH 3/4] fix: updated issue title and description components
(#3687)
* fix: issue description fixes
* chore: description html in the archive issue
* chore: changed retrieve viewset
* chore: implemented new issue title description components in inbox, issue-detail and fixed issue in archived store
* chore: removed consoles and empty description update in issue detail
* fix: draft issue empty state image
---------
Co-authored-by: sriram veeraghanta
Co-authored-by: NarayanBavisetti
Co-authored-by: Anmol Singh Bhatia
---
apiserver/plane/app/views/issue.py | 12 +--
web/components/issues/description-input.tsx | 95 +++++++++++++++++++
.../issue-detail/inbox/main-content.tsx | 23 +++--
.../comments/comment-create.tsx | 1 -
.../issues/issue-detail/main-content.tsx | 23 +++--
.../empty-states/draft-issues.tsx | 2 +-
.../issues/issue-layouts/list/block.tsx | 5 +-
.../roots/archived-issue-layout-root.tsx | 2 +-
.../issues/peek-overview/issue-detail.tsx | 42 +++++---
web/components/issues/peek-overview/root.tsx | 22 +++--
web/components/issues/title-input.tsx | 70 ++++++++++++++
.../pages/create-update-page-modal.tsx | 1 -
web/components/project/form.tsx | 2 +-
.../profile/preferences/layout.tsx | 77 +++++++--------
14 files changed, 289 insertions(+), 88 deletions(-)
create mode 100644 web/components/issues/description-input.tsx
create mode 100644 web/components/issues/title-input.tsx
diff --git a/apiserver/plane/app/views/issue.py b/apiserver/plane/app/views/issue.py
index c8845150a..edefade16 100644
--- a/apiserver/plane/app/views/issue.py
+++ b/apiserver/plane/app/views/issue.py
@@ -1209,13 +1209,13 @@ class IssueArchiveViewSet(BaseViewSet):
return Response(issues, status=status.HTTP_200_OK)
def retrieve(self, request, slug, project_id, pk=None):
- issue = Issue.objects.get(
- workspace__slug=slug,
- project_id=project_id,
- archived_at__isnull=False,
- pk=pk,
+ issue = self.get_queryset().filter(pk=pk).first()
+ return Response(
+ IssueDetailSerializer(
+ issue, fields=self.fields, expand=self.expand
+ ).data,
+ status=status.HTTP_200_OK,
)
- return Response(IssueSerializer(issue).data, status=status.HTTP_200_OK)
def unarchive(self, request, slug, project_id, pk=None):
issue = Issue.objects.get(
diff --git a/web/components/issues/description-input.tsx b/web/components/issues/description-input.tsx
new file mode 100644
index 000000000..8f3dc8644
--- /dev/null
+++ b/web/components/issues/description-input.tsx
@@ -0,0 +1,95 @@
+import { FC, useState, useEffect } from "react";
+import { observer } from "mobx-react";
+// components
+import { Loader } from "@plane/ui";
+import { RichReadOnlyEditor, RichTextEditor } from "@plane/rich-text-editor";
+// store hooks
+import { useMention, useWorkspace } from "hooks/store";
+// services
+import { FileService } from "services/file.service";
+const fileService = new FileService();
+// types
+import { TIssueOperations } from "./issue-detail";
+// hooks
+import useDebounce from "hooks/use-debounce";
+import useReloadConfirmations from "hooks/use-reload-confirmation";
+
+export type IssueDescriptionInputProps = {
+ disabled?: boolean;
+ value: string | undefined | null;
+ workspaceSlug: string;
+ setIsSubmitting: (value: "submitting" | "submitted" | "saved") => void;
+ issueOperations: TIssueOperations;
+ projectId: string;
+ issueId: string;
+};
+
+export const IssueDescriptionInput: FC = observer((props) => {
+ const { disabled, value, workspaceSlug, setIsSubmitting, issueId, issueOperations, projectId } = props;
+ // states
+ const [descriptionHTML, setDescriptionHTML] = useState(value);
+ // store hooks
+ const { mentionHighlights, mentionSuggestions } = useMention();
+ const workspaceStore = useWorkspace();
+ // hooks
+ const { setShowAlert } = useReloadConfirmations();
+ const debouncedValue = useDebounce(descriptionHTML, 1500);
+ // computed values
+ const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug)?.id as string;
+
+ useEffect(() => {
+ setDescriptionHTML(value);
+ }, [value]);
+
+ useEffect(() => {
+ if (debouncedValue || debouncedValue === "") {
+ issueOperations
+ .update(workspaceSlug, projectId, issueId, { description_html: debouncedValue }, false)
+ .finally(() => {
+ setIsSubmitting("saved");
+ });
+ }
+ // DO NOT Add more dependencies here. It will cause multiple requests to be sent.
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [debouncedValue]);
+
+ if (!descriptionHTML && descriptionHTML !== "") {
+ return (
+
+
+
+ );
+ }
+
+ if (disabled) {
+ return (
+
+ );
+ }
+
+ return (
+ {
+ setShowAlert(true);
+ setIsSubmitting("submitting");
+ setDescriptionHTML(description_html);
+ }}
+ mentionSuggestions={mentionSuggestions}
+ mentionHighlights={mentionHighlights}
+ />
+ );
+});
diff --git a/web/components/issues/issue-detail/inbox/main-content.tsx b/web/components/issues/issue-detail/inbox/main-content.tsx
index 4a1f79bee..d25fe9260 100644
--- a/web/components/issues/issue-detail/inbox/main-content.tsx
+++ b/web/components/issues/issue-detail/inbox/main-content.tsx
@@ -3,7 +3,9 @@ import { observer } from "mobx-react-lite";
// hooks
import { useIssueDetail, useProjectState, useUser } from "hooks/store";
// components
-import { IssueDescriptionForm, IssueUpdateStatus, TIssueOperations } from "components/issues";
+import { IssueUpdateStatus, TIssueOperations } from "components/issues";
+import { IssueTitleInput } from "../../title-input";
+import { IssueDescriptionInput } from "../../description-input";
import { IssueReaction } from "../reactions";
import { IssueActivity } from "../issue-activity";
import { InboxIssueStatus } from "../../../inbox/inbox-issue-status";
@@ -57,15 +59,24 @@ export const InboxIssueMainContent: React.FC = observer((props) => {
- setIsSubmitting(value)}
- isSubmitting={isSubmitting}
- issue={issue}
issueOperations={issueOperations}
disabled={!is_editable}
+ value={issue.name}
+ />
+
+ setIsSubmitting(value)}
+ issueOperations={issueOperations}
+ disabled={!is_editable}
+ value={issue.description_html}
/>
{currentUser && (
diff --git a/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx b/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx
index bb79c9817..bf5b15266 100644
--- a/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx
+++ b/web/components/issues/issue-detail/issue-activity/comments/comment-create.tsx
@@ -81,7 +81,6 @@ export const IssueCommentCreate: FC = (props) => {
render={({ field: { value, onChange } }) => (
{
- console.log("yo");
handleSubmit(onSubmit)(e);
}}
cancelUploadImage={fileService.cancelUpload}
diff --git a/web/components/issues/issue-detail/main-content.tsx b/web/components/issues/issue-detail/main-content.tsx
index 075525801..14860a0cf 100644
--- a/web/components/issues/issue-detail/main-content.tsx
+++ b/web/components/issues/issue-detail/main-content.tsx
@@ -3,7 +3,9 @@ import { observer } from "mobx-react-lite";
// hooks
import { useIssueDetail, useProjectState, useUser } from "hooks/store";
// components
-import { IssueDescriptionForm, IssueAttachmentRoot, IssueUpdateStatus } from "components/issues";
+import { IssueAttachmentRoot, IssueUpdateStatus } from "components/issues";
+import { IssueTitleInput } from "../title-input";
+import { IssueDescriptionInput } from "../description-input";
import { IssueParentDetail } from "./parent";
import { IssueReaction } from "./reactions";
import { SubIssuesRoot } from "../sub-issues";
@@ -61,15 +63,24 @@ export const IssueMainContent: React.FC = observer((props) => {
- setIsSubmitting(value)}
- isSubmitting={isSubmitting}
- issue={issue}
issueOperations={issueOperations}
disabled={!is_editable}
+ value={issue.name}
+ />
+
+ setIsSubmitting(value)}
+ issueOperations={issueOperations}
+ disabled={!is_editable}
+ value={issue.description_html}
/>
{currentUser && (
diff --git a/web/components/issues/issue-layouts/empty-states/draft-issues.tsx b/web/components/issues/issue-layouts/empty-states/draft-issues.tsx
index 347778d8f..c496cc5fe 100644
--- a/web/components/issues/issue-layouts/empty-states/draft-issues.tsx
+++ b/web/components/issues/issue-layouts/empty-states/draft-issues.tsx
@@ -42,7 +42,7 @@ export const ProjectDraftEmptyState: React.FC = observer(() => {
const isLightMode = resolvedTheme ? resolvedTheme === "light" : currentUser?.theme.theme === "light";
const currentLayoutEmptyStateImagePath = getEmptyStateImagePath("empty-filters", activeLayout ?? "list", isLightMode);
- const EmptyStateImagePath = getEmptyStateImagePath("draft", "empty-issues", isLightMode);
+ const EmptyStateImagePath = getEmptyStateImagePath("draft", "draft-issues-empty", isLightMode);
const issueFilterCount = size(
Object.fromEntries(
diff --git a/web/components/issues/issue-layouts/list/block.tsx b/web/components/issues/issue-layouts/list/block.tsx
index ceec7b219..2e48e1f1c 100644
--- a/web/components/issues/issue-layouts/list/block.tsx
+++ b/web/components/issues/issue-layouts/list/block.tsx
@@ -50,9 +50,8 @@ export const IssueBlock: React.FC = observer((props: IssueBlock
return (
{displayProperties && displayProperties?.key && (
diff --git a/web/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx b/web/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx
index 5f049d4c3..2ae7ae510 100644
--- a/web/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx
+++ b/web/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx
@@ -54,7 +54,7 @@ export const ArchivedIssueLayoutRoot: React.FC = observer(() => {
-
+
)}
diff --git a/web/components/issues/peek-overview/issue-detail.tsx b/web/components/issues/peek-overview/issue-detail.tsx
index 8c5101938..7bc1b1b03 100644
--- a/web/components/issues/peek-overview/issue-detail.tsx
+++ b/web/components/issues/peek-overview/issue-detail.tsx
@@ -1,10 +1,15 @@
-import { FC } from "react";
-// hooks
-import { useIssueDetail, useProject, useUser } from "hooks/store";
-// components
-import { IssueDescriptionForm, TIssueOperations } from "components/issues";
-import { IssueReaction } from "../issue-detail/reactions";
+import { FC, useCallback, useEffect, useState } from "react";
import { observer } from "mobx-react";
+// store hooks
+import { useIssueDetail, useProject, useUser } from "hooks/store";
+// hooks
+import useReloadConfirmations from "hooks/use-reload-confirmation";
+// components
+import { TIssueOperations } from "components/issues";
+import { IssueReaction } from "../issue-detail/reactions";
+import { IssueTitleInput } from "../title-input";
+import { IssueDescriptionInput } from "../description-input";
+import { debounce } from "lodash";
interface IPeekOverviewIssueDetails {
workspaceSlug: string;
@@ -17,17 +22,18 @@ interface IPeekOverviewIssueDetails {
}
export const PeekOverviewIssueDetails: FC = observer((props) => {
- const { workspaceSlug, projectId, issueId, issueOperations, disabled, isSubmitting, setIsSubmitting } = props;
+ const { workspaceSlug, issueId, issueOperations, disabled, setIsSubmitting } = props;
// store hooks
const { getProjectById } = useProject();
const { currentUser } = useUser();
const {
issue: { getIssueById },
} = useIssueDetail();
-
// derived values
const issue = getIssueById(issueId);
+
if (!issue) return <>>;
+
const projectDetails = getProjectById(issue?.project_id);
return (
@@ -35,20 +41,28 @@ export const PeekOverviewIssueDetails: FC = observer(
{projectDetails?.identifier}-{issue?.sequence_id}
- setIsSubmitting(value)}
- isSubmitting={isSubmitting}
- issue={issue}
issueOperations={issueOperations}
disabled={disabled}
+ value={issue.name}
+ />
+ setIsSubmitting(value)}
+ issueOperations={issueOperations}
+ disabled={disabled}
+ value={issue.description_html}
/>
{currentUser && (
diff --git a/web/components/issues/peek-overview/root.tsx b/web/components/issues/peek-overview/root.tsx
index b491ebe36..c49c0a503 100644
--- a/web/components/issues/peek-overview/root.tsx
+++ b/web/components/issues/peek-overview/root.tsx
@@ -69,20 +69,11 @@ export const IssuePeekOverview: FC = observer((props) => {
// state
const [loader, setLoader] = useState(false);
- useEffect(() => {
- if (peekIssue) {
- setLoader(true);
- fetchIssue(peekIssue.workspaceSlug, peekIssue.projectId, peekIssue.issueId).finally(() => {
- setLoader(false);
- });
- }
- }, [peekIssue, fetchIssue]);
-
const issueOperations: TIssuePeekOperations = useMemo(
() => ({
fetch: async (workspaceSlug: string, projectId: string, issueId: string) => {
try {
- await fetchIssue(workspaceSlug, projectId, issueId);
+ await fetchIssue(workspaceSlug, projectId, issueId, is_archived);
} catch (error) {
console.error("Error fetching the parent issue");
}
@@ -324,9 +315,20 @@ export const IssuePeekOverview: FC = observer((props) => {
removeModulesFromIssue,
setToastAlert,
onIssueUpdate,
+ captureIssueEvent,
+ router.asPath,
]
);
+ useEffect(() => {
+ if (peekIssue) {
+ setLoader(true);
+ issueOperations.fetch(peekIssue.workspaceSlug, peekIssue.projectId, peekIssue.issueId).finally(() => {
+ setLoader(false);
+ });
+ }
+ }, [peekIssue, issueOperations]);
+
if (!peekIssue?.workspaceSlug || !peekIssue?.projectId || !peekIssue?.issueId) return <>>;
const issue = getIssueById(peekIssue.issueId) || undefined;
diff --git a/web/components/issues/title-input.tsx b/web/components/issues/title-input.tsx
new file mode 100644
index 000000000..2cd031b4f
--- /dev/null
+++ b/web/components/issues/title-input.tsx
@@ -0,0 +1,70 @@
+import { FC, useState, useEffect, useCallback } from "react";
+import { observer } from "mobx-react";
+// components
+import { TextArea } from "@plane/ui";
+// types
+import { TIssueOperations } from "./issue-detail";
+// hooks
+import useDebounce from "hooks/use-debounce";
+import useReloadConfirmations from "hooks/use-reload-confirmation";
+
+export type IssueTitleInputProps = {
+ disabled?: boolean;
+ value: string | undefined | null;
+ workspaceSlug: string;
+ setIsSubmitting: (value: "submitting" | "submitted" | "saved") => void;
+ issueOperations: TIssueOperations;
+ projectId: string;
+ issueId: string;
+};
+
+export const IssueTitleInput: FC = observer((props) => {
+ const { disabled, value, workspaceSlug, setIsSubmitting, issueId, issueOperations, projectId } = props;
+ // states
+ const [title, setTitle] = useState("");
+ // hooks
+ const { setShowAlert } = useReloadConfirmations();
+ const debouncedValue = useDebounce(title, 1500);
+
+ useEffect(() => {
+ if (value) setTitle(value);
+ }, [value]);
+
+ useEffect(() => {
+ if (debouncedValue) {
+ issueOperations.update(workspaceSlug, projectId, issueId, { name: debouncedValue }, false).finally(() => {
+ setIsSubmitting("saved");
+ });
+ }
+ // DO NOT Add more dependencies here. It will cause multiple requests to be sent.
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [debouncedValue]);
+
+ const handleTitleChange = useCallback(
+ (e: React.ChangeEvent) => {
+ setShowAlert(true);
+ setIsSubmitting("submitting");
+ setTitle(e.target.value);
+ },
+ [setIsSubmitting, setShowAlert]
+ );
+
+ return (
+
+
+
+ 255 ? "text-red-500" : ""}`}>{title.length}
+ /255
+
+
+ );
+});
diff --git a/web/components/pages/create-update-page-modal.tsx b/web/components/pages/create-update-page-modal.tsx
index e81a0040b..eea7e9d7f 100644
--- a/web/components/pages/create-update-page-modal.tsx
+++ b/web/components/pages/create-update-page-modal.tsx
@@ -68,7 +68,6 @@ export const CreateUpdatePageModal: FC = (props) => {
state: "SUCCESS",
},
});
- console.log("Page updated successfully", pageStore);
} else {
await createProjectPage(formData);
}
diff --git a/web/components/project/form.tsx b/web/components/project/form.tsx
index f46dee6b9..7fd741cb9 100644
--- a/web/components/project/form.tsx
+++ b/web/components/project/form.tsx
@@ -79,7 +79,7 @@ export const ProjectDetailsForm: FC = (props) => {
return updateProject(workspaceSlug.toString(), project.id, payload)
.then((res) => {
const changed_properties = Object.keys(dirtyFields);
- console.log(dirtyFields);
+
captureProjectEvent({
eventName: PROJECT_UPDATED,
payload: {
diff --git a/web/layouts/settings-layout/profile/preferences/layout.tsx b/web/layouts/settings-layout/profile/preferences/layout.tsx
index 315412337..0e1d31587 100644
--- a/web/layouts/settings-layout/profile/preferences/layout.tsx
+++ b/web/layouts/settings-layout/profile/preferences/layout.tsx
@@ -20,54 +20,55 @@ export const ProfilePreferenceSettingsLayout: FC {
- const item = router.asPath.split('/');
+ const item = router.asPath.split("/");
let splittedItem = item[item.length - 1];
splittedItem = splittedItem.replace(splittedItem[0], splittedItem[0].toUpperCase());
- console.log(splittedItem);
return splittedItem;
- }
+ };
const profilePreferenceLinks: Array<{
label: string;
href: string;
}> = [
- {
- label: "Theme",
- href: `/profile/preferences/theme`,
- },
- {
- label: "Email",
- href: `/profile/preferences/email`,
- },
- ];
+ {
+ label: "Theme",
+ href: `/profile/preferences/theme`,
+ },
+ {
+ label: "Email",
+ href: `/profile/preferences/email`,
+ },
+ ];
return (
-
- themeStore.toggleSidebar()} />
-
- {showMenuItem()}
-
-
- }
- customButtonClassName="flex flex-grow justify-start text-custom-text-200 text-sm"
- >
- <>>
- {profilePreferenceLinks.map((link) => (
-
- {link.label}
-
- ))}
-
-
- }>
+
+ themeStore.toggleSidebar()} />
+
+ {showMenuItem()}
+
+
+ }
+ customButtonClassName="flex flex-grow justify-start text-custom-text-200 text-sm"
+ >
+ <>>
+ {profilePreferenceLinks.map((link) => (
+
+
+ {link.label}
+
+
+ ))}
+
+
+ }
+ >
From 41e812a811873ec7a14b787e923981dafb5323d5 Mon Sep 17 00:00:00 2001
From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com>
Date: Fri, 16 Feb 2024 20:07:38 +0530
Subject: [PATCH 4/4] fix: quick action copy link action (#3686)
---
.../issue-layouts/list/list-view-types.d.ts | 2 ++
.../quick-action-dropdowns/all-issue.tsx | 21 +++++++++-------
.../quick-action-dropdowns/archived-issue.tsx | 6 ++---
.../quick-action-dropdowns/cycle-issue.tsx | 25 +++++++++++--------
.../quick-action-dropdowns/module-issue.tsx | 25 +++++++++++--------
.../quick-action-dropdowns/project-issue.tsx | 15 ++++++-----
6 files changed, 54 insertions(+), 40 deletions(-)
diff --git a/web/components/issues/issue-layouts/list/list-view-types.d.ts b/web/components/issues/issue-layouts/list/list-view-types.d.ts
index 1838316cb..e369410af 100644
--- a/web/components/issues/issue-layouts/list/list-view-types.d.ts
+++ b/web/components/issues/issue-layouts/list/list-view-types.d.ts
@@ -1,3 +1,5 @@
+import { TIssue } from "@plane/types";
+
export interface IQuickActionProps {
issue: TIssue;
handleDelete: () => Promise;
diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx
index f97f1ea86..bc6518911 100644
--- a/web/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx
+++ b/web/components/issues/issue-layouts/quick-action-dropdowns/all-issue.tsx
@@ -2,6 +2,7 @@ import { useState } from "react";
import { useRouter } from "next/router";
import { CustomMenu } from "@plane/ui";
import { Copy, Link, Pencil, Trash2 } from "lucide-react";
+import omit from "lodash/omit";
// hooks
import useToast from "hooks/use-toast";
import { useEventTracker } from "hooks/store";
@@ -30,7 +31,7 @@ export const AllIssueQuickActions: React.FC = (props) => {
const { setToastAlert } = useToast();
const handleCopyIssueLink = () => {
- copyUrlToClipboard(`/${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() =>
+ copyUrlToClipboard(`/${workspaceSlug}/projects/${issue.project_id}/issues/${issue.id}`).then(() =>
setToastAlert({
type: "success",
title: "Link copied",
@@ -39,11 +40,13 @@ export const AllIssueQuickActions: React.FC = (props) => {
);
};
- const duplicateIssuePayload = {
- ...issue,
- name: `${issue.name} (copy)`,
- };
- delete duplicateIssuePayload.id;
+ const duplicateIssuePayload = omit(
+ {
+ ...issue,
+ name: `${issue.name} (copy)`,
+ },
+ ["id"]
+ );
return (
<>
@@ -87,7 +90,7 @@ export const AllIssueQuickActions: React.FC = (props) => {
{
setTrackElement("Global issues");
- setIssueToEdit(issue);
+ setIssueToEdit(issue);
setCreateUpdateIssueModal(true);
}}
>
@@ -99,7 +102,7 @@ export const AllIssueQuickActions: React.FC = (props) => {
{
setTrackElement("Global issues");
- setCreateUpdateIssueModal(true);
+ setCreateUpdateIssueModal(true);
}}
>
@@ -110,7 +113,7 @@ export const AllIssueQuickActions: React.FC = (props) => {
{
setTrackElement("Global issues");
- setDeleteIssueModal(true);
+ setDeleteIssueModal(true);
}}
>
diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx
index f96270176..e331d7182 100644
--- a/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx
+++ b/web/components/issues/issue-layouts/quick-action-dropdowns/archived-issue.tsx
@@ -4,7 +4,7 @@ import { CustomMenu } from "@plane/ui";
import { Link, Trash2 } from "lucide-react";
// hooks
import useToast from "hooks/use-toast";
-import { useEventTracker, useIssues ,useUser} from "hooks/store";
+import { useEventTracker, useIssues, useUser } from "hooks/store";
// components
import { DeleteArchivedIssueModal } from "components/issues";
// helpers
@@ -37,7 +37,7 @@ export const ArchivedIssueQuickActions: React.FC = (props) =>
const activeLayout = `${issuesFilter.issueFilters?.displayFilters?.layout} layout`;
const handleCopyIssueLink = () => {
- copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/archived-issues/${issue.id}`).then(() =>
+ copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project_id}/archived-issues/${issue.id}`).then(() =>
setToastAlert({
type: "success",
title: "Link copied",
@@ -75,7 +75,7 @@ export const ArchivedIssueQuickActions: React.FC = (props) =>
{
setTrackElement(activeLayout);
- setDeleteIssueModal(true);
+ setDeleteIssueModal(true);
}}
>
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 8c3beb3d2..4699b1c81 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
@@ -2,9 +2,10 @@ import { useState } from "react";
import { useRouter } from "next/router";
import { CustomMenu } from "@plane/ui";
import { Copy, Link, Pencil, Trash2, XCircle } from "lucide-react";
+import omit from "lodash/omit";
// hooks
import useToast from "hooks/use-toast";
-import { useEventTracker, useIssues,useUser } from "hooks/store";
+import { useEventTracker, useIssues, useUser } from "hooks/store";
// components
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
// helpers
@@ -49,7 +50,7 @@ export const CycleIssueQuickActions: React.FC = (props) => {
const activeLayout = `${issuesFilter.issueFilters?.displayFilters?.layout} layout`;
const handleCopyIssueLink = () => {
- copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() =>
+ copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project_id}/issues/${issue.id}`).then(() =>
setToastAlert({
type: "success",
title: "Link copied",
@@ -58,11 +59,13 @@ export const CycleIssueQuickActions: React.FC = (props) => {
);
};
- const duplicateIssuePayload = {
- ...issue,
- name: `${issue.name} (copy)`,
- };
- delete duplicateIssuePayload.id;
+ const duplicateIssuePayload = omit(
+ {
+ ...issue,
+ name: `${issue.name} (copy)`,
+ },
+ ["id"]
+ );
return (
<>
@@ -107,10 +110,10 @@ export const CycleIssueQuickActions: React.FC = (props) => {
onClick={() => {
setIssueToEdit({
...issue,
- cycle: cycleId?.toString() ?? null,
+ cycle_id: cycleId?.toString() ?? null,
});
setTrackElement(activeLayout);
- setCreateUpdateIssueModal(true);
+ setCreateUpdateIssueModal(true);
}}
>
@@ -131,7 +134,7 @@ export const CycleIssueQuickActions: React.FC = (props) => {
{
setTrackElement(activeLayout);
- setCreateUpdateIssueModal(true);
+ setCreateUpdateIssueModal(true);
}}
>
@@ -142,7 +145,7 @@ export const CycleIssueQuickActions: React.FC = (props) => {
{
setTrackElement(activeLayout);
- setDeleteIssueModal(true);
+ setDeleteIssueModal(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 a3ed73ec0..6eabfda59 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
@@ -2,9 +2,10 @@ import { useState } from "react";
import { useRouter } from "next/router";
import { CustomMenu } from "@plane/ui";
import { Copy, Link, Pencil, Trash2, XCircle } from "lucide-react";
+import omit from "lodash/omit";
// hooks
import useToast from "hooks/use-toast";
-import { useIssues, useEventTracker ,useUser } from "hooks/store";
+import { useIssues, useEventTracker, useUser } from "hooks/store";
// components
import { CreateUpdateIssueModal, DeleteIssueModal } from "components/issues";
// helpers
@@ -49,7 +50,7 @@ export const ModuleIssueQuickActions: React.FC = (props) => {
const activeLayout = `${issuesFilter.issueFilters?.displayFilters?.layout} layout`;
const handleCopyIssueLink = () => {
- copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() =>
+ copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project_id}/issues/${issue.id}`).then(() =>
setToastAlert({
type: "success",
title: "Link copied",
@@ -58,11 +59,13 @@ export const ModuleIssueQuickActions: React.FC = (props) => {
);
};
- const duplicateIssuePayload = {
- ...issue,
- name: `${issue.name} (copy)`,
- };
- delete duplicateIssuePayload.id;
+ const duplicateIssuePayload = omit(
+ {
+ ...issue,
+ name: `${issue.name} (copy)`,
+ },
+ ["id"]
+ );
return (
<>
@@ -105,9 +108,9 @@ export const ModuleIssueQuickActions: React.FC = (props) => {
<>
{
- setIssueToEdit({ ...issue, module: moduleId?.toString() ?? null });
+ setIssueToEdit({ ...issue, module_ids: moduleId ? [moduleId.toString()] : [] });
setTrackElement(activeLayout);
- setCreateUpdateIssueModal(true);
+ setCreateUpdateIssueModal(true);
}}
>
@@ -128,7 +131,7 @@ export const ModuleIssueQuickActions: React.FC = (props) => {
{
setTrackElement(activeLayout);
- setCreateUpdateIssueModal(true);
+ setCreateUpdateIssueModal(true);
}}
>
@@ -141,7 +144,7 @@ export const ModuleIssueQuickActions: React.FC = (props) => {
e.preventDefault();
e.stopPropagation();
setTrackElement(activeLayout);
- setDeleteIssueModal(true);
+ setDeleteIssueModal(true);
}}
>
diff --git a/web/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx b/web/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx
index 65adc8542..1d6d88f25 100644
--- a/web/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx
+++ b/web/components/issues/issue-layouts/quick-action-dropdowns/project-issue.tsx
@@ -2,6 +2,7 @@ import { useState } from "react";
import { useRouter } from "next/router";
import { CustomMenu } from "@plane/ui";
import { Copy, Link, Pencil, Trash2 } from "lucide-react";
+import omit from "lodash/omit";
// hooks
import { useEventTracker, useIssues, useUser } from "hooks/store";
import useToast from "hooks/use-toast";
@@ -39,7 +40,7 @@ export const ProjectIssueQuickActions: React.FC = (props) =>
const { setToastAlert } = useToast();
const handleCopyIssueLink = () => {
- copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`).then(() =>
+ copyUrlToClipboard(`${workspaceSlug}/projects/${issue.project_id}/issues/${issue.id}`).then(() =>
setToastAlert({
type: "success",
title: "Link copied",
@@ -48,11 +49,13 @@ export const ProjectIssueQuickActions: React.FC = (props) =>
);
};
- const duplicateIssuePayload = {
- ...issue,
- name: `${issue.name} (copy)`,
- };
- delete duplicateIssuePayload.id;
+ const duplicateIssuePayload = omit(
+ {
+ ...issue,
+ name: `${issue.name} (copy)`,
+ },
+ ["id"]
+ );
const isDraftIssue = router?.asPath?.includes("draft-issues") || false;
| |