diff --git a/apiserver/plane/app/views/project.py b/apiserver/plane/app/views/project.py index 2ed82e7e9..c67575db5 100644 --- a/apiserver/plane/app/views/project.py +++ b/apiserver/plane/app/views/project.py @@ -42,6 +42,7 @@ from plane.app.permissions import ( 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 e7a7d8115..486573ffa 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 30e45bba6..27b5b4789 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 d163f8a89..23f8f8d76 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/instance/setup-done-view.tsx b/web/components/instance/setup-done-view.tsx index 693e5855e..6c1c53f7c 100644 --- a/web/components/instance/setup-done-view.tsx +++ b/web/components/instance/setup-done-view.tsx @@ -5,7 +5,7 @@ import { useTheme } from "next-themes"; import { Button } from "@plane/ui"; import { UserCog2 } from "lucide-react"; // images -import instanceSetupDone from "public/instance-setup-done.svg"; +import instanceSetupDone from "public/instance-setup-done.webp"; import PlaneBlackLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg"; import PlaneWhiteLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg"; import { useMobxStore } from "lib/mobx/store-provider"; diff --git a/web/components/issues/issue-layouts/calendar/calendar.tsx b/web/components/issues/issue-layouts/calendar/calendar.tsx index ed3797383..9d8247d55 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_legacy/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 7f6a94944..ef06e34fa 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 7ccfd006b..d6a71a923 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 eaa3e9341..e3f032bb1 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 ee9f2c331..30b57b84f 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 69ac625e8..370bbfa0f 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 2d987fd53..aa70b4703 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) && ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/web/public/instance-setup-done.webp b/web/public/instance-setup-done.webp new file mode 100644 index 000000000..4773ed70b Binary files /dev/null and b/web/public/instance-setup-done.webp differ