mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat: add memo display setting menu
This commit is contained in:
@ -68,7 +68,7 @@ const TagsSection = (props: Props) => {
|
|||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Icon.MoreVertical className="w-4 h-auto shrink-0 opacity-60" />
|
<Icon.MoreVertical className="w-4 h-auto shrink-0 opacity-60" />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent align="end" alignOffset={-12}>
|
||||||
<div className="w-auto flex flex-row justify-between items-center gap-2">
|
<div className="w-auto flex flex-row justify-between items-center gap-2">
|
||||||
<span className="text-sm shrink-0">Tree mode</span>
|
<span className="text-sm shrink-0">Tree mode</span>
|
||||||
<Switch size="sm" checked={treeMode} onChange={(event) => setTreeMode(event.target.checked)} />
|
<Switch size="sm" checked={treeMode} onChange={(event) => setTreeMode(event.target.checked)} />
|
||||||
|
43
web/src/components/MemoDisplaySettingMenu.tsx
Normal file
43
web/src/components/MemoDisplaySettingMenu.tsx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { Option, Select } from "@mui/joy";
|
||||||
|
import clsx from "clsx";
|
||||||
|
import { useMemoFilterStore } from "@/store/v1";
|
||||||
|
import Icon from "./Icon";
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from "./ui/Popover";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MemoDisplaySettingMenu = ({ className }: Props) => {
|
||||||
|
const memoFilterStore = useMemoFilterStore();
|
||||||
|
const isApplying = Boolean(memoFilterStore.orderByTimeAsc) !== false;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover>
|
||||||
|
<PopoverTrigger
|
||||||
|
className={clsx(className, isApplying ? "text-teal-600 bg-teal-50 dark:text-teal-500 dark:bg-teal-900 rounded-sm" : "opacity-40")}
|
||||||
|
>
|
||||||
|
<Icon.Settings2 className="w-4 h-auto shrink-0" />
|
||||||
|
</PopoverTrigger>
|
||||||
|
<PopoverContent align="end" alignOffset={-12}>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="w-full flex flex-row justify-between items-center">
|
||||||
|
<span className="text-sm shrink-0 mr-2">Order by</span>
|
||||||
|
<Select value="displayTime">
|
||||||
|
<Option value={"displayTime"}>Display Time</Option>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="w-full flex flex-row justify-between items-center">
|
||||||
|
<span className="text-sm shrink-0 mr-2">Direction</span>
|
||||||
|
<Select value={memoFilterStore.orderByTimeAsc} onChange={(_, value) => memoFilterStore.setOrderByTimeAsc(Boolean(value))}>
|
||||||
|
<Option value={false}>DESC</Option>
|
||||||
|
<Option value={true}>ASC</Option>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</PopoverContent>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MemoDisplaySettingMenu;
|
@ -40,15 +40,6 @@ const MemoFilters = () => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
<div
|
|
||||||
className="flex flex-row items-center gap-1 pl-1.5 pr-1 hover:opacity-80 cursor-pointer"
|
|
||||||
onClick={() => memoFilterStore.setOrderByTimeAsc(!memoFilterStore.orderByTimeAsc)}
|
|
||||||
>
|
|
||||||
<Icon.Clock className="w-4 h-auto text-gray-500 dark:text-gray-400 opacity-60" />
|
|
||||||
<span className="text-gray-500 dark:text-gray-400 text-sm max-w-32 truncate">
|
|
||||||
{memoFilterStore.orderByTimeAsc ? "Asc" : "Desc"}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import { useState } from "react";
|
|||||||
import { useMemoFilterStore } from "@/store/v1";
|
import { useMemoFilterStore } from "@/store/v1";
|
||||||
import { useTranslate } from "@/utils/i18n";
|
import { useTranslate } from "@/utils/i18n";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
|
import MemoDisplaySettingMenu from "./MemoDisplaySettingMenu";
|
||||||
|
|
||||||
const SearchBar = () => {
|
const SearchBar = () => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
@ -28,7 +29,7 @@ const SearchBar = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative w-full h-auto flex flex-row justify-start items-center">
|
<div className="relative w-full h-auto flex flex-row justify-start items-center">
|
||||||
<Icon.Search className="absolute left-3 w-4 h-auto opacity-30" />
|
<Icon.Search className="absolute left-3 w-4 h-auto opacity-40" />
|
||||||
<input
|
<input
|
||||||
className="w-full text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 border dark:border-zinc-800 text-sm leading-7 rounded-lg p-1 pl-8 outline-none"
|
className="w-full text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 border dark:border-zinc-800 text-sm leading-7 rounded-lg p-1 pl-8 outline-none"
|
||||||
placeholder={t("memo.search-placeholder")}
|
placeholder={t("memo.search-placeholder")}
|
||||||
@ -36,6 +37,7 @@ const SearchBar = () => {
|
|||||||
onChange={onTextChange}
|
onChange={onTextChange}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
/>
|
/>
|
||||||
|
<MemoDisplaySettingMenu className="absolute right-3 top-3" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -90,7 +90,7 @@ const UserStatisticsView = () => {
|
|||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Icon.MoreVertical className="w-4 h-auto shrink-0 opacity-60" />
|
<Icon.MoreVertical className="w-4 h-auto shrink-0 opacity-60" />
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent>
|
<PopoverContent align="end" alignOffset={-12}>
|
||||||
<button className="w-auto flex flex-row justify-between items-center gap-2 hover:opacity-80" onClick={rebuildMemoTags}>
|
<button className="w-auto flex flex-row justify-between items-center gap-2 hover:opacity-80" onClick={rebuildMemoTags}>
|
||||||
<Icon.RefreshCcw className="text-gray-400 w-4 h-auto cursor-pointer opacity-60" />
|
<Icon.RefreshCcw className="text-gray-400 w-4 h-auto cursor-pointer opacity-60" />
|
||||||
<span className="text-sm shrink-0 text-gray-500 dark:text-gray-400">Refresh</span>
|
<span className="text-sm shrink-0 text-gray-500 dark:text-gray-400">Refresh</span>
|
||||||
|
@ -27,7 +27,7 @@ const Archived = () => {
|
|||||||
const sortedMemos = memoList.value
|
const sortedMemos = memoList.value
|
||||||
.filter((memo) => memo.rowStatus === RowStatus.ARCHIVED)
|
.filter((memo) => memo.rowStatus === RowStatus.ARCHIVED)
|
||||||
.sort((a, b) =>
|
.sort((a, b) =>
|
||||||
memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0
|
memoFilterStore.orderByTimeAsc
|
||||||
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
||||||
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
||||||
);
|
);
|
||||||
@ -49,7 +49,7 @@ const Archived = () => {
|
|||||||
tagSearch.push(`"${filter.value}"`);
|
tagSearch.push(`"${filter.value}"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0) {
|
if (memoFilterStore.orderByTimeAsc) {
|
||||||
filters.push(`order_by_time_asc == true`);
|
filters.push(`order_by_time_asc == true`);
|
||||||
}
|
}
|
||||||
if (contentSearch.length > 0) {
|
if (contentSearch.length > 0) {
|
||||||
|
@ -24,7 +24,7 @@ const Explore = () => {
|
|||||||
const [isRequesting, setIsRequesting] = useState(true);
|
const [isRequesting, setIsRequesting] = useState(true);
|
||||||
const [nextPageToken, setNextPageToken] = useState<string>("");
|
const [nextPageToken, setNextPageToken] = useState<string>("");
|
||||||
const sortedMemos = memoList.value.sort((a, b) =>
|
const sortedMemos = memoList.value.sort((a, b) =>
|
||||||
memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0
|
memoFilterStore.orderByTimeAsc
|
||||||
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
||||||
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
||||||
);
|
);
|
||||||
@ -46,7 +46,7 @@ const Explore = () => {
|
|||||||
tagSearch.push(`"${filter.value}"`);
|
tagSearch.push(`"${filter.value}"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0) {
|
if (memoFilterStore.orderByTimeAsc) {
|
||||||
filters.push(`order_by_time_asc == true`);
|
filters.push(`order_by_time_asc == true`);
|
||||||
}
|
}
|
||||||
if (contentSearch.length > 0) {
|
if (contentSearch.length > 0) {
|
||||||
|
@ -28,7 +28,7 @@ const Home = () => {
|
|||||||
const sortedMemos = memoList.value
|
const sortedMemos = memoList.value
|
||||||
.filter((memo) => memo.rowStatus === RowStatus.ACTIVE)
|
.filter((memo) => memo.rowStatus === RowStatus.ACTIVE)
|
||||||
.sort((a, b) =>
|
.sort((a, b) =>
|
||||||
memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0
|
memoFilterStore.orderByTimeAsc
|
||||||
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
||||||
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
||||||
)
|
)
|
||||||
@ -61,7 +61,7 @@ const Home = () => {
|
|||||||
filters.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`);
|
filters.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0) {
|
if (memoFilterStore.orderByTimeAsc) {
|
||||||
filters.push(`order_by_time_asc == true`);
|
filters.push(`order_by_time_asc == true`);
|
||||||
}
|
}
|
||||||
if (contentSearch.length > 0) {
|
if (contentSearch.length > 0) {
|
||||||
|
@ -28,11 +28,7 @@ const UserProfile = () => {
|
|||||||
const [isRequesting, setIsRequesting] = useState(true);
|
const [isRequesting, setIsRequesting] = useState(true);
|
||||||
const [nextPageToken, setNextPageToken] = useState<string>("");
|
const [nextPageToken, setNextPageToken] = useState<string>("");
|
||||||
const sortedMemos = memoList.value
|
const sortedMemos = memoList.value
|
||||||
.sort((a, b) =>
|
.sort((a, b) => dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix())
|
||||||
memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0
|
|
||||||
? dayjs(a.displayTime).unix() - dayjs(b.displayTime).unix()
|
|
||||||
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
|
|
||||||
)
|
|
||||||
.sort((a, b) => Number(b.pinned) - Number(a.pinned));
|
.sort((a, b) => Number(b.pinned) - Number(a.pinned));
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -82,9 +78,6 @@ const UserProfile = () => {
|
|||||||
tagSearch.push(`"${filter.value}"`);
|
tagSearch.push(`"${filter.value}"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memoFilterStore.orderByTimeAsc && memoFilterStore.filters.length > 0) {
|
|
||||||
filters.push(`order_by_time_asc == true`);
|
|
||||||
}
|
|
||||||
if (contentSearch.length > 0) {
|
if (contentSearch.length > 0) {
|
||||||
filters.push(`content_search == [${contentSearch.join(", ")}]`);
|
filters.push(`content_search == [${contentSearch.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,11 @@ const theme = extendTheme({
|
|||||||
defaultProps: {
|
defaultProps: {
|
||||||
size: "sm",
|
size: "sm",
|
||||||
},
|
},
|
||||||
|
styleOverrides: {
|
||||||
|
listbox: {
|
||||||
|
zIndex: 9999,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user