Skip to content

Commit

Permalink
feat: implement memo detail sidebar
Browse files Browse the repository at this point in the history
  • Loading branch information
boojack committed Jul 1, 2024
1 parent 05c6edf commit 291b815
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 62 deletions.
2 changes: 1 addition & 1 deletion web/src/components/ExploreSidebar/ExploreSidebarDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ExploreSidebarDrawer = () => {
<Icon.Search className="w-5 h-auto dark:text-gray-400" />
</IconButton>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-5 bg-zinc-100 dark:bg-zinc-900">
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<ExploreSidebar className="py-4" />
</div>
</Drawer>
Expand Down
2 changes: 1 addition & 1 deletion web/src/components/HomeSidebar/HomeSidebarDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const HomeSidebarDrawer = () => {
<Icon.Search className="w-5 h-auto dark:text-gray-400" />
</IconButton>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-5 bg-zinc-100 dark:bg-zinc-900">
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<HomeSidebar className="py-4" />
</div>
</Drawer>
Expand Down
48 changes: 48 additions & 0 deletions web/src/components/MemoDetailSidebar/MemoDetailSidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import clsx from "clsx";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { useTranslate } from "@/utils/i18n";
import Icon from "../Icon";

interface Props {
memo: Memo;
className?: string;
}

const MemoDetailSidebar = ({ memo, className }: Props) => {
const t = useTranslate();

if (!memo.property) {
return;
}

return (
<aside
className={clsx(
"relative w-full h-auto max-h-screen overflow-auto hide-scrollbar flex flex-col justify-start items-start",
className,
)}
>
<div className="flex flex-col justify-start items-start w-full mt-1 px-1 h-auto shrink-0 flex-nowrap hide-scrollbar">
<div className="flex flex-row justify-start items-center w-full gap-1 mb-1 text-sm leading-6 text-gray-400 select-none">
<span>{t("common.tags")}</span>
{memo.property.tags.length > 0 && <span className="shrink-0">({memo.property.tags.length})</span>}
</div>
<div className="w-full flex flex-row justify-start items-center relative flex-wrap gap-x-2 gap-y-1">
{memo.property.tags.map((tag) => (
<div
key={tag}
className="shrink-0 w-auto max-w-full text-sm rounded-md leading-6 flex flex-row justify-start items-center select-none hover:opacity-80 text-gray-600 dark:text-gray-400 dark:border-zinc-800"
>
<Icon.Hash className="group-hover:hidden w-4 h-auto shrink-0 opacity-40" />
<div className={clsx("inline-flex flex-nowrap ml-0.5 gap-0.5 cursor-pointer max-w-[calc(100%-16px)]")}>
<span className="truncate dark:opacity-80">{tag}</span>
</div>
</div>
))}
</div>
</div>
</aside>
);
};

export default MemoDetailSidebar;
41 changes: 41 additions & 0 deletions web/src/components/MemoDetailSidebar/MemoDetailSidebarDrawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Drawer, IconButton } from "@mui/joy";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { Memo } from "@/types/proto/api/v1/memo_service";
import Icon from "../Icon";
import MemoDetailSidebar from "./MemoDetailSidebar";

interface Props {
memo: Memo;
}

const MemoDetailSidebarDrawer = ({ memo }: Props) => {
const location = useLocation();
const [open, setOpen] = useState(false);

useEffect(() => {
setOpen(false);
}, [location.pathname]);

const toggleDrawer = (inOpen: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => {
if (event.type === "keydown" && ((event as React.KeyboardEvent).key === "Tab" || (event as React.KeyboardEvent).key === "Shift")) {
return;
}
setOpen(inOpen);
};

return (
<>
<IconButton onClick={toggleDrawer(true)}>
<Icon.GanttChart className="w-5 h-auto dark:text-gray-400" />
</IconButton>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<MemoDetailSidebar className="py-4" memo={memo} />
</div>
</Drawer>
</>
);
};

export default MemoDetailSidebarDrawer;
4 changes: 4 additions & 0 deletions web/src/components/MemoDetailSidebar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import MemoDetailSidebar from "./MemoDetailSidebar";
import MemoDetailSidebarDrawer from "./MemoDetailSidebarDrawer";

export { MemoDetailSidebar, MemoDetailSidebarDrawer };
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const TimelineSidebarDrawer = () => {
<Icon.Search className="w-5 h-auto dark:text-gray-400" />
</IconButton>
<Drawer anchor="right" size="sm" open={open} onClose={toggleDrawer(false)}>
<div className="w-full h-full px-5 bg-zinc-100 dark:bg-zinc-900">
<div className="w-full h-full px-4 bg-zinc-100 dark:bg-zinc-900">
<TimelineSidebar className="py-4" />
</div>
</Drawer>
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/UserStatisticsView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ const UserStatisticsView = () => {
};

return (
<div className="w-full border mt-2 py-2 px-3 rounded-lg space-y-0.5 text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800">
<div className="group w-full border mt-2 py-2 px-3 rounded-lg space-y-0.5 text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800">
<div className="w-full mb-1 flex flex-row justify-between items-center">
<p className="text-sm font-medium leading-6 dark:text-gray-500">{t("common.statistics")}</p>
<div className="">
<div className="group-hover:block hidden">
<Tooltip title={"Refresh"} placement="top">
<Icon.RefreshCcw
className="text-gray-400 w-4 h-auto cursor-pointer opacity-60 hover:opacity-100"
Expand Down
129 changes: 72 additions & 57 deletions web/src/pages/MemoDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import { Button } from "@mui/joy";
import clsx from "clsx";
import { ClientError } from "nice-grpc-web";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import { Link, useParams } from "react-router-dom";
import Icon from "@/components/Icon";
import { MemoDetailSidebar, MemoDetailSidebarDrawer } from "@/components/MemoDetailSidebar";
import showMemoEditorDialog from "@/components/MemoEditor/MemoEditorDialog";
import MemoView from "@/components/MemoView";
import MobileHeader from "@/components/MobileHeader";
import useCurrentUser from "@/hooks/useCurrentUser";
import useNavigateTo from "@/hooks/useNavigateTo";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useMemoStore } from "@/store/v1";
import { MemoRelation_Type } from "@/types/proto/api/v1/memo_relation_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { useTranslate } from "@/utils/i18n";

const MemoDetail = () => {
const t = useTranslate();
const { md } = useResponsiveWidth();
const params = useParams();
const navigateTo = useNavigateTo();
const currentUser = useCurrentUser();
Expand Down Expand Up @@ -77,66 +81,77 @@ const MemoDetail = () => {

return (
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
<MobileHeader />
<div className="w-full px-4 sm:px-6">
{parentMemo && (
<div className="w-auto inline-block mb-2">
<Link
className="px-3 py-1 border rounded-lg max-w-xs w-auto text-sm flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-400 dark:border-gray-500 hover:shadow hover:opacity-80"
to={`/m/${parentMemo.uid}`}
unstable_viewTransition
>
<Icon.ArrowUpLeftFromCircle className="w-4 h-auto shrink-0 opacity-60 mr-2" />
<span className="truncate">{parentMemo.content}</span>
</Link>
</div>
)}
<MemoView
key={`${memo.name}-${memo.displayTime}`}
className="shadow hover:shadow-xl transition-all"
memo={memo}
compact={false}
showCreator
showVisibility
showPinned
/>
<div className="pt-8 pb-16 w-full">
<h2 id="comments" className="sr-only">
{t("memo.comment.self")}
</h2>
<div className="relative mx-auto flex-grow w-full min-h-full flex flex-col justify-start items-start gap-y-1">
{comments.length === 0 ? (
currentUser && (
<div className="w-full flex flex-row justify-center items-center py-6">
<Button
variant="plain"
color="neutral"
endDecorator={<Icon.MessageCircle className="w-5 h-auto text-gray-500" />}
onClick={handleShowCommentEditor}
>
<span className="font-normal text-gray-500">{t("memo.comment.write-a-comment")}</span>
</Button>
</div>
)
) : (
<>
<div className="w-full flex flex-row justify-between items-center px-3 mb-2">
<div className="flex flex-row justify-start items-center">
<Icon.MessageCircle className="w-5 h-auto text-gray-400 mr-1" />
<span className="text-gray-400 text-sm">{t("memo.comment.self")}</span>
<span className="text-gray-400 text-sm ml-1">({comments.length})</span>
{!md && (
<MobileHeader>
<MemoDetailSidebarDrawer memo={memo} />
</MobileHeader>
)}
<div className={clsx("w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4")}>
<div className={clsx(md ? "w-[calc(100%-15rem)]" : "w-full")}>
{parentMemo && (
<div className="w-auto inline-block mb-2">
<Link
className="px-3 py-1 border rounded-lg max-w-xs w-auto text-sm flex flex-row justify-start items-center flex-nowrap text-gray-600 dark:text-gray-400 dark:border-gray-500 hover:shadow hover:opacity-80"
to={`/m/${parentMemo.uid}`}
unstable_viewTransition
>
<Icon.ArrowUpLeftFromCircle className="w-4 h-auto shrink-0 opacity-60 mr-2" />
<span className="truncate">{parentMemo.content}</span>
</Link>
</div>
)}
<MemoView
key={`${memo.name}-${memo.displayTime}`}
className="shadow hover:shadow-md transition-all"
memo={memo}
compact={false}
showCreator
showVisibility
showPinned
/>
<div className="pt-8 pb-16 w-full">
<h2 id="comments" className="sr-only">
{t("memo.comment.self")}
</h2>
<div className="relative mx-auto flex-grow w-full min-h-full flex flex-col justify-start items-start gap-y-1">
{comments.length === 0 ? (
currentUser && (
<div className="w-full flex flex-row justify-center items-center py-6">
<Button
variant="plain"
color="neutral"
endDecorator={<Icon.MessageCircle className="w-5 h-auto text-gray-500" />}
onClick={handleShowCommentEditor}
>
<span className="font-normal text-gray-500">{t("memo.comment.write-a-comment")}</span>
</Button>
</div>
)
) : (
<>
<div className="w-full flex flex-row justify-between items-center px-3 mb-2">
<div className="flex flex-row justify-start items-center">
<Icon.MessageCircle className="w-5 h-auto text-gray-400 mr-1" />
<span className="text-gray-400 text-sm">{t("memo.comment.self")}</span>
<span className="text-gray-400 text-sm ml-1">({comments.length})</span>
</div>
<Button variant="plain" color="neutral" onClick={handleShowCommentEditor}>
<span className="font-normal text-gray-500">{t("memo.comment.write-a-comment")}</span>
</Button>
</div>
<Button variant="plain" color="neutral" onClick={handleShowCommentEditor}>
<span className="font-normal text-gray-500">{t("memo.comment.write-a-comment")}</span>
</Button>
</div>
{comments.map((comment) => (
<MemoView key={`${comment.name}-${comment.displayTime}`} memo={comment} showCreator compact />
))}
</>
)}
{comments.map((comment) => (
<MemoView key={`${comment.name}-${comment.displayTime}`} memo={comment} showCreator compact />
))}
</>
)}
</div>
</div>
</div>
{md && (
<div className="sticky top-0 left-0 shrink-0 -mt-6 w-56 h-full">
<MemoDetailSidebar className="py-6" memo={memo} />
</div>
)}
</div>
</section>
);
Expand Down

0 comments on commit 291b815

Please sign in to comment.