Commit be5e24c0 authored by johnnyjoy's avatar johnnyjoy

refactor: renovate list memos endpoint

parent 14c72fa7
...@@ -15,3 +15,9 @@ message PageToken { ...@@ -15,3 +15,9 @@ message PageToken {
int32 limit = 1; int32 limit = 1;
int32 offset = 2; int32 offset = 2;
} }
enum Direction {
DIRECTION_UNSPECIFIED = 0;
ASC = 1;
DESC = 2;
}
...@@ -26,7 +26,10 @@ service MemoService { ...@@ -26,7 +26,10 @@ service MemoService {
} }
// ListMemos lists memos with pagination and filter. // ListMemos lists memos with pagination and filter.
rpc ListMemos(ListMemosRequest) returns (ListMemosResponse) { rpc ListMemos(ListMemosRequest) returns (ListMemosResponse) {
option (google.api.http) = {get: "/api/v1/memos"}; option (google.api.http) = {
get: "/api/v1/memos"
additional_bindings: {get: "/api/v1/{parent=users/*}/memos"}
};
} }
// GetMemo gets a memo. // GetMemo gets a memo.
rpc GetMemo(GetMemoRequest) returns (Memo) { rpc GetMemo(GetMemoRequest) returns (Memo) {
...@@ -190,16 +193,36 @@ message CreateMemoRequest { ...@@ -190,16 +193,36 @@ message CreateMemoRequest {
} }
message ListMemosRequest { message ListMemosRequest {
// The parent is the owner of the memos.
// If not specified or `users/-`, it will list all memos.
string parent = 1;
// The maximum number of memos to return. // The maximum number of memos to return.
int32 page_size = 1; int32 page_size = 2;
// A page token, received from a previous `ListMemos` call. // A page token, received from a previous `ListMemos` call.
// Provide this to retrieve the subsequent page. // Provide this to retrieve the subsequent page.
string page_token = 2; string page_token = 3;
// The state of the memos to list.
// Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
State state = 4;
// What field to sort the results by.
// Default to display_time.
string sort = 5;
// The direction to sort the results by.
// Default to DESC.
Direction direction = 6;
// Filter is a CEL expression to filter memos.
// Refer to `Shortcut.filter`.
string filter = 7;
// Filter is used to filter memos returned in the list. // [Deprecated] Old filter contains some specific conditions to filter memos.
// Format: "creator == 'users/{user}' && visibilities == ['PUBLIC', 'PROTECTED']" // Format: "creator == 'users/{user}' && visibilities == ['PUBLIC', 'PROTECTED']"
string filter = 3; string old_filter = 8;
} }
message ListMemosResponse { message ListMemosResponse {
......
...@@ -70,6 +70,55 @@ func (State) EnumDescriptor() ([]byte, []int) { ...@@ -70,6 +70,55 @@ func (State) EnumDescriptor() ([]byte, []int) {
return file_api_v1_common_proto_rawDescGZIP(), []int{0} return file_api_v1_common_proto_rawDescGZIP(), []int{0}
} }
type Direction int32
const (
Direction_DIRECTION_UNSPECIFIED Direction = 0
Direction_ASC Direction = 1
Direction_DESC Direction = 2
)
// Enum value maps for Direction.
var (
Direction_name = map[int32]string{
0: "DIRECTION_UNSPECIFIED",
1: "ASC",
2: "DESC",
}
Direction_value = map[string]int32{
"DIRECTION_UNSPECIFIED": 0,
"ASC": 1,
"DESC": 2,
}
)
func (x Direction) Enum() *Direction {
p := new(Direction)
*p = x
return p
}
func (x Direction) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Direction) Descriptor() protoreflect.EnumDescriptor {
return file_api_v1_common_proto_enumTypes[1].Descriptor()
}
func (Direction) Type() protoreflect.EnumType {
return &file_api_v1_common_proto_enumTypes[1]
}
func (x Direction) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Direction.Descriptor instead.
func (Direction) EnumDescriptor() ([]byte, []int) {
return file_api_v1_common_proto_rawDescGZIP(), []int{1}
}
// Used internally for obfuscating the page token. // Used internally for obfuscating the page token.
type PageToken struct { type PageToken struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
...@@ -135,18 +184,22 @@ var file_api_v1_common_proto_rawDesc = string([]byte{ ...@@ -135,18 +184,22 @@ var file_api_v1_common_proto_rawDesc = string([]byte{
0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45,
0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a,
0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x0a, 0x06, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52,
0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, 0x02, 0x42, 0xa3, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, 0x10, 0x02, 0x2a, 0x39, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65,
0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x43, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x49,
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x4f, 0x4e, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x53, 0x43, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x45, 0x53,
0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x43, 0x10, 0x02, 0x42, 0xa3, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f,
0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d,
0x56, 0x31, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69,
0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa,
0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18,
0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42,
0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73,
0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}) })
var ( var (
...@@ -161,11 +214,12 @@ func file_api_v1_common_proto_rawDescGZIP() []byte { ...@@ -161,11 +214,12 @@ func file_api_v1_common_proto_rawDescGZIP() []byte {
return file_api_v1_common_proto_rawDescData return file_api_v1_common_proto_rawDescData
} }
var file_api_v1_common_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_api_v1_common_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_api_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_api_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_api_v1_common_proto_goTypes = []any{ var file_api_v1_common_proto_goTypes = []any{
(State)(0), // 0: memos.api.v1.State (State)(0), // 0: memos.api.v1.State
(*PageToken)(nil), // 1: memos.api.v1.PageToken (Direction)(0), // 1: memos.api.v1.Direction
(*PageToken)(nil), // 2: memos.api.v1.PageToken
} }
var file_api_v1_common_proto_depIdxs = []int32{ var file_api_v1_common_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type 0, // [0:0] is the sub-list for method output_type
...@@ -185,7 +239,7 @@ func file_api_v1_common_proto_init() { ...@@ -185,7 +239,7 @@ func file_api_v1_common_proto_init() {
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_common_proto_rawDesc), len(file_api_v1_common_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_common_proto_rawDesc), len(file_api_v1_common_proto_rawDesc)),
NumEnums: 1, NumEnums: 2,
NumMessages: 1, NumMessages: 1,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
......
This diff is collapsed.
...@@ -91,6 +91,56 @@ func local_request_MemoService_ListMemos_0(ctx context.Context, marshaler runtim ...@@ -91,6 +91,56 @@ func local_request_MemoService_ListMemos_0(ctx context.Context, marshaler runtim
return msg, metadata, err return msg, metadata, err
} }
var filter_MemoService_ListMemos_1 = &utilities.DoubleArray{Encoding: map[string]int{"parent": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
func request_MemoService_ListMemos_1(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListMemosRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MemoService_ListMemos_1); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListMemos(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_MemoService_ListMemos_1(ctx context.Context, marshaler runtime.Marshaler, server MemoServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListMemosRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["parent"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
}
protoReq.Parent, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_MemoService_ListMemos_1); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListMemos(ctx, &protoReq)
return msg, metadata, err
}
func request_MemoService_GetMemo_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { func request_MemoService_GetMemo_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var ( var (
protoReq GetMemoRequest protoReq GetMemoRequest
...@@ -743,6 +793,26 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux ...@@ -743,6 +793,26 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
} }
forward_MemoService_ListMemos_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_MemoService_ListMemos_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodGet, pattern_MemoService_ListMemos_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.MemoService/ListMemos", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/memos"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_MemoService_ListMemos_1(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_MemoService_ListMemos_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_MemoService_GetMemo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle(http.MethodGet, pattern_MemoService_GetMemo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
...@@ -1097,6 +1167,23 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux ...@@ -1097,6 +1167,23 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
} }
forward_MemoService_ListMemos_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) forward_MemoService_ListMemos_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
}) })
mux.Handle(http.MethodGet, pattern_MemoService_ListMemos_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.MemoService/ListMemos", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/memos"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_MemoService_ListMemos_1(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_MemoService_ListMemos_1(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_MemoService_GetMemo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { mux.Handle(http.MethodGet, pattern_MemoService_GetMemo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context()) ctx, cancel := context.WithCancel(req.Context())
defer cancel() defer cancel()
...@@ -1341,6 +1428,7 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux ...@@ -1341,6 +1428,7 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
var ( var (
pattern_MemoService_CreateMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "memos"}, "")) pattern_MemoService_CreateMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "memos"}, ""))
pattern_MemoService_ListMemos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "memos"}, "")) pattern_MemoService_ListMemos_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "memos"}, ""))
pattern_MemoService_ListMemos_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "memos"}, ""))
pattern_MemoService_GetMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "memos", "name"}, "")) pattern_MemoService_GetMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "memos", "name"}, ""))
pattern_MemoService_UpdateMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "memos", "memo.name"}, "")) pattern_MemoService_UpdateMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "memos", "memo.name"}, ""))
pattern_MemoService_DeleteMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "memos", "name"}, "")) pattern_MemoService_DeleteMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "memos", "name"}, ""))
...@@ -1360,6 +1448,7 @@ var ( ...@@ -1360,6 +1448,7 @@ var (
var ( var (
forward_MemoService_CreateMemo_0 = runtime.ForwardResponseMessage forward_MemoService_CreateMemo_0 = runtime.ForwardResponseMessage
forward_MemoService_ListMemos_0 = runtime.ForwardResponseMessage forward_MemoService_ListMemos_0 = runtime.ForwardResponseMessage
forward_MemoService_ListMemos_1 = runtime.ForwardResponseMessage
forward_MemoService_GetMemo_0 = runtime.ForwardResponseMessage forward_MemoService_GetMemo_0 = runtime.ForwardResponseMessage
forward_MemoService_UpdateMemo_0 = runtime.ForwardResponseMessage forward_MemoService_UpdateMemo_0 = runtime.ForwardResponseMessage
forward_MemoService_DeleteMemo_0 = runtime.ForwardResponseMessage forward_MemoService_DeleteMemo_0 = runtime.ForwardResponseMessage
......
...@@ -304,6 +304,13 @@ paths: ...@@ -304,6 +304,13 @@ paths:
schema: schema:
$ref: '#/definitions/googlerpcStatus' $ref: '#/definitions/googlerpcStatus'
parameters: parameters:
- name: parent
description: |-
The parent is the owner of the memos.
If not specified or `users/-`, it will list all memos.
in: query
required: false
type: string
- name: pageSize - name: pageSize
description: The maximum number of memos to return. description: The maximum number of memos to return.
in: query in: query
...@@ -317,9 +324,47 @@ paths: ...@@ -317,9 +324,47 @@ paths:
in: query in: query
required: false required: false
type: string type: string
- name: state
description: |-
The state of the memos to list.
Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
in: query
required: false
type: string
enum:
- STATE_UNSPECIFIED
- NORMAL
- ARCHIVED
default: STATE_UNSPECIFIED
- name: sort
description: |-
What field to sort the results by.
Default to display_time.
in: query
required: false
type: string
- name: direction
description: |-
The direction to sort the results by.
Default to DESC.
in: query
required: false
type: string
enum:
- DIRECTION_UNSPECIFIED
- ASC
- DESC
default: DIRECTION_UNSPECIFIED
- name: filter - name: filter
description: |- description: |-
Filter is used to filter memos returned in the list. Filter is a CEL expression to filter memos.
Refer to `Shortcut.filter`.
in: query
required: false
type: string
- name: oldFilter
description: |-
[Deprecated] Old filter contains some specific conditions to filter memos.
Format: "creator == 'users/{user}' && visibilities == ['PUBLIC', 'PROTECTED']" Format: "creator == 'users/{user}' && visibilities == ['PUBLIC', 'PROTECTED']"
in: query in: query
required: false required: false
...@@ -1406,6 +1451,88 @@ paths: ...@@ -1406,6 +1451,88 @@ paths:
pattern: users/[^/]+ pattern: users/[^/]+
tags: tags:
- UserService - UserService
/api/v1/{parent}/memos:
get:
summary: ListMemos lists memos with pagination and filter.
operationId: MemoService_ListMemos2
responses:
"200":
description: A successful response.
schema:
$ref: '#/definitions/v1ListMemosResponse'
default:
description: An unexpected error response.
schema:
$ref: '#/definitions/googlerpcStatus'
parameters:
- name: parent
description: |-
The parent is the owner of the memos.
If not specified or `users/-`, it will list all memos.
in: path
required: true
type: string
pattern: users/[^/]+
- name: pageSize
description: The maximum number of memos to return.
in: query
required: false
type: integer
format: int32
- name: pageToken
description: |-
A page token, received from a previous `ListMemos` call.
Provide this to retrieve the subsequent page.
in: query
required: false
type: string
- name: state
description: |-
The state of the memos to list.
Default to `NORMAL`. Set to `ARCHIVED` to list archived memos.
in: query
required: false
type: string
enum:
- STATE_UNSPECIFIED
- NORMAL
- ARCHIVED
default: STATE_UNSPECIFIED
- name: sort
description: |-
What field to sort the results by.
Default to display_time.
in: query
required: false
type: string
- name: direction
description: |-
The direction to sort the results by.
Default to DESC.
in: query
required: false
type: string
enum:
- DIRECTION_UNSPECIFIED
- ASC
- DESC
default: DIRECTION_UNSPECIFIED
- name: filter
description: |-
Filter is a CEL expression to filter memos.
Refer to `Shortcut.filter`.
in: query
required: false
type: string
- name: oldFilter
description: |-
[Deprecated] Old filter contains some specific conditions to filter memos.
Format: "creator == 'users/{user}' && visibilities == ['PUBLIC', 'PROTECTED']"
in: query
required: false
type: string
tags:
- MemoService
/api/v1/{parent}/shortcuts: /api/v1/{parent}/shortcuts:
get: get:
summary: ListShortcuts returns a list of shortcuts for a user. summary: ListShortcuts returns a list of shortcuts for a user.
...@@ -2472,6 +2599,13 @@ definitions: ...@@ -2472,6 +2599,13 @@ definitions:
type: string type: string
url: url:
type: string type: string
v1Direction:
type: string
enum:
- DIRECTION_UNSPECIFIED
- ASC
- DESC
default: DIRECTION_UNSPECIFIED
v1EmbeddedContentNode: v1EmbeddedContentNode:
type: object type: object
properties: properties:
......
...@@ -12,6 +12,7 @@ var authenticationAllowlistMethods = map[string]bool{ ...@@ -12,6 +12,7 @@ var authenticationAllowlistMethods = map[string]bool{
"/memos.api.v1.AuthService/SignOut": true, "/memos.api.v1.AuthService/SignOut": true,
"/memos.api.v1.AuthService/SignUp": true, "/memos.api.v1.AuthService/SignUp": true,
"/memos.api.v1.UserService/GetUser": true, "/memos.api.v1.UserService/GetUser": true,
"/memos.api.v1.UserService/GetUserByUsername": true,
"/memos.api.v1.UserService/GetUserAvatarBinary": true, "/memos.api.v1.UserService/GetUserAvatarBinary": true,
"/memos.api.v1.UserService/ListAllUserStats": true, "/memos.api.v1.UserService/ListAllUserStats": true,
"/memos.api.v1.UserService/SearchUsers": true, "/memos.api.v1.UserService/SearchUsers": true,
......
...@@ -99,9 +99,42 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq ...@@ -99,9 +99,42 @@ func (s *APIV1Service) ListMemos(ctx context.Context, request *v1pb.ListMemosReq
// Exclude comments by default. // Exclude comments by default.
ExcludeComments: true, ExcludeComments: true,
} }
if err := s.buildMemoFindWithFilter(ctx, memoFind, request.Filter); err != nil { if err := s.buildMemoFindWithFilter(ctx, memoFind, request.OldFilter); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "failed to build find memos with filter: %v", err) return nil, status.Errorf(codes.InvalidArgument, "failed to build find memos with filter: %v", err)
} }
if request.Parent != "" && request.Parent != "users/-" {
userID, err := ExtractUserIDFromName(request.Parent)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid parent: %v", err)
}
memoFind.CreatorID = &userID
memoFind.OrderByPinned = true
}
if request.Direction == v1pb.Direction_ASC {
memoFind.OrderByTimeAsc = true
}
if request.Filter != "" {
memoFind.Filter = &request.Filter
}
currentUser, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user")
}
if currentUser == nil {
memoFind.VisibilityList = []store.Visibility{store.Public}
} else {
if memoFind.CreatorID == nil || *memoFind.CreatorID != currentUser.ID {
memoFind.VisibilityList = []store.Visibility{store.Public, store.Protected}
}
}
if request.State == v1pb.State_ARCHIVED {
state := store.Archived
memoFind.RowStatus = &state
} else {
state := store.Normal
memoFind.RowStatus = &state
}
var limit, offset int var limit, offset int
if request.PageToken != "" { if request.PageToken != "" {
......
...@@ -9,7 +9,6 @@ import ( ...@@ -9,7 +9,6 @@ import (
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
apiv1 "github.com/usememos/memos/proto/gen/api/v1"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
) )
...@@ -25,21 +24,12 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store. ...@@ -25,21 +24,12 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store.
if len(filterExpr.ContentSearch) > 0 { if len(filterExpr.ContentSearch) > 0 {
find.ContentSearch = filterExpr.ContentSearch find.ContentSearch = filterExpr.ContentSearch
} }
if len(filterExpr.Visibilities) > 0 {
find.VisibilityList = filterExpr.Visibilities
}
if filterExpr.TagSearch != nil { if filterExpr.TagSearch != nil {
if find.PayloadFind == nil { if find.PayloadFind == nil {
find.PayloadFind = &store.FindMemoPayload{} find.PayloadFind = &store.FindMemoPayload{}
} }
find.PayloadFind.TagSearch = filterExpr.TagSearch find.PayloadFind.TagSearch = filterExpr.TagSearch
} }
if filterExpr.OrderByPinned {
find.OrderByPinned = filterExpr.OrderByPinned
}
if filterExpr.OrderByTimeAsc {
find.OrderByTimeAsc = filterExpr.OrderByTimeAsc
}
if filterExpr.DisplayTimeAfter != nil { if filterExpr.DisplayTimeAfter != nil {
workspaceMemoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx) workspaceMemoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx)
if err != nil { if err != nil {
...@@ -62,31 +52,6 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store. ...@@ -62,31 +52,6 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store.
find.CreatedTsBefore = filterExpr.DisplayTimeBefore find.CreatedTsBefore = filterExpr.DisplayTimeBefore
} }
} }
if filterExpr.Creator != nil {
userID, err := ExtractUserIDFromName(*filterExpr.Creator)
if err != nil {
return errors.Wrap(err, "invalid user name")
}
user, err := s.Store.GetUser(ctx, &store.FindUser{
ID: &userID,
})
if err != nil {
return status.Errorf(codes.Internal, "failed to get user")
}
if user == nil {
return status.Errorf(codes.NotFound, "user not found")
}
find.CreatorID = &user.ID
}
if filterExpr.RowStatus != nil {
find.RowStatus = filterExpr.RowStatus
}
if filterExpr.Random {
find.Random = filterExpr.Random
}
if filterExpr.Limit != nil {
find.Limit = filterExpr.Limit
}
if filterExpr.IncludeComments { if filterExpr.IncludeComments {
find.ExcludeComments = false find.ExcludeComments = false
} }
...@@ -104,23 +69,6 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store. ...@@ -104,23 +69,6 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store.
} }
} }
user, err := s.GetCurrentUser(ctx)
if err != nil {
return status.Errorf(codes.Internal, "failed to get current user")
}
// If the user is not authenticated, only public memos are visible.
if user == nil {
if filter == "" {
// If no filter is provided, return an error.
return status.Errorf(codes.InvalidArgument, "filter is required for unauthenticated user")
}
find.VisibilityList = []store.Visibility{store.Public}
} else if find.CreatorID == nil || *find.CreatorID != user.ID {
// If creator is not specified or the creator is not the current user, only public and protected memos are visible.
find.VisibilityList = []store.Visibility{store.Public, store.Protected}
}
workspaceMemoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx) workspaceMemoRelatedSetting, err := s.Store.GetWorkspaceMemoRelatedSetting(ctx)
if err != nil { if err != nil {
return status.Errorf(codes.Internal, "failed to get workspace memo related setting") return status.Errorf(codes.Internal, "failed to get workspace memo related setting")
...@@ -134,16 +82,9 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store. ...@@ -134,16 +82,9 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store.
// MemoFilterCELAttributes are the CEL attributes. // MemoFilterCELAttributes are the CEL attributes.
var MemoFilterCELAttributes = []cel.EnvOption{ var MemoFilterCELAttributes = []cel.EnvOption{
cel.Variable("content_search", cel.ListType(cel.StringType)), cel.Variable("content_search", cel.ListType(cel.StringType)),
cel.Variable("visibilities", cel.ListType(cel.StringType)),
cel.Variable("tag_search", cel.ListType(cel.StringType)), cel.Variable("tag_search", cel.ListType(cel.StringType)),
cel.Variable("order_by_pinned", cel.BoolType),
cel.Variable("order_by_time_asc", cel.BoolType),
cel.Variable("display_time_before", cel.IntType), cel.Variable("display_time_before", cel.IntType),
cel.Variable("display_time_after", cel.IntType), cel.Variable("display_time_after", cel.IntType),
cel.Variable("creator", cel.StringType),
cel.Variable("state", cel.StringType),
cel.Variable("random", cel.BoolType),
cel.Variable("limit", cel.IntType),
cel.Variable("include_comments", cel.BoolType), cel.Variable("include_comments", cel.BoolType),
cel.Variable("has_link", cel.BoolType), cel.Variable("has_link", cel.BoolType),
cel.Variable("has_task_list", cel.BoolType), cel.Variable("has_task_list", cel.BoolType),
...@@ -153,16 +94,9 @@ var MemoFilterCELAttributes = []cel.EnvOption{ ...@@ -153,16 +94,9 @@ var MemoFilterCELAttributes = []cel.EnvOption{
type MemoFilter struct { type MemoFilter struct {
ContentSearch []string ContentSearch []string
Visibilities []store.Visibility
TagSearch []string TagSearch []string
OrderByPinned bool
OrderByTimeAsc bool
DisplayTimeBefore *int64 DisplayTimeBefore *int64
DisplayTimeAfter *int64 DisplayTimeAfter *int64
Creator *string
RowStatus *store.RowStatus
Random bool
Limit *int
IncludeComments bool IncludeComments bool
HasLink bool HasLink bool
HasTaskList bool HasTaskList bool
...@@ -200,13 +134,6 @@ func findMemoField(callExpr *exprv1.Expr_Call, filter *MemoFilter) { ...@@ -200,13 +134,6 @@ func findMemoField(callExpr *exprv1.Expr_Call, filter *MemoFilter) {
contentSearch = append(contentSearch, value) contentSearch = append(contentSearch, value)
} }
filter.ContentSearch = contentSearch filter.ContentSearch = contentSearch
} else if idExpr.Name == "visibilities" {
visibilities := []store.Visibility{}
for _, expr := range callExpr.Args[1].GetListExpr().GetElements() {
value := expr.GetConstExpr().GetStringValue()
visibilities = append(visibilities, store.Visibility(value))
}
filter.Visibilities = visibilities
} else if idExpr.Name == "tag_search" { } else if idExpr.Name == "tag_search" {
tagSearch := []string{} tagSearch := []string{}
for _, expr := range callExpr.Args[1].GetListExpr().GetElements() { for _, expr := range callExpr.Args[1].GetListExpr().GetElements() {
...@@ -214,30 +141,12 @@ func findMemoField(callExpr *exprv1.Expr_Call, filter *MemoFilter) { ...@@ -214,30 +141,12 @@ func findMemoField(callExpr *exprv1.Expr_Call, filter *MemoFilter) {
tagSearch = append(tagSearch, value) tagSearch = append(tagSearch, value)
} }
filter.TagSearch = tagSearch filter.TagSearch = tagSearch
} else if idExpr.Name == "order_by_pinned" {
value := callExpr.Args[1].GetConstExpr().GetBoolValue()
filter.OrderByPinned = value
} else if idExpr.Name == "order_by_time_asc" {
value := callExpr.Args[1].GetConstExpr().GetBoolValue()
filter.OrderByTimeAsc = value
} else if idExpr.Name == "display_time_before" { } else if idExpr.Name == "display_time_before" {
displayTimeBefore := callExpr.Args[1].GetConstExpr().GetInt64Value() displayTimeBefore := callExpr.Args[1].GetConstExpr().GetInt64Value()
filter.DisplayTimeBefore = &displayTimeBefore filter.DisplayTimeBefore = &displayTimeBefore
} else if idExpr.Name == "display_time_after" { } else if idExpr.Name == "display_time_after" {
displayTimeAfter := callExpr.Args[1].GetConstExpr().GetInt64Value() displayTimeAfter := callExpr.Args[1].GetConstExpr().GetInt64Value()
filter.DisplayTimeAfter = &displayTimeAfter filter.DisplayTimeAfter = &displayTimeAfter
} else if idExpr.Name == "creator" {
creator := callExpr.Args[1].GetConstExpr().GetStringValue()
filter.Creator = &creator
} else if idExpr.Name == "state" {
state := convertStateToStore(apiv1.State(apiv1.State_value[callExpr.Args[1].GetConstExpr().GetStringValue()]))
filter.RowStatus = &state
} else if idExpr.Name == "random" {
value := callExpr.Args[1].GetConstExpr().GetBoolValue()
filter.Random = value
} else if idExpr.Name == "limit" {
limit := int(callExpr.Args[1].GetConstExpr().GetInt64Value())
filter.Limit = &limit
} else if idExpr.Name == "include_comments" { } else if idExpr.Name == "include_comments" {
value := callExpr.Args[1].GetConstExpr().GetBoolValue() value := callExpr.Args[1].GetConstExpr().GetBoolValue()
filter.IncludeComments = value filter.IncludeComments = value
......
...@@ -45,13 +45,14 @@ const AddMemoRelationPopover = (props: Props) => { ...@@ -45,13 +45,14 @@ const AddMemoRelationPopover = (props: Props) => {
setIsFetching(true); setIsFetching(true);
try { try {
const filters = [`creator == "${user.name}"`, `state == "NORMAL"`]; const conditions = [];
if (searchText) { if (searchText) {
filters.push(`content_search == [${JSON.stringify(searchText)}]`); conditions.push(`content_search == [${JSON.stringify(searchText)}]`);
} }
const { memos } = await memoServiceClient.listMemos({ const { memos } = await memoServiceClient.listMemos({
parent: user.name,
pageSize: DEFAULT_LIST_MEMOS_PAGE_SIZE, pageSize: DEFAULT_LIST_MEMOS_PAGE_SIZE,
filter: filters.length > 0 ? filters.join(" && ") : undefined, oldFilter: conditions.length > 0 ? conditions.join(" && ") : undefined,
}); });
setFetchedMemos(memos); setFetchedMemos(memos);
} catch (error: any) { } catch (error: any) {
......
...@@ -5,6 +5,7 @@ import PullToRefresh from "react-simple-pull-to-refresh"; ...@@ -5,6 +5,7 @@ import PullToRefresh from "react-simple-pull-to-refresh";
import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts"; import { DEFAULT_LIST_MEMOS_PAGE_SIZE } from "@/helpers/consts";
import useResponsiveWidth from "@/hooks/useResponsiveWidth"; import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useMemoList, useMemoStore } from "@/store/v1"; import { useMemoList, useMemoStore } from "@/store/v1";
import { Direction, State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service"; import { Memo } from "@/types/proto/api/v1/memo_service";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
import Empty from "../Empty"; import Empty from "../Empty";
...@@ -12,11 +13,14 @@ import Empty from "../Empty"; ...@@ -12,11 +13,14 @@ import Empty from "../Empty";
interface Props { interface Props {
renderer: (memo: Memo) => JSX.Element; renderer: (memo: Memo) => JSX.Element;
listSort?: (list: Memo[]) => Memo[]; listSort?: (list: Memo[]) => Memo[];
filter?: string; owner?: string;
state?: State;
direction?: Direction;
oldFilter?: string;
pageSize?: number; pageSize?: number;
} }
interface State { interface LocalState {
isRequesting: boolean; isRequesting: boolean;
nextPageToken: string; nextPageToken: string;
} }
...@@ -26,7 +30,7 @@ const PagedMemoList = (props: Props) => { ...@@ -26,7 +30,7 @@ const PagedMemoList = (props: Props) => {
const { md } = useResponsiveWidth(); const { md } = useResponsiveWidth();
const memoStore = useMemoStore(); const memoStore = useMemoStore();
const memoList = useMemoList(); const memoList = useMemoList();
const [state, setState] = useState<State>({ const [state, setState] = useState<LocalState>({
isRequesting: true, // Initial request isRequesting: true, // Initial request
nextPageToken: "", nextPageToken: "",
}); });
...@@ -35,7 +39,10 @@ const PagedMemoList = (props: Props) => { ...@@ -35,7 +39,10 @@ const PagedMemoList = (props: Props) => {
const fetchMoreMemos = async (nextPageToken: string) => { const fetchMoreMemos = async (nextPageToken: string) => {
setState((state) => ({ ...state, isRequesting: true })); setState((state) => ({ ...state, isRequesting: true }));
const response = await memoStore.fetchMemos({ const response = await memoStore.fetchMemos({
filter: props.filter || "", parent: props.owner || "",
state: props.state || State.NORMAL,
direction: props.direction || Direction.DESC,
oldFilter: props.oldFilter || "",
pageSize: props.pageSize || DEFAULT_LIST_MEMOS_PAGE_SIZE, pageSize: props.pageSize || DEFAULT_LIST_MEMOS_PAGE_SIZE,
pageToken: nextPageToken, pageToken: nextPageToken,
}); });
...@@ -53,7 +60,7 @@ const PagedMemoList = (props: Props) => { ...@@ -53,7 +60,7 @@ const PagedMemoList = (props: Props) => {
useEffect(() => { useEffect(() => {
refreshList(); refreshList();
}, [props.filter, props.pageSize]); }, [props.owner, props.state, props.direction, props.oldFilter, props.pageSize]);
const children = ( const children = (
<div className="flex flex-col justify-start items-start w-full max-w-full"> <div className="flex flex-col justify-start items-start w-full max-w-full">
......
...@@ -8,7 +8,7 @@ import PagedMemoList from "@/components/PagedMemoList"; ...@@ -8,7 +8,7 @@ import PagedMemoList from "@/components/PagedMemoList";
import SearchBar from "@/components/SearchBar"; import SearchBar from "@/components/SearchBar";
import useCurrentUser from "@/hooks/useCurrentUser"; import useCurrentUser from "@/hooks/useCurrentUser";
import { useMemoFilterStore } from "@/store/v1"; import { useMemoFilterStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common"; import { Direction, State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service"; import { Memo } from "@/types/proto/api/v1/memo_service";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
...@@ -18,7 +18,7 @@ const Archived = () => { ...@@ -18,7 +18,7 @@ const Archived = () => {
const memoFilterStore = useMemoFilterStore(); const memoFilterStore = useMemoFilterStore();
const memoListFilter = useMemo(() => { const memoListFilter = useMemo(() => {
const filters = [`creator == "${user.name}"`, `state == "ARCHIVED"`]; const conditions = [];
const contentSearch: string[] = []; const contentSearch: string[] = [];
const tagSearch: string[] = []; const tagSearch: string[] = [];
for (const filter of memoFilterStore.filters) { for (const filter of memoFilterStore.filters) {
...@@ -28,16 +28,13 @@ const Archived = () => { ...@@ -28,16 +28,13 @@ const Archived = () => {
tagSearch.push(`"${filter.value}"`); tagSearch.push(`"${filter.value}"`);
} }
} }
if (memoFilterStore.orderByTimeAsc) {
filters.push(`order_by_time_asc == true`);
}
if (contentSearch.length > 0) { if (contentSearch.length > 0) {
filters.push(`content_search == [${contentSearch.join(", ")}]`); conditions.push(`content_search == [${contentSearch.join(", ")}]`);
} }
if (tagSearch.length > 0) { if (tagSearch.length > 0) {
filters.push(`tag_search == [${tagSearch.join(", ")}]`); conditions.push(`tag_search == [${tagSearch.join(", ")}]`);
} }
return filters.join(" && "); return conditions.join(" && ");
}, [user, memoFilterStore.filters]); }, [user, memoFilterStore.filters]);
return ( return (
...@@ -66,7 +63,10 @@ const Archived = () => { ...@@ -66,7 +63,10 @@ const Archived = () => {
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(), : dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
) )
} }
filter={memoListFilter} owner={user.name}
state={State.ARCHIVED}
direction={memoFilterStore.orderByTimeAsc ? Direction.ASC : Direction.DESC}
oldFilter={memoListFilter}
/> />
</div> </div>
</div> </div>
......
...@@ -8,7 +8,7 @@ import PagedMemoList from "@/components/PagedMemoList"; ...@@ -8,7 +8,7 @@ import PagedMemoList from "@/components/PagedMemoList";
import useCurrentUser from "@/hooks/useCurrentUser"; import useCurrentUser from "@/hooks/useCurrentUser";
import useResponsiveWidth from "@/hooks/useResponsiveWidth"; import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useMemoFilterStore } from "@/store/v1"; import { useMemoFilterStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common"; import { Direction, State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service"; import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils"; import { cn } from "@/utils";
...@@ -18,7 +18,7 @@ const Explore = () => { ...@@ -18,7 +18,7 @@ const Explore = () => {
const memoFilterStore = useMemoFilterStore(); const memoFilterStore = useMemoFilterStore();
const memoListFilter = useMemo(() => { const memoListFilter = useMemo(() => {
const filters = [`state == "NORMAL"`, `visibilities == [${user ? "'PUBLIC', 'PROTECTED'" : "'PUBLIC'"}]`]; const conditions = [];
const contentSearch: string[] = []; const contentSearch: string[] = [];
const tagSearch: string[] = []; const tagSearch: string[] = [];
for (const filter of memoFilterStore.filters) { for (const filter of memoFilterStore.filters) {
...@@ -27,29 +27,26 @@ const Explore = () => { ...@@ -27,29 +27,26 @@ const Explore = () => {
} else if (filter.factor === "tagSearch") { } else if (filter.factor === "tagSearch") {
tagSearch.push(`"${filter.value}"`); tagSearch.push(`"${filter.value}"`);
} else if (filter.factor === "property.hasLink") { } else if (filter.factor === "property.hasLink") {
filters.push(`has_link == true`); conditions.push(`has_link == true`);
} else if (filter.factor === "property.hasTaskList") { } else if (filter.factor === "property.hasTaskList") {
filters.push(`has_task_list == true`); conditions.push(`has_task_list == true`);
} else if (filter.factor === "property.hasCode") { } else if (filter.factor === "property.hasCode") {
filters.push(`has_code == true`); conditions.push(`has_code == true`);
} else if (filter.factor === "displayTime") { } else if (filter.factor === "displayTime") {
const filterDate = new Date(filter.value); const filterDate = new Date(filter.value);
const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000; const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000;
const timestampAfter = filterUtcTimestamp / 1000; const timestampAfter = filterUtcTimestamp / 1000;
filters.push(`display_time_after == ${timestampAfter}`); conditions.push(`display_time_after == ${timestampAfter}`);
filters.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`); conditions.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`);
} }
} }
if (memoFilterStore.orderByTimeAsc) {
filters.push(`order_by_time_asc == true`);
}
if (contentSearch.length > 0) { if (contentSearch.length > 0) {
filters.push(`content_search == [${contentSearch.join(", ")}]`); conditions.push(`content_search == [${contentSearch.join(", ")}]`);
} }
if (tagSearch.length > 0) { if (tagSearch.length > 0) {
filters.push(`tag_search == [${tagSearch.join(", ")}]`); conditions.push(`tag_search == [${tagSearch.join(", ")}]`);
} }
return filters.join(" && "); return conditions.join(" && ");
}, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]); }, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]);
return ( return (
...@@ -74,7 +71,8 @@ const Explore = () => { ...@@ -74,7 +71,8 @@ const Explore = () => {
: dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(), : dayjs(b.displayTime).unix() - dayjs(a.displayTime).unix(),
) )
} }
filter={memoListFilter} direction={memoFilterStore.orderByTimeAsc ? Direction.ASC : Direction.DESC}
oldFilter={memoListFilter}
/> />
</div> </div>
</div> </div>
......
...@@ -9,7 +9,7 @@ import PagedMemoList from "@/components/PagedMemoList"; ...@@ -9,7 +9,7 @@ import PagedMemoList from "@/components/PagedMemoList";
import useCurrentUser from "@/hooks/useCurrentUser"; import useCurrentUser from "@/hooks/useCurrentUser";
import useResponsiveWidth from "@/hooks/useResponsiveWidth"; import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import { useMemoFilterStore } from "@/store/v1"; import { useMemoFilterStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common"; import { Direction, State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service"; import { Memo } from "@/types/proto/api/v1/memo_service";
import { cn } from "@/utils"; import { cn } from "@/utils";
...@@ -19,7 +19,7 @@ const Home = () => { ...@@ -19,7 +19,7 @@ const Home = () => {
const memoFilterStore = useMemoFilterStore(); const memoFilterStore = useMemoFilterStore();
const memoListFilter = useMemo(() => { const memoListFilter = useMemo(() => {
const filters = [`creator == "${user.name}"`, `state == "NORMAL"`, `order_by_pinned == true`]; const conditions = [];
const contentSearch: string[] = []; const contentSearch: string[] = [];
const tagSearch: string[] = []; const tagSearch: string[] = [];
for (const filter of memoFilterStore.filters) { for (const filter of memoFilterStore.filters) {
...@@ -28,29 +28,29 @@ const Home = () => { ...@@ -28,29 +28,29 @@ const Home = () => {
} else if (filter.factor === "tagSearch") { } else if (filter.factor === "tagSearch") {
tagSearch.push(`"${filter.value}"`); tagSearch.push(`"${filter.value}"`);
} else if (filter.factor === "property.hasLink") { } else if (filter.factor === "property.hasLink") {
filters.push(`has_link == true`); conditions.push(`has_link == true`);
} else if (filter.factor === "property.hasTaskList") { } else if (filter.factor === "property.hasTaskList") {
filters.push(`has_task_list == true`); conditions.push(`has_task_list == true`);
} else if (filter.factor === "property.hasCode") { } else if (filter.factor === "property.hasCode") {
filters.push(`has_code == true`); conditions.push(`has_code == true`);
} else if (filter.factor === "displayTime") { } else if (filter.factor === "displayTime") {
const filterDate = new Date(filter.value); const filterDate = new Date(filter.value);
const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000; const filterUtcTimestamp = filterDate.getTime() + filterDate.getTimezoneOffset() * 60 * 1000;
const timestampAfter = filterUtcTimestamp / 1000; const timestampAfter = filterUtcTimestamp / 1000;
filters.push(`display_time_after == ${timestampAfter}`); conditions.push(`display_time_after == ${timestampAfter}`);
filters.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`); conditions.push(`display_time_before == ${timestampAfter + 60 * 60 * 24}`);
} }
} }
if (memoFilterStore.orderByTimeAsc) { if (memoFilterStore.orderByTimeAsc) {
filters.push(`order_by_time_asc == true`); conditions.push(`order_by_time_asc == true`);
} }
if (contentSearch.length > 0) { if (contentSearch.length > 0) {
filters.push(`content_search == [${contentSearch.join(", ")}]`); conditions.push(`content_search == [${contentSearch.join(", ")}]`);
} }
if (tagSearch.length > 0) { if (tagSearch.length > 0) {
filters.push(`tag_search == [${tagSearch.join(", ")}]`); conditions.push(`tag_search == [${tagSearch.join(", ")}]`);
} }
return filters.join(" && "); return conditions.join(" && ");
}, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]); }, [user, memoFilterStore.filters, memoFilterStore.orderByTimeAsc]);
return ( return (
...@@ -77,7 +77,9 @@ const Home = () => { ...@@ -77,7 +77,9 @@ const Home = () => {
) )
.sort((a, b) => Number(b.pinned) - Number(a.pinned)) .sort((a, b) => Number(b.pinned) - Number(a.pinned))
} }
filter={memoListFilter} owner={user.name}
direction={memoFilterStore.orderByTimeAsc ? Direction.ASC : Direction.DESC}
oldFilter={memoListFilter}
/> />
</div> </div>
</div> </div>
......
...@@ -12,7 +12,7 @@ import PagedMemoList from "@/components/PagedMemoList"; ...@@ -12,7 +12,7 @@ import PagedMemoList from "@/components/PagedMemoList";
import UserAvatar from "@/components/UserAvatar"; import UserAvatar from "@/components/UserAvatar";
import useLoading from "@/hooks/useLoading"; import useLoading from "@/hooks/useLoading";
import { useMemoFilterStore, useUserStore } from "@/store/v1"; import { useMemoFilterStore, useUserStore } from "@/store/v1";
import { State } from "@/types/proto/api/v1/common"; import { Direction, State } from "@/types/proto/api/v1/common";
import { Memo } from "@/types/proto/api/v1/memo_service"; import { Memo } from "@/types/proto/api/v1/memo_service";
import { User } from "@/types/proto/api/v1/user_service"; import { User } from "@/types/proto/api/v1/user_service";
import { useTranslate } from "@/utils/i18n"; import { useTranslate } from "@/utils/i18n";
...@@ -48,7 +48,7 @@ const UserProfile = () => { ...@@ -48,7 +48,7 @@ const UserProfile = () => {
return ""; return "";
} }
const filters = [`creator == "${user.name}"`, `state == "NORMAL"`, `order_by_pinned == true`]; const conditions = [];
const contentSearch: string[] = []; const contentSearch: string[] = [];
const tagSearch: string[] = []; const tagSearch: string[] = [];
for (const filter of memoFilterStore.filters) { for (const filter of memoFilterStore.filters) {
...@@ -59,12 +59,12 @@ const UserProfile = () => { ...@@ -59,12 +59,12 @@ const UserProfile = () => {
} }
} }
if (contentSearch.length > 0) { if (contentSearch.length > 0) {
filters.push(`content_search == [${contentSearch.join(", ")}]`); conditions.push(`content_search == [${contentSearch.join(", ")}]`);
} }
if (tagSearch.length > 0) { if (tagSearch.length > 0) {
filters.push(`tag_search == [${tagSearch.join(", ")}]`); conditions.push(`tag_search == [${tagSearch.join(", ")}]`);
} }
return filters.join(" && "); return conditions.join(" && ");
}, [user, memoFilterStore.filters]); }, [user, memoFilterStore.filters]);
const handleCopyProfileLink = () => { const handleCopyProfileLink = () => {
...@@ -115,7 +115,9 @@ const UserProfile = () => { ...@@ -115,7 +115,9 @@ const UserProfile = () => {
) )
.sort((a, b) => Number(b.pinned) - Number(a.pinned)) .sort((a, b) => Number(b.pinned) - Number(a.pinned))
} }
filter={memoListFilter} owner={user.name}
direction={memoFilterStore.orderByTimeAsc ? Direction.ASC : Direction.DESC}
oldFilter={memoListFilter}
/> />
</> </>
) : ( ) : (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment