[WEB-704] fix: inbox responsiveness (#4275)
* chore: inbox responsiveness * fix: sidebar in full view * style: border theme * condition update
This commit is contained in:
parent
ea436c925a
commit
0c880bbbc8
9 changed files with 258 additions and 25 deletions
|
|
@ -17,6 +17,7 @@ import { Button, ControlLink, CustomMenu, TOAST_TYPE, setToast } from "@plane/ui
|
|||
import {
|
||||
DeclineIssueModal,
|
||||
DeleteInboxIssueModal,
|
||||
InboxIssueActionsMobileHeader,
|
||||
InboxIssueCreateEditModalRoot,
|
||||
InboxIssueSnoozeModal,
|
||||
InboxIssueStatus,
|
||||
|
|
@ -38,10 +39,12 @@ type TInboxIssueActionsHeader = {
|
|||
projectId: string;
|
||||
inboxIssue: IInboxIssueStore | undefined;
|
||||
isSubmitting: "submitting" | "submitted" | "saved";
|
||||
toggleMobileSidebar: boolean;
|
||||
setToggleMobileSidebar: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((props) => {
|
||||
const { workspaceSlug, projectId, inboxIssue, isSubmitting } = props;
|
||||
const { workspaceSlug, projectId, inboxIssue, isSubmitting, toggleMobileSidebar, setToggleMobileSidebar } = props;
|
||||
// states
|
||||
const [isSnoozeDateModalOpen, setIsSnoozeDateModalOpen] = useState(false);
|
||||
const [selectDuplicateIssue, setSelectDuplicateIssue] = useState(false);
|
||||
|
|
@ -207,7 +210,7 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
/>
|
||||
</>
|
||||
|
||||
<div className="relative flex h-full w-full items-center justify-between gap-2 px-4">
|
||||
<div className="hidden relative lg:flex h-full w-full items-center justify-between gap-2 px-4">
|
||||
<div className="flex items-center gap-4">
|
||||
{issue?.project_id && issue.sequence_id && (
|
||||
<h3 className="text-base font-medium text-custom-text-300 flex-shrink-0">
|
||||
|
|
@ -319,6 +322,28 @@ export const InboxIssueActionsHeader: FC<TInboxIssueActionsHeader> = observer((p
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:hidden">
|
||||
<InboxIssueActionsMobileHeader
|
||||
inboxIssue={inboxIssue}
|
||||
isSubmitting={isSubmitting}
|
||||
handleCopyIssueLink={handleCopyIssueLink}
|
||||
setAcceptIssueModal={setAcceptIssueModal}
|
||||
setDeclineIssueModal={setDeclineIssueModal}
|
||||
setIsSnoozeDateModalOpen={setIsSnoozeDateModalOpen}
|
||||
setSelectDuplicateIssue={setSelectDuplicateIssue}
|
||||
setDeleteIssueModal={setDeleteIssueModal}
|
||||
canMarkAsAccepted={canMarkAsAccepted}
|
||||
canMarkAsDeclined={canMarkAsDeclined}
|
||||
canMarkAsDuplicate={canMarkAsDuplicate}
|
||||
canDelete={canDelete}
|
||||
isAcceptedOrDeclined={isAcceptedOrDeclined}
|
||||
handleInboxIssueNavigation={handleInboxIssueNavigation}
|
||||
workspaceSlug={workspaceSlug}
|
||||
toggleMobileSidebar={toggleMobileSidebar}
|
||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
170
web/components/inbox/content/inbox-issue-mobile-header.tsx
Normal file
170
web/components/inbox/content/inbox-issue-mobile-header.tsx
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { useRouter } from "next/router";
|
||||
import {
|
||||
CircleCheck,
|
||||
CircleX,
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
Clock,
|
||||
ExternalLink,
|
||||
FileStack,
|
||||
Link,
|
||||
Trash2,
|
||||
PanelLeft,
|
||||
} from "lucide-react";
|
||||
import { CustomMenu } from "@plane/ui";
|
||||
// components
|
||||
import { InboxIssueStatus } from "@/components/inbox";
|
||||
import { IssueUpdateStatus } from "@/components/issues";
|
||||
// helpers
|
||||
import { cn } from "@/helpers/common.helper";
|
||||
// store types
|
||||
import type { IInboxIssueStore } from "@/store/inbox/inbox-issue.store";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string;
|
||||
inboxIssue: IInboxIssueStore | undefined;
|
||||
isSubmitting: "submitting" | "submitted" | "saved";
|
||||
handleInboxIssueNavigation: (direction: "next" | "prev") => void;
|
||||
canMarkAsAccepted: boolean;
|
||||
canMarkAsDeclined: boolean;
|
||||
isAcceptedOrDeclined: boolean | undefined;
|
||||
canMarkAsDuplicate: boolean;
|
||||
canDelete: boolean;
|
||||
setAcceptIssueModal: (value: boolean) => void;
|
||||
setDeclineIssueModal: (value: boolean) => void;
|
||||
setDeleteIssueModal: (value: boolean) => void;
|
||||
setIsSnoozeDateModalOpen: (value: boolean) => void;
|
||||
setSelectDuplicateIssue: (value: boolean) => void;
|
||||
handleCopyIssueLink: () => void;
|
||||
toggleMobileSidebar: boolean;
|
||||
setToggleMobileSidebar: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export const InboxIssueActionsMobileHeader: React.FC<Props> = observer((props) => {
|
||||
const {
|
||||
inboxIssue,
|
||||
isSubmitting,
|
||||
handleInboxIssueNavigation,
|
||||
canMarkAsAccepted,
|
||||
canMarkAsDeclined,
|
||||
canDelete,
|
||||
canMarkAsDuplicate,
|
||||
isAcceptedOrDeclined,
|
||||
workspaceSlug,
|
||||
setAcceptIssueModal,
|
||||
setDeclineIssueModal,
|
||||
setDeleteIssueModal,
|
||||
setIsSnoozeDateModalOpen,
|
||||
setSelectDuplicateIssue,
|
||||
handleCopyIssueLink,
|
||||
toggleMobileSidebar,
|
||||
setToggleMobileSidebar,
|
||||
} = props;
|
||||
const router = useRouter();
|
||||
const issue = inboxIssue?.issue;
|
||||
const currentInboxIssueId = issue?.id;
|
||||
|
||||
if (!issue || !inboxIssue) return null;
|
||||
|
||||
return (
|
||||
<div className="h-12 relative flex border-custom-border-200 w-full items-center gap-2 px-4">
|
||||
<PanelLeft
|
||||
onClick={() => setToggleMobileSidebar(!toggleMobileSidebar)}
|
||||
className={cn(
|
||||
"w-4 h-4 flex-shrink-0 mr-2",
|
||||
toggleMobileSidebar ? "text-custom-primary-100" : "text-custom-text-200"
|
||||
)}
|
||||
/>
|
||||
<div className="flex items-center gap-2 w-full">
|
||||
<div className="flex items-center gap-x-2">
|
||||
<button
|
||||
type="button"
|
||||
className="rounded border border-custom-border-200 p-1.5"
|
||||
onClick={() => handleInboxIssueNavigation("prev")}
|
||||
>
|
||||
<ChevronUp size={14} strokeWidth={2} />
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="rounded border border-custom-border-200 p-1.5"
|
||||
onClick={() => handleInboxIssueNavigation("next")}
|
||||
>
|
||||
<ChevronDown size={14} strokeWidth={2} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<InboxIssueStatus inboxIssue={inboxIssue} iconSize={12} />
|
||||
<div className="flex items-center justify-end w-full">
|
||||
<IssueUpdateStatus isSubmitting={isSubmitting} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-auto">
|
||||
<CustomMenu verticalEllipsis placement="bottom-start">
|
||||
{isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem onClick={handleCopyIssueLink}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Link size={14} strokeWidth={2} />
|
||||
Copy issue link
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem
|
||||
onClick={() =>
|
||||
router.push(`/${workspaceSlug}/projects/${issue?.project_id}/issues/${currentInboxIssueId}`)
|
||||
}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<ExternalLink size={14} strokeWidth={2} />
|
||||
Open issue
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsAccepted && !isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem onClick={() => setIsSnoozeDateModalOpen(true)}>
|
||||
<div className="flex items-center gap-2">
|
||||
<Clock size={14} strokeWidth={2} />
|
||||
Snooze
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsDuplicate && !isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem onClick={() => setSelectDuplicateIssue(true)}>
|
||||
<div className="flex items-center gap-2">
|
||||
<FileStack size={14} strokeWidth={2} />
|
||||
Mark as duplicate
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsAccepted && (
|
||||
<CustomMenu.MenuItem onClick={() => setAcceptIssueModal(true)}>
|
||||
<div className="flex items-center gap-2 text-green-500">
|
||||
<CircleCheck size={14} strokeWidth={2} />
|
||||
Accept
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canMarkAsDeclined && (
|
||||
<CustomMenu.MenuItem onClick={() => setDeclineIssueModal(true)}>
|
||||
<div className="flex items-center gap-2 text-red-500">
|
||||
<CircleX size={14} strokeWidth={2} />
|
||||
Decline
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
{canDelete && !isAcceptedOrDeclined && (
|
||||
<CustomMenu.MenuItem onClick={() => setDeleteIssueModal(true)}>
|
||||
<div className="flex items-center gap-2 text-red-500">
|
||||
<Trash2 size={14} strokeWidth={2} />
|
||||
Delete
|
||||
</div>
|
||||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
</CustomMenu>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
export * from "./root";
|
||||
export * from "./inbox-issue-header";
|
||||
export * from "./inbox-issue-mobile-header";
|
||||
export * from "./issue-properties";
|
||||
export * from "./issue-root";
|
||||
|
|
|
|||
|
|
@ -9,10 +9,12 @@ type TInboxContentRoot = {
|
|||
workspaceSlug: string;
|
||||
projectId: string;
|
||||
inboxIssueId: string;
|
||||
toggleMobileSidebar: boolean;
|
||||
setToggleMobileSidebar: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
||||
const { workspaceSlug, projectId, inboxIssueId } = props;
|
||||
const { workspaceSlug, projectId, inboxIssueId, toggleMobileSidebar, setToggleMobileSidebar } = props;
|
||||
// states
|
||||
const [isSubmitting, setIsSubmitting] = useState<"submitting" | "submitted" | "saved">("saved");
|
||||
// hooks
|
||||
|
|
@ -43,6 +45,8 @@ export const InboxContentRoot: FC<TInboxContentRoot> = observer((props) => {
|
|||
<div className="w-full h-full overflow-hidden relative flex flex-col">
|
||||
<div className="flex-shrink-0 min-h-[50px] border-b border-custom-border-300">
|
||||
<InboxIssueActionsHeader
|
||||
setToggleMobileSidebar={setToggleMobileSidebar}
|
||||
toggleMobileSidebar={toggleMobileSidebar}
|
||||
workspaceSlug={workspaceSlug}
|
||||
projectId={projectId}
|
||||
inboxIssue={inboxIssue}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue