From 6b6a85974f9381048d35bb4037e031affdba72c5 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 17:37:06 +0530 Subject: [PATCH 1/8] chore: delete cycle toast message updated --- web/core/constants/project.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/core/constants/project.ts b/web/core/constants/project.ts index 83f3c34a10b..0269455fb56 100644 --- a/web/core/constants/project.ts +++ b/web/core/constants/project.ts @@ -100,7 +100,7 @@ export const PROJECT_ERROR_MESSAGES = { }, cycleDeleteError: { title: "Error", - message: "Failed to delete project", + message: "Failed to delete cycle", }, moduleDeleteError: { title: "Error", From e8a0d23137a0088ff83ebc4ee919ce2eed49ac67 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 17:37:48 +0530 Subject: [PATCH 2/8] fix: view page empty state --- .../(detail)/[projectId]/views/(detail)/[viewId]/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx index 45c16260a02..3aefe9e0efe 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx @@ -25,14 +25,14 @@ const ProjectViewIssuesPage = observer(() => { const project = projectId ? getProjectById(projectId.toString()) : undefined; const pageTitle = project?.name && projectView?.name ? `${project?.name} - ${projectView?.name}` : undefined; - const { error } = useSWR( + const { error, isLoading } = useSWR( workspaceSlug && projectId && viewId ? `VIEW_DETAILS_${viewId.toString()}` : null, workspaceSlug && projectId && viewId ? () => fetchViewDetails(workspaceSlug.toString(), projectId.toString(), viewId.toString()) : null ); - if (error) { + if (error && !isLoading) { return ( Date: Thu, 12 Sep 2024 17:38:19 +0530 Subject: [PATCH 3/8] fix: project settings automation --- web/core/components/automation/auto-archive-automation.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/core/components/automation/auto-archive-automation.tsx b/web/core/components/automation/auto-archive-automation.tsx index cb985b8ce1b..8ef488da599 100644 --- a/web/core/components/automation/auto-archive-automation.tsx +++ b/web/core/components/automation/auto-archive-automation.tsx @@ -33,7 +33,7 @@ export const AutoArchiveAutomation: React.FC = observer((props) => { const isAdmin = allowPermissions( [EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT, - currentProjectDetails?.workspace_detail.slug, + currentProjectDetails?.workspace_detail?.slug, currentProjectDetails?.id ); From 4ac79fa04dfd4088fa27f597b92a6488b0ae83fe Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 17:42:34 +0530 Subject: [PATCH 4/8] fix: intake delete action --- web/core/components/inbox/content/root.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/core/components/inbox/content/root.tsx b/web/core/components/inbox/content/root.tsx index b0d779f3f7d..92661ce2646 100644 --- a/web/core/components/inbox/content/root.tsx +++ b/web/core/components/inbox/content/root.tsx @@ -67,7 +67,7 @@ export const InboxContentRoot: FC = observer((props) => { EUserPermissionsLevel.PROJECT ); const isGuest = projectPermissionsByWorkspaceSlugAndProjectId(workspaceSlug, projectId) === EUserPermissions.GUEST; - const isOwner = inboxIssue.issue.created_by === currentUser?.id; + const isOwner = inboxIssue?.issue.created_by === currentUser?.id; const readOnly = !isOwner && isGuest; if (!inboxIssue) return <>; From e76f8ac4f9e281483c93c095dd2ace2ebbffe862 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 17:55:37 +0530 Subject: [PATCH 5/8] fix: project label validation --- .../components/default-properties.tsx | 7 +- web/core/components/issues/select/label.tsx | 2 +- .../labels/label-block/label-item-block.tsx | 86 +++++++++++-------- .../labels/project-setting-label-item.tsx | 13 ++- .../labels/project-setting-label-list.tsx | 15 +++- 5 files changed, 81 insertions(+), 42 deletions(-) diff --git a/web/core/components/issues/issue-modal/components/default-properties.tsx b/web/core/components/issues/issue-modal/components/default-properties.tsx index 71f919de142..5177382ce61 100644 --- a/web/core/components/issues/issue-modal/components/default-properties.tsx +++ b/web/core/components/issues/issue-modal/components/default-properties.tsx @@ -26,10 +26,11 @@ import { ETabIndices } from "@/constants/tab-indices"; import { getDate, renderFormattedPayloadDate } from "@/helpers/date-time.helper"; import { getTabIndex } from "@/helpers/tab-indices.helper"; // hooks -import { useProjectEstimates, useProject } from "@/hooks/store"; +import { useProjectEstimates, useProject, useUserPermissions } from "@/hooks/store"; import { usePlatformOS } from "@/hooks/use-platform-os"; // plane web components import { IssueIdentifier } from "@/plane-web/components/issues"; +import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; type TIssueDefaultPropertiesProps = { control: Control; @@ -67,11 +68,14 @@ export const IssueDefaultProperties: React.FC = ob const { areEstimateEnabledByProjectId } = useProjectEstimates(); const { getProjectById } = useProject(); const { isMobile } = usePlatformOS(); + const { allowPermissions } = useUserPermissions(); // derived values const projectDetails = getProjectById(projectId); const { getIndex } = getTabIndex(ETabIndices.ISSUE_FORM, isMobile); + const canCreateLabel = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT); + const minDate = getDate(startDate); minDate?.setDate(minDate.getDate()); @@ -150,6 +154,7 @@ export const IssueDefaultProperties: React.FC = ob }} projectId={projectId ?? undefined} tabIndex={getIndex("label_ids")} + createLabelEnabled={canCreateLabel} /> )} diff --git a/web/core/components/issues/select/label.tsx b/web/core/components/issues/select/label.tsx index ec2905770a9..44525b9d62c 100644 --- a/web/core/components/issues/select/label.tsx +++ b/web/core/components/issues/select/label.tsx @@ -35,7 +35,7 @@ export const IssueLabelSelect: React.FC = observer((props) => { label, disabled = false, tabIndex, - createLabelEnabled = true, + createLabelEnabled = false, buttonClassName, } = props; // router diff --git a/web/core/components/labels/label-block/label-item-block.tsx b/web/core/components/labels/label-block/label-item-block.tsx index 564481dc8ba..12a263a7430 100644 --- a/web/core/components/labels/label-block/label-item-block.tsx +++ b/web/core/components/labels/label-block/label-item-block.tsx @@ -28,10 +28,19 @@ interface ILabelItemBlock { handleLabelDelete: (label: IIssueLabel) => void; isLabelGroup?: boolean; dragHandleRef: MutableRefObject; + disabled?: boolean; } export const LabelItemBlock = (props: ILabelItemBlock) => { - const { label, isDragging, customMenuItems, handleLabelDelete, isLabelGroup, dragHandleRef } = props; + const { + label, + isDragging, + customMenuItems, + handleLabelDelete, + isLabelGroup, + dragHandleRef, + disabled = false, + } = props; // states const [isMenuActive, setIsMenuActive] = useState(false); // refs @@ -42,44 +51,51 @@ export const LabelItemBlock = (props: ILabelItemBlock) => { return (
- + {!disabled && ( + + )}
-
- setIsMenuActive(!isMenuActive)} useCaptureForOutsideClick> - {customMenuItems.map( - ({ isVisible, onClick, CustomIcon, text, key }) => - isVisible && ( - onClick(label)}> - - - {text} - - - ) + {!disabled && ( +
+ setIsMenuActive(!isMenuActive)} useCaptureForOutsideClick> + {customMenuItems.map( + ({ isVisible, onClick, CustomIcon, text, key }) => + isVisible && ( + onClick(label)}> + + + {text} + + + ) + )} + + {!isLabelGroup && ( +
+ +
)} - - {!isLabelGroup && ( -
- -
- )} -
+
+ )}
); }; diff --git a/web/core/components/labels/project-setting-label-item.tsx b/web/core/components/labels/project-setting-label-item.tsx index fbc812e12d0..0b9a8732e27 100644 --- a/web/core/components/labels/project-setting-label-item.tsx +++ b/web/core/components/labels/project-setting-label-item.tsx @@ -23,10 +23,20 @@ type Props = { droppedLabelId: string | undefined, dropAtEndOfList: boolean ) => void; + isEditable?: boolean; }; export const ProjectSettingLabelItem: React.FC = (props) => { - const { label, setIsUpdating, handleLabelDelete, isChild, isLastChild, isParentDragging = false, onDrop } = props; + const { + label, + setIsUpdating, + handleLabelDelete, + isChild, + isLastChild, + isParentDragging = false, + onDrop, + isEditable = false, + } = props; // states const [isEditLabelForm, setEditLabelForm] = useState(false); // router @@ -91,6 +101,7 @@ export const ProjectSettingLabelItem: React.FC = (props) => { customMenuItems={customMenuItems} handleLabelDelete={handleLabelDelete} dragHandleRef={dragHandleRef} + disabled={!isEditable} /> )} diff --git a/web/core/components/labels/project-setting-label-list.tsx b/web/core/components/labels/project-setting-label-list.tsx index 72525083620..b11d8249aed 100644 --- a/web/core/components/labels/project-setting-label-list.tsx +++ b/web/core/components/labels/project-setting-label-list.tsx @@ -14,7 +14,8 @@ import { ProjectSettingLabelItem, } from "@/components/labels"; import { EmptyStateType } from "@/constants/empty-state"; -import { useLabel } from "@/hooks/store"; +import { useLabel, useUserPermissions } from "@/hooks/store"; +import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/user-permissions"; // components // ui // types @@ -31,6 +32,10 @@ export const ProjectSettingsLabelList: React.FC = observer(() => { const { workspaceSlug, projectId } = useParams(); // store hooks const { projectLabels, updateLabelPosition, projectLabelsTree } = useLabel(); + const { allowPermissions } = useUserPermissions(); + + // derived values + const isEditable = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT); const newLabel = () => { setIsUpdating(false); @@ -65,9 +70,11 @@ export const ProjectSettingsLabelList: React.FC = observer(() => { />

Labels

- + {isEditable && ( + + )}
{showLabelForm && ( From 3a1646db3f2854a1566340c58fb7145d8c6b3501 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 17:55:48 +0530 Subject: [PATCH 6/8] fix: project label validation --- .../inbox/modals/create-edit-modal/issue-properties.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/web/core/components/inbox/modals/create-edit-modal/issue-properties.tsx b/web/core/components/inbox/modals/create-edit-modal/issue-properties.tsx index b47d72c7a95..b17a60abdd1 100644 --- a/web/core/components/inbox/modals/create-edit-modal/issue-properties.tsx +++ b/web/core/components/inbox/modals/create-edit-modal/issue-properties.tsx @@ -91,7 +91,6 @@ export const InboxIssueProperties: FC = observer((props) {/* labels */}
{}} value={data?.label_ids || []} onChange={(labelIds) => handleData("label_ids", labelIds)} From a56d3c8668b1d4087de5c2e369087b446d14bc72 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 18:02:10 +0530 Subject: [PATCH 7/8] fix: project state permission updated --- .../components/project-states/group-item.tsx | 23 +++++--- .../components/project-states/state-item.tsx | 54 +++++++++++-------- .../components/project-states/state-list.tsx | 4 +- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/web/core/components/project-states/group-item.tsx b/web/core/components/project-states/group-item.tsx index 5316871a1c3..9abd94d531c 100644 --- a/web/core/components/project-states/group-item.tsx +++ b/web/core/components/project-states/group-item.tsx @@ -6,6 +6,8 @@ import { Plus } from "lucide-react"; import { IState, TStateGroups } from "@plane/types"; // components import { StateList, StateCreate } from "@/components/project-states"; +import { useUserPermissions } from "@/hooks/store"; +import { EUserPermissions, EUserPermissionsLevel } from "ee/constants/user-permissions"; type TGroupItem = { workspaceSlug: string; @@ -17,22 +19,28 @@ type TGroupItem = { export const GroupItem: FC = observer((props) => { const { workspaceSlug, projectId, groupKey, groupedStates, states } = props; + // store hooks + const { allowPermissions } = useUserPermissions(); // state const [createState, setCreateState] = useState(false); + const isEditable = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT); + return (
{groupKey}
-
!createState && setCreateState(true)} - > - -
+ {isEditable && ( +
!createState && setCreateState(true)} + > + +
+ )}
- {createState && ( + {isEditable && createState && ( = observer((props) => { groupKey={groupKey} groupedStates={groupedStates} states={states} + disabled={!isEditable} />
diff --git a/web/core/components/project-states/state-item.tsx b/web/core/components/project-states/state-item.tsx index e15a708d7a5..d955a10b524 100644 --- a/web/core/components/project-states/state-item.tsx +++ b/web/core/components/project-states/state-item.tsx @@ -24,10 +24,11 @@ type TStateItem = { groupedStates: Record; totalStates: number; state: IState; + disabled?: boolean; }; export const StateItem: FC = observer((props) => { - const { workspaceSlug, projectId, groupKey, groupedStates, totalStates, state } = props; + const { workspaceSlug, projectId, groupKey, groupedStates, totalStates, state, disabled = false } = props; // hooks const { moveStatePosition } = useProjectState(); // states @@ -131,7 +132,7 @@ export const StateItem: FC = observer((props) => { )} > {/* draggable indicator */} - {totalStates != 1 && ( + {!disabled && totalStates != 1 && (
@@ -148,28 +149,35 @@ export const StateItem: FC = observer((props) => {

{state.description}

-
- {/* state mark as default option */} -
- + {!disabled && ( +
+ {/* state mark as default option */} +
+ +
+ + {/* state edit options */} +
+ + +
- - {/* state edit options */} -
- - -
-
+ )}
{/* draggable drop bottom indicator */} diff --git a/web/core/components/project-states/state-list.tsx b/web/core/components/project-states/state-list.tsx index 42ddb6955c0..5e7f79916d3 100644 --- a/web/core/components/project-states/state-list.tsx +++ b/web/core/components/project-states/state-list.tsx @@ -12,10 +12,11 @@ type TStateList = { groupKey: TStateGroups; groupedStates: Record; states: IState[]; + disabled?: boolean; }; export const StateList: FC = observer((props) => { - const { workspaceSlug, projectId, groupKey, groupedStates, states } = props; + const { workspaceSlug, projectId, groupKey, groupedStates, states, disabled = false } = props; return ( <> @@ -28,6 +29,7 @@ export const StateList: FC = observer((props) => { groupedStates={groupedStates} totalStates={states.length || 0} state={state} + disabled={disabled} /> ))} From bb34a9d7acef90409af770bb734fcf6887a90a49 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia Date: Thu, 12 Sep 2024 20:03:44 +0530 Subject: [PATCH 8/8] chore: code refactor --- .../(detail)/[projectId]/views/(detail)/[viewId]/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx index 3aefe9e0efe..8a6eeb82142 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/[projectId]/views/(detail)/[viewId]/page.tsx @@ -32,7 +32,7 @@ const ProjectViewIssuesPage = observer(() => { : null ); - if (error && !isLoading) { + if (error) { return (