fix: peek overview bugs (#2043)

* fix: side peek modal shaking

* refactor: peek overview layout

* fix: date selector, activity mutation

* fix: delete issue handler

* fix: assignees mutation
This commit is contained in:
Aaryan Khandelwal 2023-09-01 13:52:55 +05:30 committed by GitHub
parent c6d9ace6a2
commit 4ba3ef5c24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 120 additions and 110 deletions

View File

@ -33,10 +33,17 @@ type Props = {
isOpen: boolean; isOpen: boolean;
handleClose: () => void; handleClose: () => void;
data: IIssue | null; data: IIssue | null;
onSubmit?: () => Promise<void>;
user: ICurrentUserResponse | undefined; user: ICurrentUserResponse | undefined;
}; };
export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data, user }) => { export const DeleteIssueModal: React.FC<Props> = ({
isOpen,
handleClose,
data,
onSubmit,
user,
}) => {
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const router = useRouter(); const router = useRouter();
@ -116,6 +123,8 @@ export const DeleteIssueModal: React.FC<Props> = ({ isOpen, handleClose, data, u
else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(data.project, params)); else mutate(PROJECT_ISSUES_LIST_WITH_PARAMS(data.project, params));
} }
if (onSubmit) onSubmit();
handleClose(); handleClose();
setToastAlert({ setToastAlert({
title: "Success", title: "Success",

View File

@ -103,7 +103,7 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({
</div> </div>
<div className="w-3/4"> <div className="w-3/4">
<SidebarAssigneeSelect <SidebarAssigneeSelect
value={issue.assignees_list} value={issue.assignees}
onChange={(val: string[]) => handleUpdateIssue({ assignees_list: val })} onChange={(val: string[]) => handleUpdateIssue({ assignees_list: val })}
disabled={readOnly} disabled={readOnly}
/> />
@ -128,23 +128,18 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({
<span className="flex-grow truncate">Start date</span> <span className="flex-grow truncate">Start date</span>
</div> </div>
<div> <div>
{issue.start_date ? ( <CustomDatePicker
<CustomDatePicker placeholder="Select start date"
placeholder="Start date" value={issue.start_date}
value={issue.start_date} onChange={(val) =>
onChange={(val) => handleUpdateIssue({
handleUpdateIssue({ start_date: val,
start_date: val, })
}) }
} className="bg-custom-background-80 border-none"
className="bg-custom-background-100" maxDate={maxDate ?? undefined}
wrapperClassName="w-full" disabled={readOnly}
maxDate={maxDate ?? undefined} />
disabled={readOnly}
/>
) : (
<span className="text-custom-text-200">Empty</span>
)}
</div> </div>
</div> </div>
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-2 text-sm">
@ -153,23 +148,18 @@ export const PeekOverviewIssueProperties: React.FC<Props> = ({
<span className="flex-grow truncate">Due date</span> <span className="flex-grow truncate">Due date</span>
</div> </div>
<div> <div>
{issue.target_date ? ( <CustomDatePicker
<CustomDatePicker placeholder="Select due date"
placeholder="Due date" value={issue.target_date}
value={issue.target_date} onChange={(val) =>
onChange={(val) => handleUpdateIssue({
handleUpdateIssue({ target_date: val,
target_date: val, })
}) }
} className="bg-custom-background-80 border-none"
className="bg-custom-background-100" minDate={minDate ?? undefined}
wrapperClassName="w-full" disabled={readOnly}
minDate={minDate ?? undefined} />
disabled={readOnly}
/>
) : (
<span className="text-custom-text-200">Empty</span>
)}
</div> </div>
</div> </div>
{/* <div className="flex items-center gap-2 text-sm"> {/* <div className="flex items-center gap-2 text-sm">

View File

@ -2,6 +2,7 @@ import React, { useEffect, useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { mutate } from "swr";
// mobx // mobx
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
@ -10,9 +11,11 @@ import { Dialog, Transition } from "@headlessui/react";
// hooks // hooks
import useUser from "hooks/use-user"; import useUser from "hooks/use-user";
// components // components
import { FullScreenPeekView, SidePeekView } from "components/issues"; import { DeleteIssueModal, FullScreenPeekView, SidePeekView } from "components/issues";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
// fetch-keys
import { PROJECT_ISSUES_ACTIVITY } from "constants/fetch-keys";
type Props = { type Props = {
handleMutation: () => void; handleMutation: () => void;
@ -28,6 +31,7 @@ export const IssuePeekOverview: React.FC<Props> = observer(
const [isSidePeekOpen, setIsSidePeekOpen] = useState(false); const [isSidePeekOpen, setIsSidePeekOpen] = useState(false);
const [isModalPeekOpen, setIsModalPeekOpen] = useState(false); const [isModalPeekOpen, setIsModalPeekOpen] = useState(false);
const [peekOverviewMode, setPeekOverviewMode] = useState<TPeekOverviewModes>("side"); const [peekOverviewMode, setPeekOverviewMode] = useState<TPeekOverviewModes>("side");
const [deleteIssueModal, setDeleteIssueModal] = useState(false);
const router = useRouter(); const router = useRouter();
const { peekIssue } = router.query; const { peekIssue } = router.query;
@ -53,6 +57,7 @@ export const IssuePeekOverview: React.FC<Props> = observer(
if (!issue || !user) return; if (!issue || !user) return;
await updateIssue(workspaceSlug, projectId, issue.id, formData, user); await updateIssue(workspaceSlug, projectId, issue.id, formData, user);
mutate(PROJECT_ISSUES_ACTIVITY(issue.id));
handleMutation(); handleMutation();
}; };
@ -81,7 +86,6 @@ export const IssuePeekOverview: React.FC<Props> = observer(
setIsSidePeekOpen(false); setIsSidePeekOpen(false);
} }
} else { } else {
console.log("Triggered");
setIsSidePeekOpen(false); setIsSidePeekOpen(false);
setIsModalPeekOpen(false); setIsModalPeekOpen(false);
} }
@ -89,33 +93,38 @@ export const IssuePeekOverview: React.FC<Props> = observer(
return ( return (
<> <>
<DeleteIssueModal
isOpen={deleteIssueModal}
handleClose={() => setDeleteIssueModal(false)}
data={issue ? { ...issue } : null}
onSubmit={handleDeleteIssue}
user={user}
/>
<Transition.Root appear show={isSidePeekOpen} as={React.Fragment}> <Transition.Root appear show={isSidePeekOpen} as={React.Fragment}>
<Dialog as="div" className="relative z-20" onClose={handleClose}> <Dialog as="div" className="relative z-20" onClose={handleClose}>
<div className="fixed inset-0 z-20 overflow-y-auto"> <div className="fixed inset-0 z-20 h-full w-full overflow-y-auto">
<div className="relative h-full w-full"> <Transition.Child
<Transition.Child as={React.Fragment}
as={React.Fragment} enter="transition-transform duration-300"
enter="transition-transform duration-300" enterFrom="translate-x-full"
enterFrom="translate-x-full" enterTo="translate-x-0"
enterTo="translate-x-0" leave="transition-transform duration-200"
leave="transition-transform duration-200" leaveFrom="translate-x-0"
leaveFrom="translate-x-0" leaveTo="translate-x-full"
leaveTo="translate-x-full" >
> <Dialog.Panel className="fixed z-20 bg-custom-background-100 top-0 right-0 h-full w-1/2 shadow-custom-shadow-md">
<Dialog.Panel className="absolute z-20 bg-custom-background-100 top-0 right-0 h-full w-1/2 shadow-custom-shadow-md"> <SidePeekView
<SidePeekView handleClose={handleClose}
handleClose={handleClose} handleDeleteIssue={() => setDeleteIssueModal(true)}
handleDeleteIssue={handleDeleteIssue} handleUpdateIssue={handleUpdateIssue}
handleUpdateIssue={handleUpdateIssue} issue={issue}
issue={issue} mode={peekOverviewMode}
mode={peekOverviewMode} readOnly={readOnly}
readOnly={readOnly} setMode={(mode) => setPeekOverviewMode(mode)}
setMode={(mode) => setPeekOverviewMode(mode)} workspaceSlug={workspaceSlug}
workspaceSlug={workspaceSlug} />
/> </Dialog.Panel>
</Dialog.Panel> </Transition.Child>
</Transition.Child>
</div>
</div> </div>
</Dialog> </Dialog>
</Transition.Root> </Transition.Root>
@ -132,49 +141,47 @@ export const IssuePeekOverview: React.FC<Props> = observer(
> >
<div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" /> <div className="fixed inset-0 bg-custom-backdrop bg-opacity-50 transition-opacity" />
</Transition.Child> </Transition.Child>
<div className="fixed inset-0 z-20 overflow-y-auto"> <div className="fixed inset-0 z-20 h-full w-full overflow-y-auto">
<div className="relative h-full w-full"> <Transition.Child
<Transition.Child as={React.Fragment}
as={React.Fragment} enter="ease-out duration-300"
enter="ease-out duration-300" enterFrom="opacity-0"
enterFrom="opacity-0" enterTo="opacity-100"
enterTo="opacity-100" leave="ease-in duration-200"
leave="ease-in duration-200" leaveFrom="opacity-100"
leaveFrom="opacity-100" leaveTo="opacity-0"
leaveTo="opacity-0" >
<Dialog.Panel
className={`fixed z-20 bg-custom-background-100 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg shadow-custom-shadow-xl transition-all duration-300 ${
peekOverviewMode === "modal" ? "h-[70%] w-3/5" : "h-[95%] w-[95%]"
}`}
> >
<Dialog.Panel {peekOverviewMode === "modal" && (
className={`absolute z-20 bg-custom-background-100 top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg shadow-custom-shadow-xl transition-all duration-300 ${ <SidePeekView
peekOverviewMode === "modal" ? "h-[70%] w-3/5" : "h-[95%] w-[95%]" handleClose={handleClose}
}`} handleDeleteIssue={() => setDeleteIssueModal(true)}
> handleUpdateIssue={handleUpdateIssue}
{peekOverviewMode === "modal" && ( issue={issue}
<SidePeekView mode={peekOverviewMode}
handleClose={handleClose} readOnly={readOnly}
handleDeleteIssue={handleDeleteIssue} setMode={(mode) => setPeekOverviewMode(mode)}
handleUpdateIssue={handleUpdateIssue} workspaceSlug={workspaceSlug}
issue={issue} />
mode={peekOverviewMode} )}
readOnly={readOnly} {peekOverviewMode === "full" && (
setMode={(mode) => setPeekOverviewMode(mode)} <FullScreenPeekView
workspaceSlug={workspaceSlug} handleClose={handleClose}
/> handleDeleteIssue={() => setDeleteIssueModal(true)}
)} handleUpdateIssue={handleUpdateIssue}
{peekOverviewMode === "full" && ( issue={issue}
<FullScreenPeekView mode={peekOverviewMode}
handleClose={handleClose} readOnly={readOnly}
handleDeleteIssue={handleDeleteIssue} setMode={(mode) => setPeekOverviewMode(mode)}
handleUpdateIssue={handleUpdateIssue} workspaceSlug={workspaceSlug}
issue={issue} />
mode={peekOverviewMode} )}
readOnly={readOnly} </Dialog.Panel>
setMode={(mode) => setPeekOverviewMode(mode)} </Transition.Child>
workspaceSlug={workspaceSlug}
/>
)}
</Dialog.Panel>
</Transition.Child>
</div>
</div> </div>
</Dialog> </Dialog>
</Transition.Root> </Transition.Root>

View File

@ -51,7 +51,10 @@ export const SidebarAssigneeSelect: React.FC<Props> = ({ value, onChange, disabl
<span className="text-custom-text-100 text-xs">{value.length} Assignees</span> <span className="text-custom-text-100 text-xs">{value.length} Assignees</span>
</div> </div>
) : ( ) : (
<button type="button" className="bg-custom-background-80 px-2.5 py-0.5 text-xs rounded"> <button
type="button"
className="bg-custom-background-80 px-2.5 py-0.5 text-xs rounded text-custom-text-200"
>
No assignees No assignees
</button> </button>
)} )}

View File

@ -27,7 +27,7 @@ export const SidebarPrioritySelect: React.FC<Props> = ({ value, onChange, disabl
? "border-yellow-500/20 bg-yellow-500/20 text-yellow-500" ? "border-yellow-500/20 bg-yellow-500/20 text-yellow-500"
: value === "low" : value === "low"
? "border-green-500/20 bg-green-500/20 text-green-500" ? "border-green-500/20 bg-green-500/20 text-green-500"
: "bg-custom-background-80 border-custom-border-200" : "bg-custom-background-80 border-custom-border-200 text-custom-text-200"
}`} }`}
> >
<span className="grid place-items-center -my-1"> <span className="grid place-items-center -my-1">

View File

@ -41,7 +41,7 @@ const CustomSelect = ({
> >
<> <>
{customButton ? ( {customButton ? (
<Listbox.Button as="div">{customButton}</Listbox.Button> <Listbox.Button as={React.Fragment}>{customButton}</Listbox.Button>
) : ( ) : (
<Listbox.Button <Listbox.Button
type="button" type="button"

View File

@ -116,11 +116,12 @@ class IssuesStore {
const originalIssue = { ...this.issues[issueId] }; const originalIssue = { ...this.issues[issueId] };
// immediately update the issue in the store // immediately update the issue in the store
const updatedIssue = { ...originalIssue, ...issueForm }; const updatedIssue = { ...this.issues[issueId], ...issueForm };
if (updatedIssue.assignees_list) updatedIssue.assignees = updatedIssue.assignees_list;
try { try {
runInAction(() => { runInAction(() => {
this.issues[issueId] = updatedIssue; this.issues[issueId] = { ...updatedIssue };
}); });
// make a patch request to update the issue // make a patch request to update the issue