diff --git a/apps/app/components/common/board-view/single-issue.tsx b/apps/app/components/common/board-view/single-issue.tsx index a099c29b1..cd84697e9 100644 --- a/apps/app/components/common/board-view/single-issue.tsx +++ b/apps/app/components/common/board-view/single-issue.tsx @@ -25,7 +25,16 @@ import { AssigneesList, CustomDatePicker } from "components/ui"; import { renderShortNumericDateFormat, findHowManyDaysLeft } from "helpers/date-time.helper"; import { addSpaceIfCamelCase } from "helpers/string.helper"; // types -import { IIssue, IUserLite, IWorkspaceMember, Properties, UserAuth } from "types"; +import { + CycleIssueResponse, + IIssue, + IssueResponse, + IUserLite, + IWorkspaceMember, + ModuleIssueResponse, + Properties, + UserAuth, +} from "types"; // common import { PRIORITIES } from "constants/"; import { @@ -80,6 +89,60 @@ const SingleBoardIssue: React.FC = ({ const partialUpdateIssue = (formData: Partial) => { if (!workspaceSlug || !projectId) return; + if (typeId) { + mutate( + CYCLE_ISSUES(typeId ?? ""), + (prevData) => { + const updatedIssues = (prevData ?? []).map((p) => { + if (p.issue_detail.id === issue.id) { + return { + ...p, + issue_detail: { + ...p.issue_detail, + ...formData, + }, + }; + } + return p; + }); + return [...updatedIssues]; + }, + false + ); + + mutate( + MODULE_ISSUES(typeId ?? ""), + (prevData) => { + const updatedIssues = (prevData ?? []).map((p) => { + if (p.issue_detail.id === issue.id) { + return { + ...p, + issue_detail: { + ...p.issue_detail, + ...formData, + }, + }; + } + return p; + }); + return [...updatedIssues]; + }, + false + ); + } + + mutate( + PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), + (prevData) => ({ + ...(prevData as IssueResponse), + results: (prevData?.results ?? []).map((p) => { + if (p.id === issue.id) return { ...p, ...formData }; + return p; + }), + }), + false + ); + issuesService .patchIssue(workspaceSlug as string, projectId as string, issue.id, formData) .then((res) => { @@ -270,13 +333,11 @@ const SingleBoardIssue: React.FC = ({ { + onChange={(val) => partialUpdateIssue({ - target_date: val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null, - }); - }} + target_date: val, + }) + } className={issue?.target_date ? "w-[6.5rem]" : "w-[3rem] text-center"} /> {/* = ({ const partialUpdateIssue = (formData: Partial) => { if (!workspaceSlug || !projectId) return; + if (typeId) { + mutate( + CYCLE_ISSUES(typeId ?? ""), + (prevData) => { + const updatedIssues = (prevData ?? []).map((p) => { + if (p.issue_detail.id === issue.id) { + return { + ...p, + issue_detail: { + ...p.issue_detail, + ...formData, + }, + }; + } + return p; + }); + return [...updatedIssues]; + }, + false + ); + + mutate( + MODULE_ISSUES(typeId ?? ""), + (prevData) => { + const updatedIssues = (prevData ?? []).map((p) => { + if (p.issue_detail.id === issue.id) { + return { + ...p, + issue_detail: { + ...p.issue_detail, + ...formData, + }, + }; + } + return p; + }); + return [...updatedIssues]; + }, + false + ); + } + + mutate( + PROJECT_ISSUES_LIST(workspaceSlug as string, projectId as string), + (prevData) => ({ + ...(prevData as IssueResponse), + results: (prevData?.results ?? []).map((p) => { + if (p.id === issue.id) return { ...p, ...formData }; + return p; + }), + }), + false + ); + issuesService .patchIssue(workspaceSlug as string, projectId as string, issue.id, formData) .then((res) => { @@ -255,44 +312,24 @@ const SingleListIssue: React.FC = ({ { + onChange={(val) => partialUpdateIssue({ - target_date: val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null, - }); - }} + target_date: val, + }) + } className={issue?.target_date ? "w-[6.5rem]" : "w-[3rem] text-center"} /> - {/* { - partialUpdateIssue({ - target_date: val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null, - }); - }} - dateFormat="dd-MM-yyyy" - className={`cursor-pointer rounded-md border px-2 py-[3px] text-xs shadow-sm duration-300 hover:bg-gray-100 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 ${ - issue?.target_date ? "w-[4.5rem]" : "w-[3rem] text-center" - }`} - isClearable - /> */}
Due date
{renderShortNumericDateFormat(issue.target_date ?? "")}
- {issue.target_date && - (issue.target_date < new Date().toISOString() + {issue.target_date + ? issue.target_date < new Date().toISOString() ? `Due date has passed by ${findHowManyDaysLeft(issue.target_date)} days` : findHowManyDaysLeft(issue.target_date) <= 3 ? `Due date is in ${findHowManyDaysLeft(issue.target_date)} days` - : "Due date")} + : "Due date" + : "N/A"}
diff --git a/apps/app/components/core/view.tsx b/apps/app/components/core/view.tsx index 987b09fe9..1fe147f22 100644 --- a/apps/app/components/core/view.tsx +++ b/apps/app/components/core/view.tsx @@ -47,10 +47,10 @@ const View: React.FC = ({ issues }) => { ); return ( -
-
- {issues && ( - <> + <> + {issues && issues.length > 0 && ( +
+
- - )} -
- - {({ open }) => ( - <> - - View - +
+ + {({ open }) => ( + <> + + View + - - -
- {issues && ( -
-
-

Group by

- option.key === groupByProperty)?.name ?? - "Select" - } - width="lg" - > - {groupByOptions.map((option) => ( - setGroupByProperty(option.key)} + + +
+ {issues && ( +
+
+

Group by

+ option.key === groupByProperty) + ?.name ?? "Select" + } + width="lg" > - {option.name} - - ))} - -
-
-

Order by

- option.key === orderBy)?.name ?? - "Select" - } - width="lg" - > - {orderByOptions.map((option) => - groupByProperty === "priority" && option.key === "priority" ? null : ( - setOrderBy(option.key)} - > - {option.name} - - ) - )} - -
-
-

Issue type

- option.key === filterIssue)?.name ?? - "Select" - } - width="lg" - > - {filterIssueOptions.map((option) => ( - setFilterIssue(option.key)} + {groupByOptions.map((option) => ( + setGroupByProperty(option.key)} + > + {option.name} + + ))} + +
+
+

Order by

+ option.key === orderBy)?.name ?? + "Select" + } + width="lg" > - {option.name} - + {orderByOptions.map((option) => + groupByProperty === "priority" && + option.key === "priority" ? null : ( + setOrderBy(option.key)} + > + {option.name} + + ) + )} + +
+
+

Issue type

+ option.key === filterIssue) + ?.name ?? "Select" + } + width="lg" + > + {filterIssueOptions.map((option) => ( + setFilterIssue(option.key)} + > + {option.name} + + ))} + +
+
+ + +
+
+ )} +
+

Display Properties

+
+ {Object.keys(properties).map((key) => ( + ))} - -
-
- - +
- )} -
-

Display Properties

-
- {Object.keys(properties).map((key) => ( - - ))} -
-
-
- - - - )} - -
+ + + + )} + +
+ )} + ); }; diff --git a/apps/app/components/issues/description-form.tsx b/apps/app/components/issues/description-form.tsx index 9882eee36..84ae61643 100644 --- a/apps/app/components/issues/description-form.tsx +++ b/apps/app/components/issues/description-form.tsx @@ -17,7 +17,7 @@ const RemirrorRichTextEditor = dynamic(() => import("components/rich-text-editor ), }); // types -import { IIssue } from "types"; +import { IIssue, UserAuth } from "types"; import useToast from "hooks/use-toast"; export interface IssueDescriptionFormValues { @@ -29,9 +29,14 @@ export interface IssueDescriptionFormValues { export interface IssueDetailsProps { issue: IIssue; handleFormSubmit: (value: IssueDescriptionFormValues) => void; + userAuth: UserAuth; } -export const IssueDescriptionForm: FC = ({ issue, handleFormSubmit }) => { +export const IssueDescriptionForm: FC = ({ + issue, + handleFormSubmit, + userAuth, +}) => { const { setToastAlert } = useToast(); const { @@ -97,6 +102,8 @@ export const IssueDescriptionForm: FC = ({ issue, handleFormS reset(issue); }, [issue, reset]); + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; + return (
= ({ issue, handleFormS }} mode="transparent" className="text-xl font-medium" + disabled={isNotAllowed} /> {errors.name ? errors.name.message : null} = ({ issue, handleFormS debounceHandler(); }} onHTMLChange={(html) => setValue("description_html", html)} + editable={!isNotAllowed} />
); diff --git a/apps/app/components/issues/form.tsx b/apps/app/components/issues/form.tsx index 4ad6ed60c..a2233fc52 100644 --- a/apps/app/components/issues/form.tsx +++ b/apps/app/components/issues/form.tsx @@ -291,13 +291,7 @@ export const IssueForm: FC = ({ render={({ field: { value, onChange } }) => ( { - onChange( - val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null - ); - }} + onChange={onChange} className="max-w-[7rem]" /> )} diff --git a/apps/app/components/issues/sub-issue-list.tsx b/apps/app/components/issues/sub-issue-list.tsx index db3ab754e..f8944f379 100644 --- a/apps/app/components/issues/sub-issue-list.tsx +++ b/apps/app/components/issues/sub-issue-list.tsx @@ -7,7 +7,7 @@ import { CustomMenu } from "components/ui"; import { CreateUpdateIssueModal } from "components/issues"; import AddAsSubIssue from "components/project/issues/issue-detail/add-as-sub-issue"; // types -import { IIssue } from "types"; +import { IIssue, UserAuth } from "types"; export interface SubIssueListProps { issues: IIssue[]; @@ -15,6 +15,7 @@ export interface SubIssueListProps { workspaceSlug: string; parentIssue: IIssue; handleSubIssueRemove: (subIssueId: string) => void; + userAuth: UserAuth; } export const SubIssueList: FC = ({ @@ -23,6 +24,7 @@ export const SubIssueList: FC = ({ parentIssue, workspaceSlug, projectId, + userAuth, }) => { // states const [isIssueModalActive, setIssueModalActive] = useState(false); @@ -45,6 +47,8 @@ export const SubIssueList: FC = ({ setSubIssueModalActive(false); }; + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; + return ( <> = ({ setIsOpen={setSubIssueModalActive} parent={parentIssue} /> - {parentIssue?.id && workspaceSlug && projectId && issues?.length > 0 ? ( - - {({ open }) => ( - <> -
- - - Sub-issues {issues.length} - - {open ? ( -
- + + + { - openIssueModal(); - setPreloadedData({ - parent: parentIssue.id, - }); + setSubIssueModalActive(true); }} > - - Create new - - - - { - setSubIssueModalActive(true); - }} - > - Add an existing issue - - -
- ) : null} -
- - - {issues.map((issue) => ( - + ) : null} +
+ + + {issues.map((issue) => ( +
+ + + + + {issue.project_detail.identifier}-{issue.sequence_id} + + {issue.name} + + + {!isNotAllowed && (
handleSubIssueRemove(issue.id)}> @@ -129,40 +133,14 @@ export const SubIssueList: FC = ({
-
- ))} -
-
- - )} - - ) : ( - - - Add sub-issue - - } - optionsPosition="left" - noBorder - > - { - openIssueModal(); - }} - > - Create new - - { - openSubIssueModal(); - }} - > - Add an existing issue - - - )} + )} +
+ ))} + + + + )} + ); }; diff --git a/apps/app/components/onboarding/user-details.tsx b/apps/app/components/onboarding/user-details.tsx index f2755a1f4..99d4d5168 100644 --- a/apps/app/components/onboarding/user-details.tsx +++ b/apps/app/components/onboarding/user-details.tsx @@ -34,8 +34,8 @@ const UserDetails: React.FC = ({ user, setStep }) => { defaultValues, }); - const onSubmit = (formData: IUser) => { - userService + const onSubmit = async (formData: IUser) => { + await userService .updateUser(formData) .then(() => { setToastAlert({ diff --git a/apps/app/components/onboarding/workspace.tsx b/apps/app/components/onboarding/workspace.tsx index 8a4b4b016..786459c08 100644 --- a/apps/app/components/onboarding/workspace.tsx +++ b/apps/app/components/onboarding/workspace.tsx @@ -55,15 +55,17 @@ const Workspace: React.FC = ({ setStep, setWorkspace }) => { const handleCreateWorkspace = async (formData: IWorkspace) => { await workspaceService .workspaceSlugCheck(formData.slug) - .then((res) => { + .then(async (res) => { if (res.status === true) { - workspaceService + setSlugError(false); + await workspaceService .createWorkspace(formData) .then((res) => { console.log(res); setToastAlert({ type: "success", - title: "Workspace created successfully!", + title: "Success!", + message: "Workspace created successfully.", }); setWorkspace(res); setStep(3); @@ -160,10 +162,10 @@ const Workspace: React.FC = ({ setStep, setWorkspace }) => { {"https://app.plane.so/"} {slugError && ( diff --git a/apps/app/components/project/cycles/create-update-cycle-modal.tsx b/apps/app/components/project/cycles/create-update-cycle-modal.tsx index ef0a75cf5..30348e587 100644 --- a/apps/app/components/project/cycles/create-update-cycle-modal.tsx +++ b/apps/app/components/project/cycles/create-update-cycle-modal.tsx @@ -217,15 +217,7 @@ const CreateUpdateCycleModal: React.FC = ({ isOpen, setIsOpen, data, proj { - onChange( - val - ? `${val.getFullYear()}-${ - val.getMonth() + 1 - }-${val.getDate()}` - : null - ); - }} + onChange={onChange} error={errors.start_date ? true : false} /> )} @@ -246,15 +238,7 @@ const CreateUpdateCycleModal: React.FC = ({ isOpen, setIsOpen, data, proj { - onChange( - val - ? `${val.getFullYear()}-${ - val.getMonth() + 1 - }-${val.getDate()}` - : null - ); - }} + onChange={onChange} error={errors.end_date ? true : false} /> )} diff --git a/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx b/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx index dd81f0692..323b4f5f8 100644 --- a/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx +++ b/apps/app/components/project/cycles/cycle-detail-sidebar/index.tsx @@ -1,6 +1,7 @@ import { useEffect } from "react"; import { useRouter } from "next/router"; +import Image from "next/image"; import { mutate } from "swr"; @@ -129,14 +130,28 @@ const CycleDetailSidebar: React.FC = ({ cycle, isOpen, cycleIssues }) =>

Owned by

-
- {cycle.owned_by.first_name !== "" ? ( - <> - {cycle.owned_by.first_name} {cycle.owned_by.last_name} - - ) : ( - cycle.owned_by.email - )} +
+ {cycle.owned_by && + (cycle.owned_by.avatar && cycle.owned_by.avatar !== "" ? ( +
+ {cycle.owned_by?.first_name} +
+ ) : ( +
+ {cycle.owned_by?.first_name && cycle.owned_by.first_name !== "" + ? cycle.owned_by.first_name.charAt(0) + : cycle.owned_by?.email.charAt(0)} +
+ ))} + {cycle.owned_by.first_name !== "" + ? cycle.owned_by.first_name + : cycle.owned_by.email}
@@ -171,13 +186,11 @@ const CycleDetailSidebar: React.FC = ({ cycle, isOpen, cycleIssues }) => render={({ field: { value } }) => ( { + onChange={(val) => submitChanges({ - start_date: val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null, - }); - }} + start_date: val, + }) + } isClearable={false} /> )} @@ -196,13 +209,11 @@ const CycleDetailSidebar: React.FC = ({ cycle, isOpen, cycleIssues }) => render={({ field: { value } }) => ( { + onChange={(val) => submitChanges({ - end_date: val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null, - }); - }} + end_date: val, + }) + } isClearable={false} /> )} diff --git a/apps/app/components/project/issues/confirm-issue-deletion.tsx b/apps/app/components/project/issues/confirm-issue-deletion.tsx index 38d2258ce..12b8c63e9 100644 --- a/apps/app/components/project/issues/confirm-issue-deletion.tsx +++ b/apps/app/components/project/issues/confirm-issue-deletion.tsx @@ -25,9 +25,7 @@ type Props = { data?: IIssue; }; -const ConfirmIssueDeletion: React.FC = (props) => { - const { isOpen, handleClose, data } = props; - +const ConfirmIssueDeletion: React.FC = ({ isOpen, handleClose, data }) => { const cancelButtonRef = useRef(null); const [isDeleteLoading, setIsDeleteLoading] = useState(false); @@ -45,6 +43,8 @@ const ConfirmIssueDeletion: React.FC = (props) => { handleClose(); }; + console.log(data); + const handleDeletion = async () => { setIsDeleteLoading(true); if (!data || !workspaceSlug) return; @@ -62,8 +62,8 @@ const ConfirmIssueDeletion: React.FC = (props) => { false ); - const moduleId = data.issue_module?.module; - const cycleId = data.issue_cycle?.cycle; + const moduleId = data?.module; + const cycleId = data?.cycle; if (moduleId) { mutate( diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx index b46b4c3e1..fb18d4ebd 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx +++ b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/index.tsx @@ -39,7 +39,7 @@ import { // helpers import { copyTextToClipboard } from "helpers/string.helper"; // types -import type { ICycle, IIssue, IIssueLabels } from "types"; +import type { ICycle, IIssue, IIssueLabels, UserAuth } from "types"; // fetch-keys import { PROJECT_ISSUE_LABELS, PROJECT_ISSUES_LIST, ISSUE_DETAILS } from "constants/fetch-keys"; @@ -50,6 +50,7 @@ type Props = { submitChanges: (formData: Partial) => void; issueDetail: IIssue | undefined; watch: UseFormWatch; + userAuth: UserAuth; }; const defaultValues: Partial = { @@ -62,6 +63,7 @@ const IssueDetailSidebar: React.FC = ({ submitChanges, issueDetail, watch: watchIssue, + userAuth, }) => { const [createLabelForm, setCreateLabelForm] = useState(false); const [deleteIssueModal, setDeleteIssueModal] = useState(false); @@ -122,6 +124,8 @@ const IssueDetailSidebar: React.FC = ({ }); }; + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; + return ( <> = ({ > - + {!isNotAllowed && ( + + )}
- - - + + +
= ({ ) } watch={watchIssue} + userAuth={userAuth} /> i.id !== issueDetail?.id) ?? []} watch={watchIssue} + userAuth={userAuth} /> i.id !== issueDetail?.id) ?? []} watch={watchIssue} + userAuth={userAuth} />
@@ -219,37 +228,18 @@ const IssueDetailSidebar: React.FC = ({

Due date

- {/* ( - { - submitChanges({ - target_date: `${val.getFullYear()}-${ - val.getMonth() + 1 - }-${val.getDate()}`, - }); - onChange(`${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}`); - }} - dateFormat="dd-MM-yyyy" - /> - )} - /> */} ( { + onChange={(val) => submitChanges({ - target_date: val - ? `${val.getFullYear()}-${val.getMonth() + 1}-${val.getDate()}` - : null, - }); - }} + target_date: val, + }) + } + disabled={isNotAllowed} /> )} /> @@ -260,7 +250,7 @@ const IssueDetailSidebar: React.FC = ({
@@ -290,7 +280,7 @@ const IssueDetailSidebar: React.FC = ({ > {singleLabel.name} @@ -307,12 +297,19 @@ const IssueDetailSidebar: React.FC = ({ onChange={(val: any) => submitChanges({ labels_list: val })} className="flex-shrink-0" multiple + disabled={isNotAllowed} > {({ open }) => ( <> Label
- + Select Label @@ -361,8 +358,11 @@ const IssueDetailSidebar: React.FC = ({ /> +
+
- -
+ )} @@ -284,8 +289,11 @@ const SelectBlocked: React.FC = ({ submitChanges, issuesList, watch }) => diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx index e2cb85e6f..433f5c9fe 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx +++ b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-blocker.tsx @@ -19,7 +19,7 @@ import { Button } from "components/ui"; import { FolderIcon, MagnifyingGlassIcon, XMarkIcon } from "@heroicons/react/24/outline"; import { BlockerIcon, LayerDiagonalIcon } from "components/icons"; // types -import { IIssue } from "types"; +import { IIssue, UserAuth } from "types"; // fetch-keys import { PROJECT_ISSUES_LIST } from "constants/fetch-keys"; @@ -31,9 +31,10 @@ type Props = { submitChanges: (formData: Partial) => void; issuesList: IIssue[]; watch: UseFormWatch; + userAuth: UserAuth; }; -const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch }) => { +const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch, userAuth }) => { const [query, setQuery] = useState(""); const [isBlockerModalOpen, setIsBlockerModalOpen] = useState(false); @@ -95,6 +96,8 @@ const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch }) => .includes(query.toLowerCase()) ); + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; + return (
@@ -265,16 +268,18 @@ const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch }) => -
-
- +
+
- -
+ )}
@@ -282,8 +287,11 @@ const SelectBlocker: React.FC = ({ submitChanges, issuesList, watch }) => diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx index 9830204b5..159f96c68 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx +++ b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-cycle.tsx @@ -4,8 +4,6 @@ import { useRouter } from "next/router"; import useSWR, { mutate } from "swr"; -// react-hook-form -import { UseFormWatch } from "react-hook-form"; // services import issuesService from "services/issues.service"; import cyclesService from "services/cycles.service"; @@ -14,17 +12,17 @@ import { Spinner, CustomSelect } from "components/ui"; // icons import { CyclesIcon } from "components/icons"; // types -import { ICycle, IIssue } from "types"; +import { ICycle, IIssue, UserAuth } from "types"; // fetch-keys import { CYCLE_ISSUES, CYCLE_LIST, ISSUE_DETAILS } from "constants/fetch-keys"; type Props = { issueDetail: IIssue | undefined; handleCycleChange: (cycle: ICycle) => void; - watch: UseFormWatch; + userAuth: UserAuth; }; -const SelectCycle: React.FC = ({ issueDetail, handleCycleChange }) => { +const SelectCycle: React.FC = ({ issueDetail, handleCycleChange, userAuth }) => { const router = useRouter(); const { workspaceSlug, projectId, issueId } = router.query; @@ -52,6 +50,8 @@ const SelectCycle: React.FC = ({ issueDetail, handleCycleChange }) => { const issueCycle = issueDetail?.issue_cycle; + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; + return (
@@ -73,6 +73,7 @@ const SelectCycle: React.FC = ({ issueDetail, handleCycleChange }) => { ? removeIssueFromCycle(issueCycle?.id ?? "", issueCycle?.cycle ?? "") : handleCycleChange(cycles?.find((c) => c.id === value) as any); }} + disabled={isNotAllowed} > {cycles ? ( cycles.length > 0 ? ( diff --git a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx index ecacedd84..7cb298324 100644 --- a/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx +++ b/apps/app/components/project/issues/issue-detail/issue-detail-sidebar/select-parent.tsx @@ -13,7 +13,7 @@ import issuesServices from "services/issues.service"; import IssuesListModal from "components/project/issues/issues-list-modal"; // icons // types -import { IIssue } from "types"; +import { IIssue, UserAuth } from "types"; // fetch-keys import { PROJECT_ISSUES_LIST } from "constants/fetch-keys"; @@ -23,6 +23,7 @@ type Props = { issuesList: IIssue[]; customDisplay: JSX.Element; watch: UseFormWatch; + userAuth: UserAuth; }; const SelectParent: React.FC = ({ @@ -31,6 +32,7 @@ const SelectParent: React.FC = ({ issuesList, customDisplay, watch, + userAuth, }) => { const [isParentModalOpen, setIsParentModalOpen] = useState(false); @@ -46,6 +48,8 @@ const SelectParent: React.FC = ({ : null ); + const isNotAllowed = userAuth.isGuest || userAuth.isViewer; + return (
@@ -73,8 +77,11 @@ const SelectParent: React.FC = ({ />