diff --git a/server/router/api/v1/memo_service.go b/server/router/api/v1/memo_service.go
index 93caf6e10..32a916bd8 100644
--- a/server/router/api/v1/memo_service.go
+++ b/server/router/api/v1/memo_service.go
@@ -108,6 +108,7 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
memoFind.CreatorID = &userID
+ memoFind.OrderByPinned = true
}
if request.State == v1pb.State_ARCHIVED {
state := store.Archived
diff --git a/store/db/mysql/memo.go b/store/db/mysql/memo.go
index 46f3700da..4dd87d35e 100644
--- a/store/db/mysql/memo.go
+++ b/store/db/mysql/memo.go
@@ -138,13 +138,15 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
if find.OrderByTimeAsc {
order = "ASC"
}
- orders := []string{}
+ orderBy := []string{}
+ if find.OrderByPinned {
+ orderBy = append(orderBy, "`pinned` DESC")
+ }
if find.OrderByUpdatedTs {
- orders = append(orders, "`updated_ts` "+order)
+ orderBy = append(orderBy, "`updated_ts` "+order)
} else {
- orders = append(orders, "`created_ts` "+order)
+ orderBy = append(orderBy, "`created_ts` "+order)
}
- orders = append(orders, "`id` "+order)
fields := []string{
"`memo`.`id` AS `id`",
"`memo`.`uid` AS `uid`",
@@ -165,7 +167,7 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
"LEFT JOIN `memo_relation` ON `memo`.`id` = `memo_relation`.`memo_id` AND `memo_relation`.`type` = 'COMMENT'" + " " +
"WHERE " + strings.Join(where, " AND ") + " " +
"HAVING " + strings.Join(having, " AND ") + " " +
- "ORDER BY " + strings.Join(orders, ", ")
+ "ORDER BY " + strings.Join(orderBy, ", ")
if find.Limit != nil {
query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit)
if find.Offset != nil {
diff --git a/store/db/postgres/memo.go b/store/db/postgres/memo.go
index e02429358..4ec66df7f 100644
--- a/store/db/postgres/memo.go
+++ b/store/db/postgres/memo.go
@@ -130,13 +130,15 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
if find.OrderByTimeAsc {
order = "ASC"
}
- orders := []string{}
+ orderBy := []string{}
+ if find.OrderByPinned {
+ orderBy = append(orderBy, "pinned DESC")
+ }
if find.OrderByUpdatedTs {
- orders = append(orders, "updated_ts "+order)
+ orderBy = append(orderBy, "updated_ts "+order)
} else {
- orders = append(orders, "created_ts "+order)
+ orderBy = append(orderBy, "created_ts "+order)
}
- orders = append(orders, "id "+order)
fields := []string{
`memo.id AS id`,
`memo.uid AS uid`,
@@ -157,7 +159,7 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
FROM memo
LEFT JOIN memo_relation ON memo.id = memo_relation.memo_id AND memo_relation.type = 'COMMENT'
WHERE ` + strings.Join(where, " AND ") + `
- ORDER BY ` + strings.Join(orders, ", ")
+ ORDER BY ` + strings.Join(orderBy, ", ")
if find.Limit != nil {
query = fmt.Sprintf("%s LIMIT %d", query, *find.Limit)
if find.Offset != nil {
diff --git a/store/db/sqlite/memo.go b/store/db/sqlite/memo.go
index 5ca4365d8..d6580250a 100644
--- a/store/db/sqlite/memo.go
+++ b/store/db/sqlite/memo.go
@@ -131,12 +131,14 @@ func (d *DB) ListMemos(ctx context.Context, find *store.FindMemo) ([]*store.Memo
order = "ASC"
}
orderBy := []string{}
+ if find.OrderByPinned {
+ orderBy = append(orderBy, "`pinned` DESC")
+ }
if find.OrderByUpdatedTs {
orderBy = append(orderBy, "`updated_ts` "+order)
} else {
orderBy = append(orderBy, "`created_ts` "+order)
}
- orderBy = append(orderBy, "`id` "+order)
fields := []string{
"`memo`.`id` AS `id`",
"`memo`.`uid` AS `uid`",
diff --git a/store/memo.go b/store/memo.go
index 629c73208..2a16d3645 100644
--- a/store/memo.go
+++ b/store/memo.go
@@ -82,6 +82,7 @@ type FindMemo struct {
// Ordering
OrderByUpdatedTs bool
+ OrderByPinned bool
OrderByTimeAsc bool
}
diff --git a/web/src/components/MemoFilters.tsx b/web/src/components/MemoFilters.tsx
index cd1771a61..939807736 100644
--- a/web/src/components/MemoFilters.tsx
+++ b/web/src/components/MemoFilters.tsx
@@ -1,5 +1,5 @@
import { isEqual } from "lodash-es";
-import { CalendarIcon, CheckCircleIcon, CodeIcon, EyeIcon, HashIcon, LinkIcon, PinIcon, SearchIcon, XIcon } from "lucide-react";
+import { CalendarIcon, CheckCircleIcon, CodeIcon, EyeIcon, HashIcon, LinkIcon, BookmarkIcon, SearchIcon, XIcon } from "lucide-react";
import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import { FilterFactor, getMemoFilterKey, MemoFilter, stringifyFilters, useMemoFilterStore } from "@/store/v1";
@@ -68,7 +68,7 @@ const FactorIcon = ({ factor, className }: { factor: FilterFactor; className?: s
visibility: