[WEB-3410] fix: work item permission and validation (#6621)
* fix: work item permission and validation * fix: command palette * chore: code refactor
This commit is contained in:
parent
075eefe1a5
commit
a9aeeb6707
9 changed files with 47 additions and 29 deletions
|
|
@ -5,27 +5,22 @@ import useSWR from "swr";
|
||||||
import { BulkDeleteIssuesModal } from "@/components/core";
|
import { BulkDeleteIssuesModal } from "@/components/core";
|
||||||
import { CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues";
|
import { CreateUpdateIssueModal, DeleteIssueModal } from "@/components/issues";
|
||||||
// constants
|
// constants
|
||||||
import { ISSUE_DETAILS } from "@/constants/fetch-keys";
|
|
||||||
// hooks
|
// hooks
|
||||||
import { useCommandPalette, useUser } from "@/hooks/store";
|
import { useCommandPalette, useIssueDetail, useUser } from "@/hooks/store";
|
||||||
import { useAppRouter } from "@/hooks/use-app-router";
|
import { useAppRouter } from "@/hooks/use-app-router";
|
||||||
import { useIssuesStore } from "@/hooks/use-issue-layout-store";
|
import { useIssuesStore } from "@/hooks/use-issue-layout-store";
|
||||||
// services
|
|
||||||
import { IssueService } from "@/services/issue";
|
|
||||||
|
|
||||||
// services
|
|
||||||
const issueService = new IssueService();
|
|
||||||
|
|
||||||
export const IssueLevelModals = observer(() => {
|
export const IssueLevelModals = observer(() => {
|
||||||
// router
|
// router
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const { workspaceSlug, projectId, issueId, cycleId, moduleId } = useParams();
|
const { workspaceSlug, projectId: paramsProjectId, workItem, cycleId, moduleId } = useParams();
|
||||||
const router = useAppRouter();
|
const router = useAppRouter();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { data: currentUser } = useUser();
|
const { data: currentUser } = useUser();
|
||||||
const {
|
const {
|
||||||
issues: { removeIssue },
|
issues: { removeIssue },
|
||||||
} = useIssuesStore();
|
} = useIssuesStore();
|
||||||
|
const { fetchIssueWithIdentifier } = useIssueDetail();
|
||||||
const {
|
const {
|
||||||
isCreateIssueModalOpen,
|
isCreateIssueModalOpen,
|
||||||
toggleCreateIssueModal,
|
toggleCreateIssueModal,
|
||||||
|
|
@ -37,13 +32,19 @@ export const IssueLevelModals = observer(() => {
|
||||||
// derived values
|
// derived values
|
||||||
const isDraftIssue = pathname?.includes("draft-issues") || false;
|
const isDraftIssue = pathname?.includes("draft-issues") || false;
|
||||||
|
|
||||||
|
const projectIdentifier = workItem?.toString().split("-")[0];
|
||||||
|
const sequence_id = workItem?.toString().split("-")[1];
|
||||||
|
|
||||||
const { data: issueDetails } = useSWR(
|
const { data: issueDetails } = useSWR(
|
||||||
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
|
workspaceSlug && workItem ? `ISSUE_DETAIL_${workspaceSlug}_${projectIdentifier}_${sequence_id}` : null,
|
||||||
workspaceSlug && projectId && issueId
|
workspaceSlug && workItem
|
||||||
? () => issueService.retrieve(workspaceSlug as string, projectId as string, issueId as string)
|
? () => fetchIssueWithIdentifier(workspaceSlug.toString(), projectIdentifier, sequence_id)
|
||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const issueId = issueDetails?.id;
|
||||||
|
const projectId = paramsProjectId ?? issueDetails?.project_id;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CreateUpdateIssueModal
|
<CreateUpdateIssueModal
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,14 @@ type Props = {
|
||||||
export const CommandPaletteIssueActions: React.FC<Props> = observer((props) => {
|
export const CommandPaletteIssueActions: React.FC<Props> = observer((props) => {
|
||||||
const { closePalette, issueDetails, pages, setPages, setPlaceholder, setSearchTerm } = props;
|
const { closePalette, issueDetails, pages, setPages, setPlaceholder, setSearchTerm } = props;
|
||||||
// router
|
// router
|
||||||
const { workspaceSlug, projectId, issueId } = useParams();
|
const { workspaceSlug } = useParams();
|
||||||
// hooks
|
// hooks
|
||||||
const { updateIssue } = useIssueDetail();
|
const { updateIssue } = useIssueDetail();
|
||||||
const { toggleCommandPaletteModal, toggleDeleteIssueModal } = useCommandPalette();
|
const { toggleCommandPaletteModal, toggleDeleteIssueModal } = useCommandPalette();
|
||||||
const { data: currentUser } = useUser();
|
const { data: currentUser } = useUser();
|
||||||
|
// derived values
|
||||||
|
const issueId = issueDetails?.id;
|
||||||
|
const projectId = issueDetails?.project_id;
|
||||||
|
|
||||||
const handleUpdateIssue = async (formData: Partial<TIssue>) => {
|
const handleUpdateIssue = async (formData: Partial<TIssue>) => {
|
||||||
if (!workspaceSlug || !projectId || !issueDetails) return;
|
if (!workspaceSlug || !projectId || !issueDetails) return;
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,15 @@ type Props = { closePalette: () => void; issue: TIssue };
|
||||||
export const ChangeIssueAssignee: React.FC<Props> = observer((props) => {
|
export const ChangeIssueAssignee: React.FC<Props> = observer((props) => {
|
||||||
const { closePalette, issue } = props;
|
const { closePalette, issue } = props;
|
||||||
// router params
|
// router params
|
||||||
const { workspaceSlug, projectId } = useParams();
|
const { workspaceSlug } = useParams();
|
||||||
// store
|
// store
|
||||||
const { updateIssue } = useIssueDetail();
|
const { updateIssue } = useIssueDetail();
|
||||||
const {
|
const {
|
||||||
project: { projectMemberIds, getProjectMemberDetails },
|
project: { getProjectMemberIds, getProjectMemberDetails },
|
||||||
} = useMember();
|
} = useMember();
|
||||||
|
// derived values
|
||||||
|
const projectId = issue?.project_id ?? "";
|
||||||
|
const projectMemberIds = getProjectMemberIds(projectId);
|
||||||
|
|
||||||
const options =
|
const options =
|
||||||
projectMemberIds
|
projectMemberIds
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,11 @@ type Props = { closePalette: () => void; issue: TIssue };
|
||||||
export const ChangeIssuePriority: React.FC<Props> = observer((props) => {
|
export const ChangeIssuePriority: React.FC<Props> = observer((props) => {
|
||||||
const { closePalette, issue } = props;
|
const { closePalette, issue } = props;
|
||||||
// router params
|
// router params
|
||||||
const { workspaceSlug, projectId } = useParams();
|
const { workspaceSlug } = useParams();
|
||||||
|
// store hooks
|
||||||
const { updateIssue } = useIssueDetail();
|
const { updateIssue } = useIssueDetail();
|
||||||
|
// derived values
|
||||||
|
const projectId = issue?.project_id;
|
||||||
|
|
||||||
const submitChanges = async (formData: Partial<TIssue>) => {
|
const submitChanges = async (formData: Partial<TIssue>) => {
|
||||||
if (!workspaceSlug || !projectId || !issue) return;
|
if (!workspaceSlug || !projectId || !issue) return;
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,13 @@ type Props = { closePalette: () => void; issue: TIssue };
|
||||||
export const ChangeIssueState: React.FC<Props> = observer((props) => {
|
export const ChangeIssueState: React.FC<Props> = observer((props) => {
|
||||||
const { closePalette, issue } = props;
|
const { closePalette, issue } = props;
|
||||||
// router params
|
// router params
|
||||||
const { workspaceSlug, projectId } = useParams();
|
const { workspaceSlug } = useParams();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { updateIssue } = useIssueDetail();
|
const { updateIssue } = useIssueDetail();
|
||||||
const { projectStates } = useProjectState();
|
const { getProjectStates } = useProjectState();
|
||||||
|
// derived values
|
||||||
|
const projectId = issue?.project_id;
|
||||||
|
const projectStates = getProjectStates(projectId);
|
||||||
|
|
||||||
const submitChanges = async (formData: Partial<TIssue>) => {
|
const submitChanges = async (formData: Partial<TIssue>) => {
|
||||||
if (!workspaceSlug || !projectId || !issue) return;
|
if (!workspaceSlug || !projectId || !issue) return;
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import {
|
||||||
|
|
||||||
export const CommandPalette: FC = observer(() => {
|
export const CommandPalette: FC = observer(() => {
|
||||||
// router params
|
// router params
|
||||||
const { workspaceSlug, projectId, issueId } = useParams();
|
const { workspaceSlug, projectId, workItem } = useParams();
|
||||||
// store hooks
|
// store hooks
|
||||||
const { toggleSidebar } = useAppTheme();
|
const { toggleSidebar } = useAppTheme();
|
||||||
const { setTrackElement } = useEventTracker();
|
const { setTrackElement } = useEventTracker();
|
||||||
|
|
@ -51,7 +51,7 @@ export const CommandPalette: FC = observer(() => {
|
||||||
const canPerformProjectAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT);
|
const canPerformProjectAdminActions = allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT);
|
||||||
|
|
||||||
const copyIssueUrlToClipboard = useCallback(() => {
|
const copyIssueUrlToClipboard = useCallback(() => {
|
||||||
if (!issueId) return;
|
if (!workItem) return;
|
||||||
|
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
copyTextToClipboard(url.href)
|
copyTextToClipboard(url.href)
|
||||||
|
|
@ -67,7 +67,7 @@ export const CommandPalette: FC = observer(() => {
|
||||||
title: "Some error occurred",
|
title: "Some error occurred",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, [issueId]);
|
}, [workItem]);
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
const performProjectCreateActions = useCallback(
|
const performProjectCreateActions = useCallback(
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,11 @@ export const IssueLabelActivity: FC<TIssueLabelActivity> = observer((props) => {
|
||||||
const {
|
const {
|
||||||
activity: { getActivityById },
|
activity: { getActivityById },
|
||||||
} = useIssueDetail();
|
} = useIssueDetail();
|
||||||
const { projectLabels } = useLabel();
|
const { getLabelById } = useLabel();
|
||||||
|
|
||||||
const activity = getActivityById(activityId);
|
const activity = getActivityById(activityId);
|
||||||
|
const oldLabelColor = getLabelById(activity?.old_identifier ?? "")?.color;
|
||||||
|
const newLabelColor = getLabelById(activity?.new_identifier ?? "")?.color;
|
||||||
|
|
||||||
if (!activity) return <></>;
|
if (!activity) return <></>;
|
||||||
return (
|
return (
|
||||||
|
|
@ -29,11 +31,7 @@ export const IssueLabelActivity: FC<TIssueLabelActivity> = observer((props) => {
|
||||||
{activity.old_value === "" ? `added a new label ` : `removed the label `}
|
{activity.old_value === "" ? `added a new label ` : `removed the label `}
|
||||||
<LabelActivityChip
|
<LabelActivityChip
|
||||||
name={activity.old_value === "" ? activity.new_value : activity.old_value}
|
name={activity.old_value === "" ? activity.new_value : activity.old_value}
|
||||||
color={
|
color={activity.old_value === "" ? newLabelColor : oldLabelColor}
|
||||||
activity.old_value === ""
|
|
||||||
? projectLabels?.find((l) => l.id === activity.new_identifier)?.color
|
|
||||||
: projectLabels?.find((l) => l.id === activity.old_identifier)?.color
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
{showIssue && (activity.old_value === "" ? ` to ` : ` from `)}
|
{showIssue && (activity.old_value === "" ? ` to ` : ` from `)}
|
||||||
{showIssue && <IssueLink activityId={activityId} />}
|
{showIssue && <IssueLink activityId={activityId} />}
|
||||||
|
|
|
||||||
|
|
@ -170,10 +170,17 @@ export const IssueDetailQuickActions: FC<Props> = observer((props) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// auth
|
// auth
|
||||||
const isEditable = allowPermissions([EUserPermissions.ADMIN, EUserPermissions.MEMBER], EUserPermissionsLevel.PROJECT);
|
const isEditable = allowPermissions(
|
||||||
|
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
||||||
|
EUserPermissionsLevel.PROJECT,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId
|
||||||
|
);
|
||||||
const canRestoreIssue = allowPermissions(
|
const canRestoreIssue = allowPermissions(
|
||||||
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
[EUserPermissions.ADMIN, EUserPermissions.MEMBER],
|
||||||
EUserPermissionsLevel.PROJECT
|
EUserPermissionsLevel.PROJECT,
|
||||||
|
workspaceSlug,
|
||||||
|
projectId
|
||||||
);
|
);
|
||||||
const isArchivingAllowed = !issue?.archived_at && isEditable;
|
const isArchivingAllowed = !issue?.archived_at && isEditable;
|
||||||
const isInArchivableGroup = !!stateDetails && ARCHIVABLE_STATE_GROUPS.includes(stateDetails?.group);
|
const isInArchivableGroup = !!stateDetails && ARCHIVABLE_STATE_GROUPS.includes(stateDetails?.group);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue