- {filters.map((filter: MemoFilter) => (
-
memoFilterStore.removeFilter((f: MemoFilter) => isEqual(f, filter))}
- >
-
- {getFilterDisplayText(filter)}
-
-
- ))}
+
+ {filters.map((filter) => {
+ const config = FILTER_CONFIGS[filter.factor];
+ const Icon = config?.icon;
+
+ return (
+
+ {Icon && }
+ {getFilterDisplayText(filter)}
+
+
+ );
+ })}
);
});
-const FactorIcon = ({ factor, className }: { factor: FilterFactor; className?: string }) => {
- const iconMap = {
- tagSearch:
,
- visibility:
,
- contentSearch:
,
- displayTime:
,
- pinned:
,
- "property.hasLink":
,
- "property.hasTaskList":
,
- "property.hasCode":
,
- };
- return iconMap[factor as keyof typeof iconMap] || <>>;
-};
+MemoFilters.displayName = "MemoFilters";
export default MemoFilters;
diff --git a/web/src/components/PagedMemoList/PagedMemoList.tsx b/web/src/components/PagedMemoList/PagedMemoList.tsx
index fafa9ed38..fd76c6c8b 100644
--- a/web/src/components/PagedMemoList/PagedMemoList.tsx
+++ b/web/src/components/PagedMemoList/PagedMemoList.tsx
@@ -14,6 +14,7 @@ import { useTranslate } from "@/utils/i18n";
import Empty from "../Empty";
import MasonryView, { MemoRenderContext } from "../MasonryView";
import MemoEditor from "../MemoEditor";
+import MemoFilters from "../MemoFilters";
import MemoSkeleton from "../MemoSkeleton";
interface Props {
@@ -153,7 +154,12 @@ const PagedMemoList = observer((props: Props) => {
: undefined}
+ prefixElement={
+ <>
+ {showMemoEditor ?
: undefined}
+
+ >
+ }
listMode={viewStore.state.layout === "LIST"}
/>
diff --git a/web/src/pages/Archived.tsx b/web/src/pages/Archived.tsx
index 986e0e371..884312f52 100644
--- a/web/src/pages/Archived.tsx
+++ b/web/src/pages/Archived.tsx
@@ -4,16 +4,17 @@ import { MemoRenderContext } from "@/components/MasonryView";
import MemoView from "@/components/MemoView";
import PagedMemoList from "@/components/PagedMemoList";
import useCurrentUser from "@/hooks/useCurrentUser";
-import { viewStore } from "@/store";
+import { viewStore, workspaceStore } from "@/store";
import { extractUserIdFromName } from "@/store/common";
import memoFilterStore from "@/store/memoFilter";
import { State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service";
+import { WorkspaceSetting_Key } from "@/types/proto/api/v1/workspace_service";
const Archived = observer(() => {
const user = useCurrentUser();
- // Build filter from active filters - no useMemo needed since component is MobX observer
+ // Build filter from active filters
const buildMemoFilter = () => {
const conditions = [`creator_id == ${extractUserIdFromName(user.name)}`];
for (const filter of memoFilterStore.filters) {
@@ -21,6 +22,20 @@ const Archived = observer(() => {
conditions.push(`content.contains("${filter.value}")`);
} else if (filter.factor === "tagSearch") {
conditions.push(`tag in ["${filter.value}"]`);
+ } else if (filter.factor === "property.hasLink") {
+ conditions.push(`has_link`);
+ } else if (filter.factor === "property.hasTaskList") {
+ conditions.push(`has_task_list`);
+ } else if (filter.factor === "property.hasCode") {
+ conditions.push(`has_code`);
+ } else if (filter.factor === "displayTime") {
+ const displayWithUpdateTime = workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.MEMO_RELATED).memoRelatedSetting
+ ?.displayWithUpdateTime;
+ const factor = displayWithUpdateTime ? "updated_ts" : "created_ts";
+ const filterDate = new Date(filter.value);
+ const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000;
+ const timestampAfter = filterUtcTimestamp / 1000;
+ conditions.push(`${factor} >= ${timestampAfter} && ${factor} < ${timestampAfter + 60 * 60 * 24}`);
}
}
return conditions.length > 0 ? conditions.join(" && ") : undefined;
diff --git a/web/src/pages/Explore.tsx b/web/src/pages/Explore.tsx
index bf551024b..7aeee0974 100644
--- a/web/src/pages/Explore.tsx
+++ b/web/src/pages/Explore.tsx
@@ -5,13 +5,44 @@ import MemoView from "@/components/MemoView";
import MobileHeader from "@/components/MobileHeader";
import PagedMemoList from "@/components/PagedMemoList";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
-import { viewStore } from "@/store";
+import { viewStore, workspaceStore } from "@/store";
+import memoFilterStore from "@/store/memoFilter";
import { State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service";
+import { WorkspaceSetting_Key } from "@/types/proto/api/v1/workspace_service";
const Explore = observer(() => {
const { md } = useResponsiveWidth();
+ // Build filter from active filters
+ const buildMemoFilter = () => {
+ const conditions: string[] = [];
+ for (const filter of memoFilterStore.filters) {
+ if (filter.factor === "contentSearch") {
+ conditions.push(`content.contains("${filter.value}")`);
+ } else if (filter.factor === "tagSearch") {
+ conditions.push(`tag in ["${filter.value}"]`);
+ } else if (filter.factor === "property.hasLink") {
+ conditions.push(`has_link`);
+ } else if (filter.factor === "property.hasTaskList") {
+ conditions.push(`has_task_list`);
+ } else if (filter.factor === "property.hasCode") {
+ conditions.push(`has_code`);
+ } else if (filter.factor === "displayTime") {
+ const displayWithUpdateTime = workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.MEMO_RELATED).memoRelatedSetting
+ ?.displayWithUpdateTime;
+ const factor = displayWithUpdateTime ? "updated_ts" : "created_ts";
+ const filterDate = new Date(filter.value);
+ const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000;
+ const timestampAfter = filterUtcTimestamp / 1000;
+ conditions.push(`${factor} >= ${timestampAfter} && ${factor} < ${timestampAfter + 60 * 60 * 24}`);
+ }
+ }
+ return conditions.length > 0 ? conditions.join(" && ") : undefined;
+ };
+
+ const memoFilter = buildMemoFilter();
+
return (
{!md && }
@@ -30,6 +61,7 @@ const Explore = observer(() => {
)
}
orderBy={viewStore.state.orderByTimeAsc ? "display_time asc" : "display_time desc"}
+ filter={memoFilter}
showCreator
/>
diff --git a/web/src/pages/UserProfile.tsx b/web/src/pages/UserProfile.tsx
index 557b9d18f..6cea26396 100644
--- a/web/src/pages/UserProfile.tsx
+++ b/web/src/pages/UserProfile.tsx
@@ -11,12 +11,13 @@ import PagedMemoList from "@/components/PagedMemoList";
import UserAvatar from "@/components/UserAvatar";
import { Button } from "@/components/ui/button";
import useLoading from "@/hooks/useLoading";
-import { viewStore, userStore } from "@/store";
+import { viewStore, userStore, workspaceStore } from "@/store";
import { extractUserIdFromName } from "@/store/common";
import memoFilterStore from "@/store/memoFilter";
import { State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service";
import { User } from "@/types/proto/api/v1/user_service";
+import { WorkspaceSetting_Key } from "@/types/proto/api/v1/workspace_service";
import { useTranslate } from "@/utils/i18n";
const UserProfile = observer(() => {
@@ -43,7 +44,7 @@ const UserProfile = observer(() => {
});
}, [params.username]);
- // Build filter from active filters - no useMemo needed since component is MobX observer
+ // Build filter from active filters
const buildMemoFilter = () => {
if (!user) {
return undefined;
@@ -55,6 +56,22 @@ const UserProfile = observer(() => {
conditions.push(`content.contains("${filter.value}")`);
} else if (filter.factor === "tagSearch") {
conditions.push(`tag in ["${filter.value}"]`);
+ } else if (filter.factor === "pinned") {
+ conditions.push(`pinned`);
+ } else if (filter.factor === "property.hasLink") {
+ conditions.push(`has_link`);
+ } else if (filter.factor === "property.hasTaskList") {
+ conditions.push(`has_task_list`);
+ } else if (filter.factor === "property.hasCode") {
+ conditions.push(`has_code`);
+ } else if (filter.factor === "displayTime") {
+ const displayWithUpdateTime = workspaceStore.getWorkspaceSettingByKey(WorkspaceSetting_Key.MEMO_RELATED).memoRelatedSetting
+ ?.displayWithUpdateTime;
+ const factor = displayWithUpdateTime ? "updated_ts" : "created_ts";
+ const filterDate = new Date(filter.value);
+ const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000;
+ const timestampAfter = filterUtcTimestamp / 1000;
+ conditions.push(`${factor} >= ${timestampAfter} && ${factor} < ${timestampAfter + 60 * 60 * 24}`);
}
}
return conditions.length > 0 ? conditions.join(" && ") : undefined;