fix: sub-issue properties not rendering and other sub-issue bugs (#3020)

* fix: sub-issue properties not rendering

* fix: delete sub-issue

* fix: delete issue modal on command k and the issue details page
This commit is contained in:
Aaryan Khandelwal 2023-12-07 17:33:38 +05:30 committed by GitHub
parent c6e2effa65
commit 5fdd2ac366
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 80 additions and 107 deletions

View File

@ -34,6 +34,7 @@ export const CommandPalette: FC = observer(() => {
theme: { toggleSidebar },
user: { currentUser },
trackEvent: { setTrackElement },
projectIssues: { removeIssue },
} = useMobxStore();
const {
toggleCommandPaletteModal,
@ -218,11 +219,15 @@ export const CommandPalette: FC = observer(() => {
currentStore={createIssueStoreType}
/>
{issueId && issueDetails && (
{workspaceSlug && projectId && issueId && issueDetails && (
<DeleteIssueModal
handleClose={() => toggleDeleteIssueModal(false)}
isOpen={isDeleteIssueModalOpen}
data={issueDetails}
onSubmit={async () => {
await removeIssue(workspaceSlug.toString(), projectId.toString(), issueId.toString());
router.push(`/${workspaceSlug}/projects/${projectId}/issues`);
}}
/>
)}

View File

@ -57,12 +57,8 @@ export const UserImageUploadModal: React.FC<Props> = observer((props) => {
};
const handleSubmit = async () => {
console.log("Submit triggered");
if (!image) return;
console.log("Inside submit");
setIsImageUploading(true);
const formData = new FormData();

View File

@ -29,7 +29,10 @@ export const DeleteIssueModal: React.FC<Props> = (props) => {
const handleIssueDelete = async () => {
setIsDeleteLoading(true);
if (onSubmit) await onSubmit().finally(() => setIsDeleteLoading(false));
if (onSubmit)
await onSubmit()
.then(() => onClose())
.finally(() => setIsDeleteLoading(false));
};
return (

View File

@ -61,8 +61,6 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = (props) => {
description_html: issue.description_html,
});
console.log("in form", localIssueDescription);
useEffect(() => {
if (issue.id) {
setLocalIssueDescription({ id: issue.id, description_html: issue.description_html });

View File

@ -81,11 +81,10 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
const [selectedLinkToUpdate, setSelectedLinkToUpdate] = useState<ILinkDetails | null>(null);
const {
user: userStore,
user: { currentUser, currentProjectRole },
projectState: { states },
projectIssues: { removeIssue },
} = useMobxStore();
const user = userStore.currentUser;
const userRole = userStore.currentProjectRole;
const router = useRouter();
const { workspaceSlug, projectId, issueId, inboxIssueId } = router.query;
@ -102,7 +101,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
const handleCycleChange = useCallback(
(cycleId: string) => {
if (!workspaceSlug || !projectId || !issueDetail || !user) return;
if (!workspaceSlug || !projectId || !issueDetail || !currentUser) return;
issueService
.addIssueToCycle(workspaceSlug as string, projectId as string, cycleId, {
@ -112,12 +111,12 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
mutate(ISSUE_DETAILS(issueId as string));
});
},
[workspaceSlug, projectId, issueId, issueDetail, user]
[workspaceSlug, projectId, issueId, issueDetail, currentUser]
);
const handleModuleChange = useCallback(
(moduleId: string) => {
if (!workspaceSlug || !projectId || !issueDetail || !user) return;
if (!workspaceSlug || !projectId || !issueDetail || !currentUser) return;
moduleService
.addIssuesToModule(workspaceSlug as string, projectId as string, moduleId, {
@ -127,7 +126,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
mutate(ISSUE_DETAILS(issueId as string));
});
},
[workspaceSlug, projectId, issueId, issueDetail, user]
[workspaceSlug, projectId, issueId, issueDetail, currentUser]
);
const handleCreateLink = async (formData: IIssueLink) => {
@ -249,7 +248,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
setLinkModal(true);
};
const isAllowed = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER;
const isAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
const currentIssueState = projectId
? states[projectId.toString()]?.find((s) => s.id === issueDetail?.state)
@ -268,8 +267,16 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
createIssueLink={handleCreateLink}
updateIssueLink={handleUpdateLink}
/>
{issueDetail && (
<DeleteIssueModal handleClose={() => setDeleteIssueModal(false)} isOpen={deleteIssueModal} data={issueDetail} />
{workspaceSlug && projectId && issueDetail && (
<DeleteIssueModal
handleClose={() => setDeleteIssueModal(false)}
isOpen={deleteIssueModal}
data={issueDetail}
onSubmit={async () => {
await removeIssue(workspaceSlug.toString(), projectId.toString(), issueDetail.id);
router.push(`/${workspaceSlug}/projects/${projectId}/issues`);
}}
/>
)}
<div className="h-full w-full flex flex-col divide-y-2 divide-custom-border-200 overflow-hidden">
<div className="flex items-center justify-between px-5 pb-3">
@ -288,8 +295,8 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
</h4>
</div>
<div className="flex flex-wrap items-center gap-2">
{issueDetail?.created_by !== user?.id &&
!issueDetail?.assignees.includes(user?.id ?? "") &&
{issueDetail?.created_by !== currentUser?.id &&
!issueDetail?.assignees.includes(currentUser?.id ?? "") &&
!router.pathname.includes("[archivedIssueId]") &&
(fieldsToShow.includes("all") || fieldsToShow.includes("subscribe")) && (
<Button
@ -654,10 +661,10 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
handleDeleteLink={handleDeleteLink}
handleEditLink={handleEditLink}
userAuth={{
isGuest: userRole === 5,
isViewer: userRole === 10,
isMember: userRole === 15,
isOwner: userRole === 20,
isGuest: currentProjectRole === 5,
isViewer: currentProjectRole === 10,
isMember: currentProjectRole === 15,
isOwner: currentProjectRole === 20,
}}
/>
) : null}

View File

@ -117,17 +117,16 @@ export const SubIssues: React.FC<ISubIssues> = ({
workspaceSlug={workspaceSlug}
parentIssue={parentIssue}
issue={issue}
user={user}
editable={editable}
/>
</div>
<div className="flex-shrink-0 text-sm">
<CustomMenu width="auto" ellipsis>
<CustomMenu width="auto" placement="bottom-end" ellipsis>
{editable && (
<CustomMenu.MenuItem onClick={() => handleIssueCrudOperation("edit", parentIssue?.id, issue)}>
<div className="flex items-center justify-start gap-2">
<Pencil width={14} strokeWidth={2} />
<div className="flex items-center gap-2">
<Pencil className="h-3.5 w-3.5" strokeWidth={2} />
<span>Edit issue</span>
</div>
</CustomMenu.MenuItem>
@ -135,8 +134,8 @@ export const SubIssues: React.FC<ISubIssues> = ({
{editable && (
<CustomMenu.MenuItem onClick={() => handleIssueCrudOperation("delete", parentIssue?.id, issue)}>
<div className="flex items-center justify-start gap-2">
<Trash width={14} strokeWidth={2} />
<div className="flex items-center gap-2">
<Trash className="h-3.5 w-3.5" strokeWidth={2} />
<span>Delete issue</span>
</div>
</CustomMenu.MenuItem>
@ -145,8 +144,8 @@ export const SubIssues: React.FC<ISubIssues> = ({
<CustomMenu.MenuItem
onClick={() => copyText(`${workspaceSlug}/projects/${issue.project}/issues/${issue.id}`)}
>
<div className="flex items-center justify-start gap-2">
<LinkIcon width={14} strokeWidth={2} />
<div className="flex items-center gap-2">
<LinkIcon className="h-3.5 w-3.5" strokeWidth={2} />
<span>Copy issue link</span>
</div>
</CustomMenu.MenuItem>

View File

@ -1,15 +1,11 @@
import React from "react";
import { observer } from "mobx-react-lite";
import { mutate } from "swr";
// mobx store
import { useMobxStore } from "lib/mobx/store-provider";
// services
import { IssueService } from "services/issue";
// components
import { ViewDueDateSelect, ViewStartDateSelect } from "components/issues";
import { PrioritySelect } from "components/project";
// types
import { IUser, IIssue, IState } from "types";
import { IIssue, IState } from "types";
// fetch-keys
import { SUB_ISSUES } from "constants/fetch-keys";
import { IssuePropertyAssignee, IssuePropertyState } from "../issue-layouts/properties";
@ -18,19 +14,14 @@ export interface IIssueProperty {
workspaceSlug: string;
parentIssue: IIssue;
issue: IIssue;
user: IUser | undefined;
editable: boolean;
}
// services
const issueService = new IssueService();
export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
const { workspaceSlug, parentIssue, issue, user, editable } = props;
const { issueFilter: issueFilterStore } = useMobxStore();
const displayProperties = issueFilterStore.userDisplayProperties ?? {};
export const IssueProperty: React.FC<IIssueProperty> = (props) => {
const { workspaceSlug, parentIssue, issue, editable } = props;
const handlePriorityChange = (data: any) => {
partialUpdateIssue({ priority: data });
@ -77,63 +68,30 @@ export const IssueProperty: React.FC<IIssueProperty> = observer((props) => {
};
return (
<div className="relative flex items-center gap-1">
{displayProperties.priority && (
<div className="flex-shrink-0">
<PrioritySelect
value={issue.priority}
onChange={handlePriorityChange}
hideDropdownArrow
disabled={!editable}
/>
</div>
)}
<div className="relative flex items-center gap-2">
<div className="flex-shrink-0">
<PrioritySelect value={issue.priority} onChange={handlePriorityChange} hideDropdownArrow disabled={!editable} />
</div>
{displayProperties.state && (
<div className="flex-shrink-0">
<IssuePropertyState
projectId={issue?.project_detail?.id || null}
value={issue?.state_detail || null}
onChange={(data) => handleStateChange(data)}
disabled={false}
hideDropdownArrow
/>
</div>
)}
<div className="flex-shrink-0">
<IssuePropertyState
projectId={issue?.project_detail?.id || null}
value={issue?.state || null}
onChange={(data) => handleStateChange(data)}
disabled={false}
hideDropdownArrow
/>
</div>
{displayProperties.start_date && issue.start_date && (
<div className="flex-shrink-0 w-[104px]">
<ViewStartDateSelect
issue={issue}
onChange={(val) => partialUpdateIssue({ start_date: val })}
disabled={!editable}
/>
</div>
)}
{displayProperties.due_date && issue.target_date && (
<div className="flex-shrink-0 w-[104px]">
{user && (
<ViewDueDateSelect
issue={issue}
onChange={(val) => partialUpdateIssue({ target_date: val })}
disabled={!editable}
/>
)}
</div>
)}
{displayProperties.assignee && (
<div className="flex-shrink-0">
<IssuePropertyAssignee
projectId={issue?.project_detail?.id || null}
value={issue?.assignees || null}
hideDropdownArrow
onChange={(val) => handleAssigneeChange(val)}
disabled={false}
/>
</div>
)}
<div className="flex-shrink-0">
<IssuePropertyAssignee
projectId={issue?.project_detail?.id || null}
value={issue?.assignees || null}
hideDropdownArrow
onChange={(val) => handleAssigneeChange(val)}
disabled={false}
/>
</div>
</div>
);
});
};

View File

@ -45,11 +45,10 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
const { parentIssue, user } = props;
const {
user: userStore,
user: { currentProjectRole },
issue: { updateIssueStructure },
projectIssues: { updateIssue },
projectIssues: { updateIssue, removeIssue },
} = useMobxStore();
const userRole = userStore.currentProjectRole;
const router = useRouter();
const { workspaceSlug, projectId } = router.query;
@ -177,7 +176,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
[updateIssueStructure, projectId, updateIssue, user, workspaceSlug]
);
const isEditable = !!userRole && userRole >= EUserWorkspaceRoles.MEMBER;
const isEditable = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
const mutateSubIssues = (parentIssueId: string | null) => {
if (parentIssueId) mutate(SUB_ISSUES(parentIssueId));
@ -261,7 +260,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
</>
}
buttonClassName="whitespace-nowrap"
// position="left"
placement="bottom-end"
noBorder
noChevron
>
@ -297,7 +296,7 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
</>
}
buttonClassName="whitespace-nowrap"
// position="left"
placement="bottom-end"
noBorder
noChevron
>
@ -356,7 +355,8 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
</>
)}
{isEditable &&
issueCrudOperation?.delete?.toggle &&
workspaceSlug &&
projectId &&
issueCrudOperation?.delete?.issueId &&
issueCrudOperation?.delete?.issue && (
<DeleteIssueModal
@ -366,6 +366,13 @@ export const SubIssuesRoot: React.FC<ISubIssuesRoot> = observer((props) => {
handleIssueCrudOperation("delete", null, null);
}}
data={issueCrudOperation?.delete?.issue}
onSubmit={async () => {
await removeIssue(
workspaceSlug.toString(),
projectId.toString(),
issueCrudOperation?.delete?.issue?.id ?? ""
);
}}
/>
)}
</>