forked from github/plane
fix: merge conflicts resolved
This commit is contained in:
commit
9cf5348019
@ -42,8 +42,8 @@ export const EditorHeader = (props: IEditorHeader) => {
|
|||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center border-b border-custom-border-200 px-5 py-2">
|
<div className="flex items-center border-b border-custom-border-200 md:px-5 px-3 py-2">
|
||||||
<div className="w-56 flex-shrink-0 lg:w-72">
|
<div className="md:w-56 flex-shrink-0 lg:w-72 w-fit">
|
||||||
<SummaryPopover
|
<SummaryPopover
|
||||||
editor={editor}
|
editor={editor}
|
||||||
markings={markings}
|
markings={markings}
|
||||||
@ -52,7 +52,7 @@ export const EditorHeader = (props: IEditorHeader) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex-shrink-0">
|
<div className="flex-shrink-0 hidden md:flex">
|
||||||
{!readonly && uploadFile && (
|
{!readonly && uploadFile && (
|
||||||
<FixedMenu editor={editor} uploadFile={uploadFile} setIsSubmitting={setIsSubmitting} />
|
<FixedMenu editor={editor} uploadFile={uploadFile} setIsSubmitting={setIsSubmitting} />
|
||||||
)}
|
)}
|
||||||
|
@ -152,7 +152,7 @@ export const PageRenderer = (props: IPageRenderer) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full pb-64 pl-7 pt-5 page-renderer">
|
<div className="w-full pb-64 md:pl-7 pl-3 pt-5 page-renderer">
|
||||||
{!readonly ? (
|
{!readonly ? (
|
||||||
<input
|
<input
|
||||||
onChange={(e) => handlePageTitleChange(e.target.value)}
|
onChange={(e) => handlePageTitleChange(e.target.value)}
|
||||||
|
@ -40,6 +40,19 @@ export const SummaryPopover: React.FC<Props> = (props) => {
|
|||||||
>
|
>
|
||||||
<List className="h-4 w-4" />
|
<List className="h-4 w-4" />
|
||||||
</button>
|
</button>
|
||||||
|
<div className="md:hidden block">
|
||||||
|
{sidePeekVisible && (
|
||||||
|
<div
|
||||||
|
className="z-10 max-h-80 w-64 overflow-y-auto rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 shadow-custom-shadow-rg"
|
||||||
|
ref={setPopperElement}
|
||||||
|
style={summaryPopoverStyles.popper}
|
||||||
|
{...summaryPopoverAttributes.popper}
|
||||||
|
>
|
||||||
|
<ContentBrowser editor={editor} markings={markings} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="hidden md:block">
|
||||||
{!sidePeekVisible && (
|
{!sidePeekVisible && (
|
||||||
<div
|
<div
|
||||||
className="z-10 hidden max-h-80 w-64 overflow-y-auto rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 shadow-custom-shadow-rg group-hover/summary-popover:block"
|
className="z-10 hidden max-h-80 w-64 overflow-y-auto rounded border-[0.5px] border-custom-border-200 bg-custom-background-100 p-3 shadow-custom-shadow-rg group-hover/summary-popover:block"
|
||||||
@ -51,5 +64,6 @@ export const SummaryPopover: React.FC<Props> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,7 @@ import { DocumentDetails } from "src/types/editor-types";
|
|||||||
import { PageRenderer } from "src/ui/components/page-renderer";
|
import { PageRenderer } from "src/ui/components/page-renderer";
|
||||||
import { getMenuOptions } from "src/utils/menu-options";
|
import { getMenuOptions } from "src/utils/menu-options";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
import { FixedMenu } from "src";
|
||||||
|
|
||||||
interface IDocumentEditor {
|
interface IDocumentEditor {
|
||||||
// document info
|
// document info
|
||||||
@ -149,11 +150,14 @@ const DocumentEditor = ({
|
|||||||
documentDetails={documentDetails}
|
documentDetails={documentDetails}
|
||||||
isSubmitting={isSubmitting}
|
isSubmitting={isSubmitting}
|
||||||
/>
|
/>
|
||||||
|
<div className="flex-shrink-0 md:hidden border-b border-custom-border-200 pl-3 py-2">
|
||||||
|
{uploadFile && <FixedMenu editor={editor} uploadFile={uploadFile} setIsSubmitting={setIsSubmitting} />}
|
||||||
|
</div>
|
||||||
<div className="flex h-full w-full overflow-y-auto frame-renderer">
|
<div className="flex h-full w-full overflow-y-auto frame-renderer">
|
||||||
<div className="sticky top-0 h-full w-56 flex-shrink-0 lg:w-72">
|
<div className="sticky top-0 h-full w-56 flex-shrink-0 lg:w-72 hidden md:block">
|
||||||
<SummarySideBar editor={editor} markings={markings} sidePeekVisible={sidePeekVisible} />
|
<SummarySideBar editor={editor} markings={markings} sidePeekVisible={sidePeekVisible} />
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)] page-renderer">
|
<div className="h-full w-full md:w-[calc(100%-14rem)] lg:w-[calc(100%-18rem-18rem)] page-renderer">
|
||||||
<PageRenderer
|
<PageRenderer
|
||||||
onActionCompleteHandler={onActionCompleteHandler}
|
onActionCompleteHandler={onActionCompleteHandler}
|
||||||
hideDragHandle={hideDragHandleOnMouseLeave}
|
hideDragHandle={hideDragHandleOnMouseLeave}
|
||||||
|
@ -77,7 +77,7 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center divide-x divide-custom-border-200">
|
<div className="flex flex-wrap items-center divide-x divide-custom-border-200">
|
||||||
<div className="flex items-center gap-0.5 pr-2">
|
<div className="flex items-center gap-0.5 pr-2">
|
||||||
{basicMarkItems.map((item) => (
|
{basicMarkItems.map((item) => (
|
||||||
<button
|
<button
|
||||||
|
@ -7,7 +7,7 @@ export const SidebarHamburgerToggle: FC = observer(() => {
|
|||||||
const { theme: themStore } = useApplication();
|
const { theme: themStore } = useApplication();
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="w-7 h-7 rounded flex justify-center items-center bg-custom-background-80 transition-all hover:bg-custom-background-90 cursor-pointer group md:hidden"
|
className="w-7 h-7 flex-shrink-0 rounded flex justify-center items-center bg-custom-background-80 transition-all hover:bg-custom-background-90 cursor-pointer group md:hidden"
|
||||||
onClick={() => themStore.toggleSidebar()}
|
onClick={() => themStore.toggleSidebar()}
|
||||||
>
|
>
|
||||||
<Menu size={14} className="text-custom-text-200 group-hover:text-custom-text-100 transition-all" />
|
<Menu size={14} className="text-custom-text-200 group-hover:text-custom-text-100 transition-all" />
|
||||||
|
@ -65,14 +65,14 @@ export const EmptyState: React.FC<Props> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center min-h-full min-w-full overflow-y-auto py-10 px-20">
|
<div className="flex items-center justify-center min-h-full min-w-full overflow-y-auto py-10 md:px-20 px-5">
|
||||||
<div
|
<div
|
||||||
className={cn("flex flex-col gap-5", {
|
className={cn("flex flex-col gap-5", {
|
||||||
"min-w-[24rem] max-w-[45rem]": size === "sm",
|
"md:min-w-[24rem] max-w-[45rem]": size === "sm",
|
||||||
"min-w-[30rem] max-w-[60rem]": size === "lg",
|
"md:min-w-[30rem] max-w-[60rem]": size === "lg",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col gap-1.5 flex-shrink-0">{emptyStateHeader}</div>
|
<div className="flex flex-col gap-1.5 flex-shrink">{emptyStateHeader}</div>
|
||||||
|
|
||||||
<Image
|
<Image
|
||||||
src={image}
|
src={image}
|
||||||
|
@ -36,6 +36,8 @@ export const PageDetailsHeader: FC<IPagesHeaderProps> = observer((props) => {
|
|||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
link={
|
link={
|
||||||
|
<span>
|
||||||
|
<span className="hidden md:block">
|
||||||
<BreadcrumbLink
|
<BreadcrumbLink
|
||||||
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}
|
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}
|
||||||
label={currentProjectDetails?.name ?? "Project"}
|
label={currentProjectDetails?.name ?? "Project"}
|
||||||
@ -51,8 +53,17 @@ export const PageDetailsHeader: FC<IPagesHeaderProps> = observer((props) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
</span>
|
||||||
|
<span className="md:hidden">
|
||||||
|
<BreadcrumbLink
|
||||||
|
href={`/${workspaceSlug}/projects/${currentProjectDetails?.id}/issues`}
|
||||||
|
label={"..."}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
link={
|
link={
|
||||||
|
@ -3,7 +3,7 @@ import useSWR from "swr";
|
|||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// hooks
|
// hooks
|
||||||
import { useProject } from "hooks/store";
|
import { useApplication, useProject } from "hooks/store";
|
||||||
// ui
|
// ui
|
||||||
import { Breadcrumbs, LayersIcon } from "@plane/ui";
|
import { Breadcrumbs, LayersIcon } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
@ -15,6 +15,8 @@ import { ISSUE_DETAILS } from "constants/fetch-keys";
|
|||||||
// components
|
// components
|
||||||
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
|
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
|
||||||
import { BreadcrumbLink } from "components/common";
|
import { BreadcrumbLink } from "components/common";
|
||||||
|
import { PanelRight } from "lucide-react";
|
||||||
|
import { cn } from "helpers/common.helper";
|
||||||
|
|
||||||
// services
|
// services
|
||||||
const issueService = new IssueService();
|
const issueService = new IssueService();
|
||||||
@ -25,6 +27,7 @@ export const ProjectIssueDetailsHeader: FC = observer(() => {
|
|||||||
const { workspaceSlug, projectId, issueId } = router.query;
|
const { workspaceSlug, projectId, issueId } = router.query;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { currentProjectDetails, getProjectById } = useProject();
|
const { currentProjectDetails, getProjectById } = useProject();
|
||||||
|
const { theme: themeStore } = useApplication();
|
||||||
|
|
||||||
const { data: issueDetails } = useSWR(
|
const { data: issueDetails } = useSWR(
|
||||||
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
|
workspaceSlug && projectId && issueId ? ISSUE_DETAILS(issueId as string) : null,
|
||||||
@ -33,12 +36,14 @@ export const ProjectIssueDetailsHeader: FC = observer(() => {
|
|||||||
: null
|
: null
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const isSidebarCollapsed = themeStore.issueDetailSidebarCollapsed;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
|
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
|
||||||
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
|
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
|
||||||
<SidebarHamburgerToggle />
|
<SidebarHamburgerToggle />
|
||||||
<div>
|
<div>
|
||||||
<Breadcrumbs>
|
<Breadcrumbs onBack={router.back}>
|
||||||
<Breadcrumbs.BreadcrumbItem
|
<Breadcrumbs.BreadcrumbItem
|
||||||
type="text"
|
type="text"
|
||||||
link={
|
link={
|
||||||
@ -85,6 +90,9 @@ export const ProjectIssueDetailsHeader: FC = observer(() => {
|
|||||||
</Breadcrumbs>
|
</Breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<button className="block md:hidden" onClick={() => themeStore.toggleIssueDetailSidebar()}>
|
||||||
|
<PanelRight className={cn("w-4 h-4 ", !isSidebarCollapsed ? "text-custom-primary-100" : " text-custom-text-200")} />
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -213,7 +213,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
|
|||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
<Inbox className="w-4 h-4 mr-2 text-custom-text-200" />
|
<Inbox className="w-4 h-4 mr-2 text-custom-text-200 block md:hidden" />
|
||||||
</Link>
|
</Link>
|
||||||
)}
|
)}
|
||||||
{canUserCreateIssue && (
|
{canUserCreateIssue && (
|
||||||
|
@ -33,7 +33,7 @@ export const IssueActivityBlockComponent: FC<TIssueActivityBlockComponent> = (pr
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="absolute left-[13px] top-0 bottom-0 w-0.5 bg-custom-background-80" aria-hidden={true} />
|
<div className="absolute left-[13px] top-0 bottom-0 w-0.5 bg-custom-background-80" aria-hidden={true} />
|
||||||
<div className="flex-shrink-0 ring-6 w-7 h-7 rounded-full overflow-hidden flex justify-center items-center z-10 bg-custom-background-80 text-custom-text-200">
|
<div className="flex-shrink-0 ring-6 w-7 h-7 rounded-full overflow-hidden flex justify-center items-center z-[4] bg-custom-background-80 text-custom-text-200">
|
||||||
{icon ? icon : <Network className="w-3.5 h-3.5" />}
|
{icon ? icon : <Network className="w-3.5 h-3.5" />}
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full text-custom-text-200">
|
<div className="w-full text-custom-text-200">
|
||||||
|
@ -9,7 +9,7 @@ import { EmptyState } from "components/common";
|
|||||||
// images
|
// images
|
||||||
import emptyIssue from "public/empty-state/issue.svg";
|
import emptyIssue from "public/empty-state/issue.svg";
|
||||||
// hooks
|
// hooks
|
||||||
import { useEventTracker, useIssueDetail, useIssues, useUser } from "hooks/store";
|
import { useApplication, useEventTracker, useIssueDetail, useIssues, useUser } from "hooks/store";
|
||||||
import useToast from "hooks/use-toast";
|
import useToast from "hooks/use-toast";
|
||||||
// types
|
// types
|
||||||
import { TIssue } from "@plane/types";
|
import { TIssue } from "@plane/types";
|
||||||
@ -17,6 +17,7 @@ import { TIssue } from "@plane/types";
|
|||||||
import { EUserProjectRoles } from "constants/project";
|
import { EUserProjectRoles } from "constants/project";
|
||||||
import { EIssuesStoreType } from "constants/issue";
|
import { EIssuesStoreType } from "constants/issue";
|
||||||
import { ISSUE_UPDATED, ISSUE_DELETED } from "constants/event-tracker";
|
import { ISSUE_UPDATED, ISSUE_DELETED } from "constants/event-tracker";
|
||||||
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
export type TIssueOperations = {
|
export type TIssueOperations = {
|
||||||
fetch: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
fetch: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||||
@ -52,7 +53,7 @@ export type TIssueDetailRoot = {
|
|||||||
is_archived?: boolean;
|
is_archived?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const IssueDetailRoot: FC<TIssueDetailRoot> = (props) => {
|
export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
|
||||||
const { workspaceSlug, projectId, issueId, is_archived = false } = props;
|
const { workspaceSlug, projectId, issueId, is_archived = false } = props;
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -76,6 +77,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = (props) => {
|
|||||||
const {
|
const {
|
||||||
membership: { currentProjectRole },
|
membership: { currentProjectRole },
|
||||||
} = useUser();
|
} = useUser();
|
||||||
|
const { theme: themeStore } = useApplication();
|
||||||
|
|
||||||
const issueOperations: TIssueOperations = useMemo(
|
const issueOperations: TIssueOperations = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@ -347,8 +349,8 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = (props) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex h-full overflow-hidden">
|
<div className="flex w-full h-full overflow-hidden">
|
||||||
<div className="h-full w-2/3 space-y-5 divide-y-2 divide-custom-border-300 overflow-y-auto p-5">
|
<div className="h-full w-full max-w-2/3 space-y-5 divide-y-2 divide-custom-border-300 overflow-y-auto p-5">
|
||||||
<IssueMainContent
|
<IssueMainContent
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
@ -357,7 +359,10 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = (props) => {
|
|||||||
is_editable={!is_archived && is_editable}
|
is_editable={!is_archived && is_editable}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-full w-1/3 space-y-5 overflow-hidden border-l border-custom-border-300 py-5">
|
<div
|
||||||
|
className="h-full w-full sm:w-1/2 md:w-1/3 space-y-5 overflow-hidden border-l border-custom-border-300 py-5 fixed md:relative bg-custom-sidebar-background-100 right-0 z-[5]"
|
||||||
|
style={themeStore.issueDetailSidebarCollapsed ? { right: `-${window?.innerWidth || 0}px` } : {}}
|
||||||
|
>
|
||||||
<IssueDetailsSidebar
|
<IssueDetailsSidebar
|
||||||
workspaceSlug={workspaceSlug}
|
workspaceSlug={workspaceSlug}
|
||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
@ -374,4 +379,4 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = (props) => {
|
|||||||
<IssuePeekOverview />
|
<IssuePeekOverview />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
@ -187,8 +187,7 @@ export const IssueDetailsSidebar: React.FC<Props> = observer((props) => {
|
|||||||
buttonVariant={issue?.assignee_ids?.length > 1 ? "transparent-without-text" : "transparent-with-text"}
|
buttonVariant={issue?.assignee_ids?.length > 1 ? "transparent-without-text" : "transparent-with-text"}
|
||||||
className="w-3/5 flex-grow group"
|
className="w-3/5 flex-grow group"
|
||||||
buttonContainerClassName="w-full text-left"
|
buttonContainerClassName="w-full text-left"
|
||||||
buttonClassName={`text-sm justify-between ${
|
buttonClassName={`text-sm justify-between ${issue?.assignee_ids.length > 0 ? "" : "text-custom-text-400"
|
||||||
issue?.assignee_ids.length > 0 ? "" : "text-custom-text-400"
|
|
||||||
}`}
|
}`}
|
||||||
hideIcon={issue.assignee_ids?.length === 0}
|
hideIcon={issue.assignee_ids?.length === 0}
|
||||||
dropdownArrow
|
dropdownArrow
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { FC, useState } from "react";
|
import { FC, useState } from "react";
|
||||||
import { Bell } from "lucide-react";
|
import { Bell, BellOff } from "lucide-react";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
// UI
|
// UI
|
||||||
import { Button } from "@plane/ui";
|
import { Button } from "@plane/ui";
|
||||||
@ -52,12 +52,20 @@ export const IssueSubscription: FC<TIssueSubscription> = observer((props) => {
|
|||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
prependIcon={<Bell className="h-3 w-3" />}
|
prependIcon={subscription?.subscribed ? <BellOff /> : <Bell className="h-3 w-3" />}
|
||||||
variant="outline-primary"
|
variant="outline-primary"
|
||||||
className="hover:!bg-custom-primary-100/20"
|
className="hover:!bg-custom-primary-100/20"
|
||||||
onClick={handleSubscription}
|
onClick={handleSubscription}
|
||||||
>
|
>
|
||||||
{loading ? "Loading..." : subscription?.subscribed ? "Unsubscribe" : "Subscribe"}
|
{loading ? (
|
||||||
|
<span>
|
||||||
|
<span className="hidden sm:block">Loading</span>...
|
||||||
|
</span>
|
||||||
|
) : subscription?.subscribed ? (
|
||||||
|
<div className="hidden sm:block">Unsubscribe</div>
|
||||||
|
) : (
|
||||||
|
<div className="hidden sm:block">Subscribe</div>
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -66,11 +66,11 @@ export const HeaderColumn = (props: Props) => {
|
|||||||
}
|
}
|
||||||
onMenuClose={onClose}
|
onMenuClose={onClose}
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
|
closeOnSelect
|
||||||
>
|
>
|
||||||
<CustomMenu.MenuItem onClick={() => handleOrderBy(propertyDetails.ascendingOrderKey, property)}>
|
<CustomMenu.MenuItem onClick={() => handleOrderBy(propertyDetails.ascendingOrderKey, property)}>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center justify-between gap-1.5 px-1 ${
|
className={`flex items-center justify-between gap-1.5 px-1 ${selectedMenuItem === `${propertyDetails.ascendingOrderKey}_${property}`
|
||||||
selectedMenuItem === `${propertyDetails.ascendingOrderKey}_${property}`
|
|
||||||
? "text-custom-text-100"
|
? "text-custom-text-100"
|
||||||
: "text-custom-text-200 hover:text-custom-text-100"
|
: "text-custom-text-200 hover:text-custom-text-100"
|
||||||
}`}
|
}`}
|
||||||
@ -87,8 +87,7 @@ export const HeaderColumn = (props: Props) => {
|
|||||||
</CustomMenu.MenuItem>
|
</CustomMenu.MenuItem>
|
||||||
<CustomMenu.MenuItem onClick={() => handleOrderBy(propertyDetails.descendingOrderKey, property)}>
|
<CustomMenu.MenuItem onClick={() => handleOrderBy(propertyDetails.descendingOrderKey, property)}>
|
||||||
<div
|
<div
|
||||||
className={`flex items-center justify-between gap-1.5 px-1 ${
|
className={`flex items-center justify-between gap-1.5 px-1 ${selectedMenuItem === `${propertyDetails.descendingOrderKey}_${property}`
|
||||||
selectedMenuItem === `${propertyDetails.descendingOrderKey}_${property}`
|
|
||||||
? "text-custom-text-100"
|
? "text-custom-text-100"
|
||||||
: "text-custom-text-200 hover:text-custom-text-100"
|
: "text-custom-text-200 hover:text-custom-text-100"
|
||||||
}`}
|
}`}
|
||||||
|
@ -104,7 +104,7 @@ export const CreateUpdatePageModal: FC<Props> = (props) => {
|
|||||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
>
|
>
|
||||||
<Dialog.Panel className="relative transform rounded-lg bg-custom-background-100 p-5 px-4 text-left shadow-custom-shadow-md transition-all sm:w-full sm:max-w-2xl">
|
<Dialog.Panel className="relative transform rounded-lg bg-custom-background-100 p-5 px-4 text-left shadow-custom-shadow-md transition-all w-full sm:max-w-2xl">
|
||||||
<PageForm handleFormSubmit={handleFormSubmit} handleClose={handleClose} pageStore={pageStore} />
|
<PageForm handleFormSubmit={handleFormSubmit} handleClose={handleClose} pageStore={pageStore} />
|
||||||
</Dialog.Panel>
|
</Dialog.Panel>
|
||||||
</Transition.Child>
|
</Transition.Child>
|
||||||
|
@ -67,7 +67,7 @@ export const PageForm: React.FC<Props> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5 flex items-center justify-between gap-2">
|
<div className="mt-5 md:flex items-center justify-between gap-2">
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="access"
|
name="access"
|
||||||
@ -100,7 +100,7 @@ export const PageForm: React.FC<Props> = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2 justify-end mt-5 md:mt-0">
|
||||||
<Button variant="neutral-primary" size="sm" onClick={handleClose} tabIndex={4}>
|
<Button variant="neutral-primary" size="sm" onClick={handleClose} tabIndex={4}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -155,7 +155,7 @@ export const PagesListItem: FC<IPagesListItem> = observer(({ pageId, projectId }
|
|||||||
<DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} pageId={pageId} />
|
<DeletePageModal isOpen={deletePageModal} onClose={() => setDeletePageModal(false)} pageId={pageId} />
|
||||||
<li>
|
<li>
|
||||||
<Link href={`/${workspaceSlug}/projects/${projectId}/pages/${pageId}`}>
|
<Link href={`/${workspaceSlug}/projects/${projectId}/pages/${pageId}`}>
|
||||||
<div className="relative rounded p-4 text-custom-text-200 hover:bg-custom-background-80">
|
<div className="relative rounded p-3 md:p-4 text-custom-text-200 hover:bg-custom-background-80">
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2 overflow-hidden">
|
<div className="flex items-center gap-2 overflow-hidden">
|
||||||
<FileText className="h-4 w-4 shrink-0" />
|
<FileText className="h-4 w-4 shrink-0" />
|
||||||
|
@ -52,7 +52,7 @@ export const RecentPagesList: FC = observer(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={key}>
|
<div key={key}>
|
||||||
<h2 className="sticky top-0 z-[1] mb-2 bg-custom-background-100 text-xl font-semibold capitalize">
|
<h2 className="sticky top-0 z-[1] mb-2 bg-custom-background-100 text-xl font-semibold capitalize px-3 md:p-0">
|
||||||
{replaceUnderscoreIfSnakeCase(key)}
|
{replaceUnderscoreIfSnakeCase(key)}
|
||||||
</h2>
|
</h2>
|
||||||
<PagesListView pageIds={recentProjectPages[key]} />
|
<PagesListView pageIds={recentProjectPages[key]} />
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { ReactElement } from "react";
|
import React, { ReactElement, useEffect } from "react";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import useSWR from "swr";
|
import useSWR from "swr";
|
||||||
import { observer } from "mobx-react-lite";
|
import { observer } from "mobx-react-lite";
|
||||||
@ -12,7 +12,7 @@ import { Loader } from "@plane/ui";
|
|||||||
// types
|
// types
|
||||||
import { NextPageWithLayout } from "lib/types";
|
import { NextPageWithLayout } from "lib/types";
|
||||||
// fetch-keys
|
// fetch-keys
|
||||||
import { useIssueDetail } from "hooks/store";
|
import { useApplication, useIssueDetail } from "hooks/store";
|
||||||
|
|
||||||
const IssueDetailsPage: NextPageWithLayout = observer(() => {
|
const IssueDetailsPage: NextPageWithLayout = observer(() => {
|
||||||
// router
|
// router
|
||||||
@ -23,6 +23,7 @@ const IssueDetailsPage: NextPageWithLayout = observer(() => {
|
|||||||
fetchIssue,
|
fetchIssue,
|
||||||
issue: { getIssueById },
|
issue: { getIssueById },
|
||||||
} = useIssueDetail();
|
} = useIssueDetail();
|
||||||
|
const { theme: themeStore } = useApplication();
|
||||||
|
|
||||||
const { isLoading } = useSWR(
|
const { isLoading } = useSWR(
|
||||||
workspaceSlug && projectId && issueId ? `ISSUE_DETAIL_${workspaceSlug}_${projectId}_${issueId}` : null,
|
workspaceSlug && projectId && issueId ? `ISSUE_DETAIL_${workspaceSlug}_${projectId}_${issueId}` : null,
|
||||||
@ -34,6 +35,21 @@ const IssueDetailsPage: NextPageWithLayout = observer(() => {
|
|||||||
const issue = getIssueById(issueId?.toString() || "") || undefined;
|
const issue = getIssueById(issueId?.toString() || "") || undefined;
|
||||||
const issueLoader = !issue || isLoading ? true : false;
|
const issueLoader = !issue || isLoading ? true : false;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleToggleIssueDetailSidebar = () => {
|
||||||
|
if (window && window.innerWidth < 768) {
|
||||||
|
themeStore.toggleIssueDetailSidebar(true);
|
||||||
|
}
|
||||||
|
if (window && themeStore.issueDetailSidebarCollapsed && window.innerWidth >= 768) {
|
||||||
|
themeStore.toggleIssueDetailSidebar(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener("resize", handleToggleIssueDetailSidebar);
|
||||||
|
handleToggleIssueDetailSidebar();
|
||||||
|
return () => window.removeEventListener("resize", handleToggleIssueDetailSidebar);
|
||||||
|
}, [themeStore]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{issueLoader ? (
|
{issueLoader ? (
|
||||||
|
@ -103,6 +103,25 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||||||
|
|
||||||
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
const isEditingAllowed = !!currentProjectRole && currentProjectRole >= EUserWorkspaceRoles.MEMBER;
|
||||||
|
|
||||||
|
const mobileTabList = (
|
||||||
|
<Tab.List as="div" className="flex items-center justify-between border-b border-custom-border-200 px-3 pt-3 mb-4">
|
||||||
|
<div className="flex flex-wrap items-center gap-4">
|
||||||
|
{PAGE_TABS_LIST.map((tab) => (
|
||||||
|
<Tab
|
||||||
|
key={tab.key}
|
||||||
|
className={({ selected }) =>
|
||||||
|
`text-sm outline-none pb-3 ${
|
||||||
|
selected ? "border-custom-primary-100 text-custom-primary-100 border-b" : ""
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{tab.title}
|
||||||
|
</Tab>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Tab.List>
|
||||||
|
);
|
||||||
|
|
||||||
if (loader || archivedPageLoader)
|
if (loader || archivedPageLoader)
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center h-full w-full">
|
<div className="flex items-center justify-center h-full w-full">
|
||||||
@ -121,8 +140,8 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||||||
projectId={projectId.toString()}
|
projectId={projectId.toString()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="flex h-full flex-col space-y-5 overflow-hidden p-6">
|
<div className="flex h-full flex-col md:space-y-5 overflow-hidden md:p-6">
|
||||||
<div className="flex justify-between gap-4">
|
<div className="justify-between gap-4 hidden md:flex">
|
||||||
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
<h3 className="text-2xl font-semibold text-custom-text-100">Pages</h3>
|
||||||
</div>
|
</div>
|
||||||
<Tab.Group
|
<Tab.Group
|
||||||
@ -147,7 +166,8 @@ const ProjectPagesPage: NextPageWithLayout = observer(() => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Tab.List as="div" className="mb-6 flex items-center justify-between">
|
<div className="md:hidden">{mobileTabList}</div>
|
||||||
|
<Tab.List as="div" className="mb-6 items-center justify-between hidden md:flex">
|
||||||
<div className="flex flex-wrap items-center gap-4">
|
<div className="flex flex-wrap items-center gap-4">
|
||||||
{PAGE_TABS_LIST.map((tab) => (
|
{PAGE_TABS_LIST.map((tab) => (
|
||||||
<Tab
|
<Tab
|
||||||
|
@ -9,11 +9,13 @@ export interface IThemeStore {
|
|||||||
sidebarCollapsed: boolean | undefined;
|
sidebarCollapsed: boolean | undefined;
|
||||||
profileSidebarCollapsed: boolean | undefined;
|
profileSidebarCollapsed: boolean | undefined;
|
||||||
workspaceAnalyticsSidebarCollapsed: boolean | undefined;
|
workspaceAnalyticsSidebarCollapsed: boolean | undefined;
|
||||||
|
issueDetailSidebarCollapsed: boolean | undefined;
|
||||||
// actions
|
// actions
|
||||||
toggleSidebar: (collapsed?: boolean) => void;
|
toggleSidebar: (collapsed?: boolean) => void;
|
||||||
setTheme: (theme: any) => void;
|
setTheme: (theme: any) => void;
|
||||||
toggleProfileSidebar: (collapsed?: boolean) => void;
|
toggleProfileSidebar: (collapsed?: boolean) => void;
|
||||||
toggleWorkspaceAnalyticsSidebar: (collapsed?: boolean) => void;
|
toggleWorkspaceAnalyticsSidebar: (collapsed?: boolean) => void;
|
||||||
|
toggleIssueDetailSidebar: (collapsed?: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ThemeStore implements IThemeStore {
|
export class ThemeStore implements IThemeStore {
|
||||||
@ -22,6 +24,7 @@ export class ThemeStore implements IThemeStore {
|
|||||||
theme: string | null = null;
|
theme: string | null = null;
|
||||||
profileSidebarCollapsed: boolean | undefined = undefined;
|
profileSidebarCollapsed: boolean | undefined = undefined;
|
||||||
workspaceAnalyticsSidebarCollapsed: boolean | undefined = undefined;
|
workspaceAnalyticsSidebarCollapsed: boolean | undefined = undefined;
|
||||||
|
issueDetailSidebarCollapsed: boolean | undefined = undefined;
|
||||||
// root store
|
// root store
|
||||||
rootStore;
|
rootStore;
|
||||||
|
|
||||||
@ -32,11 +35,13 @@ export class ThemeStore implements IThemeStore {
|
|||||||
theme: observable.ref,
|
theme: observable.ref,
|
||||||
profileSidebarCollapsed: observable.ref,
|
profileSidebarCollapsed: observable.ref,
|
||||||
workspaceAnalyticsSidebarCollapsed: observable.ref,
|
workspaceAnalyticsSidebarCollapsed: observable.ref,
|
||||||
|
issueDetailSidebarCollapsed: observable.ref,
|
||||||
// action
|
// action
|
||||||
toggleSidebar: action,
|
toggleSidebar: action,
|
||||||
setTheme: action,
|
setTheme: action,
|
||||||
toggleProfileSidebar: action,
|
toggleProfileSidebar: action,
|
||||||
toggleWorkspaceAnalyticsSidebar: action
|
toggleWorkspaceAnalyticsSidebar: action,
|
||||||
|
toggleIssueDetailSidebar: action,
|
||||||
// computed
|
// computed
|
||||||
});
|
});
|
||||||
// root store
|
// root store
|
||||||
@ -82,6 +87,15 @@ export class ThemeStore implements IThemeStore {
|
|||||||
localStorage.setItem("workspace_analytics_sidebar_collapsed", this.workspaceAnalyticsSidebarCollapsed.toString());
|
localStorage.setItem("workspace_analytics_sidebar_collapsed", this.workspaceAnalyticsSidebarCollapsed.toString());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
toggleIssueDetailSidebar = (collapsed?: boolean) => {
|
||||||
|
if(collapsed === undefined) {
|
||||||
|
this.issueDetailSidebarCollapsed = !this.issueDetailSidebarCollapsed;
|
||||||
|
} else {
|
||||||
|
this.issueDetailSidebarCollapsed = collapsed;
|
||||||
|
}
|
||||||
|
localStorage.setItem("issue_detail_sidebar_collapsed", this.issueDetailSidebarCollapsed.toString());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the user theme and applies it to the platform
|
* Sets the user theme and applies it to the platform
|
||||||
* @param _theme
|
* @param _theme
|
||||||
|
Loading…
Reference in New Issue
Block a user