diff --git a/apiserver/plane/app/views/project.py b/apiserver/plane/app/views/project.py index 2ed82e7e920..c67575db5ff 100644 --- a/apiserver/plane/app/views/project.py +++ b/apiserver/plane/app/views/project.py @@ -42,6 +42,7 @@ WorkspaceUserPermission, ProjectBasePermission, ProjectMemberPermission, + ProjectLitePermission, ) from plane.db.models import ( @@ -602,6 +603,18 @@ class ProjectMemberViewSet(BaseViewSet): ProjectMemberPermission, ] + def get_permissions(self): + if self.action == "leave": + self.permission_classes = [ + ProjectLitePermission, + ] + else: + self.permission_classes = [ + ProjectMemberPermission, + ] + + return super(ProjectMemberViewSet, self).get_permissions() + search_fields = [ "member__display_name", "member__first_name", diff --git a/space/components/accounts/sign-in-forms/self-hosted-sign-in.tsx b/space/components/accounts/sign-in-forms/self-hosted-sign-in.tsx index e7a7d811584..486573ffa62 100644 --- a/space/components/accounts/sign-in-forms/self-hosted-sign-in.tsx +++ b/space/components/accounts/sign-in-forms/self-hosted-sign-in.tsx @@ -130,7 +130,7 @@ export const SelfHostedSignInForm: React.FC = (props) => { />

When you click the button above, you agree with our{" "} diff --git a/web/components/account/sign-in-forms/self-hosted-sign-in.tsx b/web/components/account/sign-in-forms/self-hosted-sign-in.tsx index 30e45bba626..27b5b4789e6 100644 --- a/web/components/account/sign-in-forms/self-hosted-sign-in.tsx +++ b/web/components/account/sign-in-forms/self-hosted-sign-in.tsx @@ -130,7 +130,7 @@ export const SelfHostedSignInForm: React.FC = (props) => { />

When you click the button above, you agree with our{" "} diff --git a/web/components/gantt-chart/sidebar/sidebar.tsx b/web/components/gantt-chart/sidebar/sidebar.tsx index d163f8a89b7..23f8f8d76bb 100644 --- a/web/components/gantt-chart/sidebar/sidebar.tsx +++ b/web/components/gantt-chart/sidebar/sidebar.tsx @@ -27,11 +27,21 @@ type Props = { viewId?: string ) => Promise; viewId?: string; + disableIssueCreation?: boolean; }; export const IssueGanttSidebar: React.FC = (props) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars - const { title, blockUpdateHandler, blocks, enableReorder, enableQuickIssueCreate, quickAddCallback, viewId } = props; + const { + title, + blockUpdateHandler, + blocks, + enableReorder, + enableQuickIssueCreate, + quickAddCallback, + viewId, + disableIssueCreation, + } = props; const router = useRouter(); const { cycleId } = router.query; @@ -160,7 +170,7 @@ export const IssueGanttSidebar: React.FC = (props) => { )} {droppableProvided.placeholder} - {enableQuickIssueCreate && ( + {enableQuickIssueCreate && !disableIssueCreation && ( )} diff --git a/web/components/issues/issue-layouts/calendar/calendar.tsx b/web/components/issues/issue-layouts/calendar/calendar.tsx index afcbee3f910..a2626b0237e 100644 --- a/web/components/issues/issue-layouts/calendar/calendar.tsx +++ b/web/components/issues/issue-layouts/calendar/calendar.tsx @@ -16,6 +16,8 @@ import { IProjectIssuesFilterStore, IViewIssuesFilterStore, } from "store/issues"; +// constants +import { EUserWorkspaceRoles } from "constants/workspace"; type Props = { issuesFilterStore: @@ -41,7 +43,14 @@ export const CalendarChart: React.FC = observer((props) => { const { issuesFilterStore, issues, groupedIssueIds, layout, showWeekends, quickActions, quickAddCallback, viewId } = props; - const { calendar: calendarStore } = useMobxStore(); + const { + calendar: calendarStore, + projectIssues: issueStore, + user: { currentProjectRole }, + } = useMobxStore(); + + const { enableIssueCreation } = issueStore?.viewFlags || {}; + const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; const calendarPayload = calendarStore.calendarPayload; @@ -71,6 +80,7 @@ export const CalendarChart: React.FC = observer((props) => { issues={issues} groupedIssueIds={groupedIssueIds} enableQuickIssueCreate + disableIssueCreation={!enableIssueCreation || !isEditingAllowed} quickActions={quickActions} quickAddCallback={quickAddCallback} viewId={viewId} @@ -85,6 +95,7 @@ export const CalendarChart: React.FC = observer((props) => { issues={issues} groupedIssueIds={groupedIssueIds} enableQuickIssueCreate + disableIssueCreation={!enableIssueCreation || !isEditingAllowed} quickActions={quickActions} quickAddCallback={quickAddCallback} viewId={viewId} diff --git a/web/components/issues/issue-layouts/calendar/day-tile.tsx b/web/components/issues/issue-layouts/calendar/day-tile.tsx index b999f615583..c9f022ebe2e 100644 --- a/web/components/issues/issue-layouts/calendar/day-tile.tsx +++ b/web/components/issues/issue-layouts/calendar/day-tile.tsx @@ -26,6 +26,7 @@ type Props = { groupedIssueIds: IGroupedIssues; quickActions: (issue: IIssue, customActionButton?: React.ReactElement) => React.ReactNode; enableQuickIssueCreate?: boolean; + disableIssueCreation?: boolean; quickAddCallback?: ( workspaceSlug: string, projectId: string, @@ -43,6 +44,7 @@ export const CalendarDayTile: React.FC = observer((props) => { groupedIssueIds, quickActions, enableQuickIssueCreate, + disableIssueCreation, quickAddCallback, viewId, } = props; @@ -86,7 +88,7 @@ export const CalendarDayTile: React.FC = observer((props) => { ref={provided.innerRef} > - {enableQuickIssueCreate && ( + {enableQuickIssueCreate && !disableIssueCreation && (

React.ReactNode; enableQuickIssueCreate?: boolean; + disableIssueCreation?: boolean; quickAddCallback?: ( workspaceSlug: string, projectId: string, @@ -42,6 +43,7 @@ export const CalendarWeekDays: React.FC = observer((props) => { week, quickActions, enableQuickIssueCreate, + disableIssueCreation, quickAddCallback, viewId, } = props; @@ -69,6 +71,7 @@ export const CalendarWeekDays: React.FC = observer((props) => { groupedIssueIds={groupedIssueIds} quickActions={quickActions} enableQuickIssueCreate={enableQuickIssueCreate} + disableIssueCreation={disableIssueCreation} quickAddCallback={quickAddCallback} viewId={viewId} /> 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 f467df208a5..62df8fc7972 100644 --- a/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx +++ b/web/components/issues/issue-layouts/gantt/base-gantt-root.tsx @@ -51,6 +51,7 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan const issuesResponse = issueStore.getIssues; const issueIds = (issueStore.getIssuesIds ?? []) as TUnGroupedIssues; + const { enableIssueCreation } = issueStore?.viewFlags || {}; const issues = issueIds.map((id) => issuesResponse?.[id]); @@ -87,6 +88,7 @@ export const BaseGanttRoot: React.FC = observer((props: IBaseGan quickAddCallback={issueStore.quickAddIssue} viewId={viewId} enableQuickIssueCreate + disableIssueCreation={!enableIssueCreation || !isAllowed} /> )} enableBlockLeftResize={isAllowed} 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 05799f72857..057ba0b87be 100644 --- a/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx +++ b/web/components/issues/issue-layouts/kanban/base-kanban-root.tsx @@ -330,7 +330,7 @@ export const BaseKanBanRoot: React.FC = observer((props: IBas projects={workspaceProjects} showEmptyGroup={userDisplayFilters?.show_empty_groups || true} isDragStarted={isDragStarted} - disableIssueCreation={true} + disableIssueCreation={!enableIssueCreation || !isEditingAllowed} enableQuickIssueCreate={enableQuickAdd} currentStore={currentStore} quickAddCallback={issueStore?.quickAddIssue} diff --git a/web/components/issues/issue-layouts/kanban/default.tsx b/web/components/issues/issue-layouts/kanban/default.tsx index 2f14ca3ab23..87fb98bf743 100644 --- a/web/components/issues/issue-layouts/kanban/default.tsx +++ b/web/components/issues/issue-layouts/kanban/default.tsx @@ -149,7 +149,7 @@ const GroupByKanBan: React.FC = observer((props) => {
- {enableQuickIssueCreate && ( + {enableQuickIssueCreate && !disableIssueCreation && ( = (props) => { /> )} - {enableIssueQuickAdd && ( + {enableIssueQuickAdd && !disableIssueCreation && (
{ user: userStore, } = useMobxStore(); - const { enableInlineEditing, enableQuickAdd } = issueStore?.viewFlags || {}; + const { enableInlineEditing, enableQuickAdd, enableIssueCreation } = issueStore?.viewFlags || {}; const { currentProjectRole } = userStore; const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER; @@ -120,6 +120,7 @@ export const BaseSpreadsheetRoot = observer((props: IBaseSpreadsheetRoot) => { quickAddCallback={issueStore.quickAddIssue} viewId={viewId} enableQuickCreateIssue={enableQuickAdd} + disableIssueCreation={!enableIssueCreation || !isEditingAllowed} /> ); }); diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx index 69ac625e828..370bbfa0f95 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-view.tsx @@ -33,6 +33,7 @@ type Props = { viewId?: string; canEditProperties: (projectId: string | undefined) => boolean; enableQuickCreateIssue?: boolean; + disableIssueCreation?: boolean; }; export const SpreadsheetView: React.FC = observer((props) => { @@ -50,6 +51,7 @@ export const SpreadsheetView: React.FC = observer((props) => { viewId, canEditProperties, enableQuickCreateIssue, + disableIssueCreation, } = props; // states const [expandedIssues, setExpandedIssues] = useState([]); @@ -147,7 +149,7 @@ export const SpreadsheetView: React.FC = observer((props) => {
- {enableQuickCreateIssue && ( + {enableQuickCreateIssue && !disableIssueCreation && ( )}
diff --git a/web/components/project/member-list-item.tsx b/web/components/project/member-list-item.tsx index 2d987fd53b3..aa70b4703ba 100644 --- a/web/components/project/member-list-item.tsx +++ b/web/components/project/member-list-item.tsx @@ -168,7 +168,7 @@ export const ProjectMemberListItem: React.FC = observer((props) => { ); })} - {isAdmin && ( + {(isAdmin || memberDetails.id === currentProjectMemberInfo?.member.id) && (