[WEB-1557] fix: create issue disabled for guests (#5102)
* fix: create issue disabled for guests * fix: workspace role type * fix: create modal issue * fix: removed the create action in guest mode * Remove unused imports --------- Co-authored-by: Satish Gandham <satish.iitg@gmail.com>
This commit is contained in:
parent
0cc5a5357b
commit
4c353b6eeb
4 changed files with 1276 additions and 1125 deletions
|
|
@ -12,20 +12,20 @@ import { IWorkspaceSearchResults } from "@plane/types";
|
||||||
// hooks
|
// hooks
|
||||||
import { LayersIcon, Loader, ToggleSwitch, Tooltip } from "@plane/ui";
|
import { LayersIcon, Loader, ToggleSwitch, Tooltip } from "@plane/ui";
|
||||||
import {
|
import {
|
||||||
CommandPaletteThemeActions,
|
|
||||||
ChangeIssueAssignee,
|
ChangeIssueAssignee,
|
||||||
ChangeIssuePriority,
|
ChangeIssuePriority,
|
||||||
ChangeIssueState,
|
ChangeIssueState,
|
||||||
CommandPaletteHelpActions,
|
CommandPaletteHelpActions,
|
||||||
CommandPaletteIssueActions,
|
CommandPaletteIssueActions,
|
||||||
CommandPaletteProjectActions,
|
CommandPaletteProjectActions,
|
||||||
CommandPaletteWorkspaceSettingsActions,
|
|
||||||
CommandPaletteSearchResults,
|
CommandPaletteSearchResults,
|
||||||
|
CommandPaletteThemeActions,
|
||||||
|
CommandPaletteWorkspaceSettingsActions,
|
||||||
} from "@/components/command-palette";
|
} from "@/components/command-palette";
|
||||||
import { EmptyState } from "@/components/empty-state";
|
import { EmptyState } from "@/components/empty-state";
|
||||||
import { EmptyStateType } from "@/constants/empty-state";
|
import { EmptyStateType } from "@/constants/empty-state";
|
||||||
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
|
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
|
||||||
import { useCommandPalette, useEventTracker, useProject } from "@/hooks/store";
|
import { useCommandPalette, useEventTracker, useProject, useUser } from "@/hooks/store";
|
||||||
import { useAppRouter } from "@/hooks/use-app-router";
|
import { useAppRouter } from "@/hooks/use-app-router";
|
||||||
import useDebounce from "@/hooks/use-debounce";
|
import useDebounce from "@/hooks/use-debounce";
|
||||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||||
|
|
@ -46,6 +46,7 @@ export const CommandModal: React.FC = observer(() => {
|
||||||
// hooks
|
// hooks
|
||||||
const { getProjectById, workspaceProjectIds } = useProject();
|
const { getProjectById, workspaceProjectIds } = useProject();
|
||||||
const { isMobile } = usePlatformOS();
|
const { isMobile } = usePlatformOS();
|
||||||
|
const { canPerformWorkspaceCreateActions } = useUser();
|
||||||
// states
|
// states
|
||||||
const [placeholder, setPlaceholder] = useState("Type a command or search...");
|
const [placeholder, setPlaceholder] = useState("Type a command or search...");
|
||||||
const [resultsCount, setResultsCount] = useState(0);
|
const [resultsCount, setResultsCount] = useState(0);
|
||||||
|
|
@ -282,24 +283,27 @@ export const CommandModal: React.FC = observer(() => {
|
||||||
setSearchTerm={(newSearchTerm) => setSearchTerm(newSearchTerm)}
|
setSearchTerm={(newSearchTerm) => setSearchTerm(newSearchTerm)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{workspaceSlug && workspaceProjectIds && workspaceProjectIds.length > 0 && (
|
{workspaceSlug &&
|
||||||
<Command.Group heading="Issue">
|
workspaceProjectIds &&
|
||||||
<Command.Item
|
workspaceProjectIds.length > 0 &&
|
||||||
onSelect={() => {
|
canPerformWorkspaceCreateActions && (
|
||||||
closePalette();
|
<Command.Group heading="Issue">
|
||||||
setTrackElement("Command Palette");
|
<Command.Item
|
||||||
toggleCreateIssueModal(true);
|
onSelect={() => {
|
||||||
}}
|
closePalette();
|
||||||
className="focus:bg-custom-background-80"
|
setTrackElement("Command Palette");
|
||||||
>
|
toggleCreateIssueModal(true);
|
||||||
<div className="flex items-center gap-2 text-custom-text-200">
|
}}
|
||||||
<LayersIcon className="h-3.5 w-3.5" />
|
className="focus:bg-custom-background-80"
|
||||||
Create new issue
|
>
|
||||||
</div>
|
<div className="flex items-center gap-2 text-custom-text-200">
|
||||||
<kbd>C</kbd>
|
<LayersIcon className="h-3.5 w-3.5" />
|
||||||
</Command.Item>
|
Create new issue
|
||||||
</Command.Group>
|
</div>
|
||||||
)}
|
<kbd>C</kbd>
|
||||||
|
</Command.Item>
|
||||||
|
</Command.Group>
|
||||||
|
)}
|
||||||
|
|
||||||
{workspaceSlug && (
|
{workspaceSlug && (
|
||||||
<Command.Group heading="Project">
|
<Command.Group heading="Project">
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,6 @@ import { CreateProjectModal } from "@/components/project";
|
||||||
import { CreateUpdateProjectViewModal } from "@/components/views";
|
import { CreateUpdateProjectViewModal } from "@/components/views";
|
||||||
// constants
|
// constants
|
||||||
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
|
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
|
||||||
import { EUserProjectRoles } from "@/constants/project";
|
|
||||||
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
|
||||||
// helpers
|
// helpers
|
||||||
import { copyTextToClipboard } from "@/helpers/string.helper";
|
import { copyTextToClipboard } from "@/helpers/string.helper";
|
||||||
// hooks
|
// hooks
|
||||||
|
|
@ -43,10 +41,7 @@ export const CommandPalette: FC = observer(() => {
|
||||||
const { toggleSidebar } = useAppTheme();
|
const { toggleSidebar } = useAppTheme();
|
||||||
const { setTrackElement } = useEventTracker();
|
const { setTrackElement } = useEventTracker();
|
||||||
const { platform } = usePlatformOS();
|
const { platform } = usePlatformOS();
|
||||||
const {
|
const { data: currentUser, canPerformProjectCreateActions, canPerformWorkspaceCreateActions } = useUser();
|
||||||
membership: { currentWorkspaceRole, currentProjectRole },
|
|
||||||
data: currentUser,
|
|
||||||
} = useUser();
|
|
||||||
const {
|
const {
|
||||||
issues: { removeIssue },
|
issues: { removeIssue },
|
||||||
} = useIssuesStore();
|
} = useIssuesStore();
|
||||||
|
|
@ -100,30 +95,29 @@ export const CommandPalette: FC = observer(() => {
|
||||||
}, [issueId]);
|
}, [issueId]);
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
const canPerformProjectCreateActions = useCallback(
|
const performProjectCreateActions = useCallback(
|
||||||
(showToast: boolean = true) => {
|
(showToast: boolean = true) => {
|
||||||
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserProjectRoles.MEMBER;
|
if (!canPerformProjectCreateActions && showToast)
|
||||||
if (!isAllowed && showToast)
|
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "You don't have permission to perform this action.",
|
title: "You don't have permission to perform this action.",
|
||||||
});
|
});
|
||||||
|
|
||||||
return isAllowed;
|
return canPerformProjectCreateActions;
|
||||||
},
|
},
|
||||||
[currentProjectRole]
|
[canPerformProjectCreateActions]
|
||||||
);
|
);
|
||||||
const canPerformWorkspaceCreateActions = useCallback(
|
|
||||||
|
const performWorkspaceCreateActions = useCallback(
|
||||||
(showToast: boolean = true) => {
|
(showToast: boolean = true) => {
|
||||||
const isAllowed = !!currentWorkspaceRole && currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
if (!canPerformWorkspaceCreateActions && showToast)
|
||||||
if (!isAllowed && showToast)
|
|
||||||
setToast({
|
setToast({
|
||||||
type: TOAST_TYPE.ERROR,
|
type: TOAST_TYPE.ERROR,
|
||||||
title: "You don't have permission to perform this action.",
|
title: "You don't have permission to perform this action.",
|
||||||
});
|
});
|
||||||
return isAllowed;
|
return canPerformWorkspaceCreateActions;
|
||||||
},
|
},
|
||||||
[currentWorkspaceRole]
|
[canPerformWorkspaceCreateActions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const shortcutsList: {
|
const shortcutsList: {
|
||||||
|
|
@ -228,19 +222,20 @@ export const CommandPalette: FC = observer(() => {
|
||||||
}
|
}
|
||||||
} else if (!isAnyModalOpen) {
|
} else if (!isAnyModalOpen) {
|
||||||
setTrackElement("Shortcut key");
|
setTrackElement("Shortcut key");
|
||||||
if (Object.keys(shortcutsList.global).includes(keyPressed)) shortcutsList.global[keyPressed].action();
|
if (Object.keys(shortcutsList.global).includes(keyPressed) && performWorkspaceCreateActions())
|
||||||
|
shortcutsList.global[keyPressed].action();
|
||||||
// workspace authorized actions
|
// workspace authorized actions
|
||||||
else if (
|
else if (
|
||||||
Object.keys(shortcutsList.workspace).includes(keyPressed) &&
|
Object.keys(shortcutsList.workspace).includes(keyPressed) &&
|
||||||
workspaceSlug &&
|
workspaceSlug &&
|
||||||
canPerformWorkspaceCreateActions()
|
performWorkspaceCreateActions()
|
||||||
)
|
)
|
||||||
shortcutsList.workspace[keyPressed].action();
|
shortcutsList.workspace[keyPressed].action();
|
||||||
// project authorized actions
|
// project authorized actions
|
||||||
else if (
|
else if (
|
||||||
Object.keys(shortcutsList.project).includes(keyPressed) &&
|
Object.keys(shortcutsList.project).includes(keyPressed) &&
|
||||||
projectId &&
|
projectId &&
|
||||||
canPerformProjectCreateActions()
|
performProjectCreateActions()
|
||||||
) {
|
) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
// actions that can be performed only inside a project
|
// actions that can be performed only inside a project
|
||||||
|
|
@ -249,8 +244,8 @@ export const CommandPalette: FC = observer(() => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
canPerformProjectCreateActions,
|
performProjectCreateActions,
|
||||||
canPerformWorkspaceCreateActions,
|
performWorkspaceCreateActions,
|
||||||
copyIssueUrlToClipboard,
|
copyIssueUrlToClipboard,
|
||||||
isAnyModalOpen,
|
isAnyModalOpen,
|
||||||
projectId,
|
projectId,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import cloneDeep from "lodash/cloneDeep";
|
import cloneDeep from "lodash/cloneDeep";
|
||||||
import set from "lodash/set";
|
import set from "lodash/set";
|
||||||
import { action, makeObservable, observable, runInAction } from "mobx";
|
import { action, makeObservable, observable, runInAction, computed } from "mobx";
|
||||||
// types
|
// types
|
||||||
import { IUser } from "@plane/types";
|
import { IUser } from "@plane/types";
|
||||||
|
// constants
|
||||||
|
import { EUserProjectRoles } from "@/constants/project";
|
||||||
|
import { EUserWorkspaceRoles } from "@/constants/workspace";
|
||||||
// helpers
|
// helpers
|
||||||
import { API_BASE_URL } from "@/helpers/common.helper";
|
import { API_BASE_URL } from "@/helpers/common.helper";
|
||||||
// services
|
// services
|
||||||
|
|
@ -38,6 +41,9 @@ export interface IUserStore {
|
||||||
deactivateAccount: () => Promise<void>;
|
deactivateAccount: () => Promise<void>;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
signOut: () => Promise<void>;
|
signOut: () => Promise<void>;
|
||||||
|
// computed
|
||||||
|
canPerformProjectCreateActions: boolean;
|
||||||
|
canPerformWorkspaceCreateActions: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserStore implements IUserStore {
|
export class UserStore implements IUserStore {
|
||||||
|
|
@ -82,6 +88,9 @@ export class UserStore implements IUserStore {
|
||||||
deactivateAccount: action,
|
deactivateAccount: action,
|
||||||
reset: action,
|
reset: action,
|
||||||
signOut: action,
|
signOut: action,
|
||||||
|
// computed
|
||||||
|
canPerformProjectCreateActions: computed,
|
||||||
|
canPerformWorkspaceCreateActions: computed,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,4 +228,20 @@ export class UserStore implements IUserStore {
|
||||||
await this.authService.signOut(API_BASE_URL);
|
await this.authService.signOut(API_BASE_URL);
|
||||||
this.store.resetOnSignOut();
|
this.store.resetOnSignOut();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description tells if user has project create actions permissions
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get canPerformProjectCreateActions() {
|
||||||
|
return !!this.membership.currentProjectRole && this.membership.currentProjectRole >= EUserProjectRoles.MEMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description tells if user has workspace create actions permissions
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
get canPerformWorkspaceCreateActions() {
|
||||||
|
return !!this.membership.currentWorkspaceRole && this.membership.currentWorkspaceRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue