mirror of
				https://github.com/usememos/memos.git
				synced 2025-06-05 22:09:59 +02:00 
			
		
		
		
	feat: implement list memos filter
This commit is contained in:
		| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"github.com/pkg/errors" | 	"github.com/pkg/errors" | ||||||
| 	apiv2pb "github.com/usememos/memos/proto/gen/api/v2" | 	apiv2pb "github.com/usememos/memos/proto/gen/api/v2" | ||||||
| 	"github.com/usememos/memos/store" | 	"github.com/usememos/memos/store" | ||||||
|  | 	v1alpha1 "google.golang.org/genproto/googleapis/api/expr/v1alpha1" | ||||||
| 	"google.golang.org/grpc/codes" | 	"google.golang.org/grpc/codes" | ||||||
| 	"google.golang.org/grpc/status" | 	"google.golang.org/grpc/status" | ||||||
| ) | ) | ||||||
| @@ -26,19 +27,32 @@ func NewMemoService(store *store.Store) *MemoService { | |||||||
|  |  | ||||||
| func (s *MemoService) ListMemos(ctx context.Context, request *apiv2pb.ListMemosRequest) (*apiv2pb.ListMemosResponse, error) { | func (s *MemoService) ListMemos(ctx context.Context, request *apiv2pb.ListMemosRequest) (*apiv2pb.ListMemosResponse, error) { | ||||||
| 	memoFind := &store.FindMemo{} | 	memoFind := &store.FindMemo{} | ||||||
|  | 	if request.Filter != "" { | ||||||
|  | 		filter, err := parseListMemosFilter(request.Filter) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return nil, status.Errorf(codes.InvalidArgument, "invalid filter: %v", err) | ||||||
|  | 		} | ||||||
|  | 		if filter.Visibility != nil { | ||||||
|  | 			memoFind.VisibilityList = []store.Visibility{*filter.Visibility} | ||||||
|  | 		} | ||||||
|  | 		if filter.CreatedTsBefore != nil { | ||||||
|  | 			memoFind.CreatedTsBefore = filter.CreatedTsBefore | ||||||
|  | 		} | ||||||
|  | 		if filter.CreatedTsAfter != nil { | ||||||
|  | 			memoFind.CreatedTsAfter = filter.CreatedTsAfter | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	userIDPtr := ctx.Value(UserIDContextKey) | ||||||
|  | 	// If the user is not authenticated, only public memos are visible. | ||||||
|  | 	if userIDPtr == nil { | ||||||
|  | 		memoFind.VisibilityList = []store.Visibility{store.Public} | ||||||
|  | 	} | ||||||
| 	if request.PageSize != 0 { | 	if request.PageSize != 0 { | ||||||
| 		offset := int(request.Page * request.PageSize) | 		offset := int(request.Page * request.PageSize) | ||||||
| 		limit := int(request.PageSize) | 		limit := int(request.PageSize) | ||||||
| 		memoFind.Offset = &offset | 		memoFind.Offset = &offset | ||||||
| 		memoFind.Limit = &limit | 		memoFind.Limit = &limit | ||||||
| 	} | 	} | ||||||
| 	if request.Filter != "" { |  | ||||||
| 		visibilityString, err := getVisibilityFilter(request.Filter) |  | ||||||
| 		if err != nil { |  | ||||||
| 			return nil, status.Errorf(codes.InvalidArgument, "invalid filter: %v", err) |  | ||||||
| 		} |  | ||||||
| 		memoFind.VisibilityList = []store.Visibility{store.Visibility(visibilityString)} |  | ||||||
| 	} |  | ||||||
| 	memos, err := s.Store.ListMemos(ctx, memoFind) | 	memos, err := s.Store.ListMemos(ctx, memoFind) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @@ -49,9 +63,8 @@ func (s *MemoService) ListMemos(ctx context.Context, request *apiv2pb.ListMemosR | |||||||
| 		memoMessages[i] = convertMemoFromStore(memo) | 		memoMessages[i] = convertMemoFromStore(memo) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// TODO(steven): Add privalige checks. |  | ||||||
| 	response := &apiv2pb.ListMemosResponse{ | 	response := &apiv2pb.ListMemosResponse{ | ||||||
| 		Memos: nil, | 		Memos: memoMessages, | ||||||
| 	} | 	} | ||||||
| 	return response, nil | 	return response, nil | ||||||
| } | } | ||||||
| @@ -83,39 +96,59 @@ func (s *MemoService) GetMemo(ctx context.Context, request *apiv2pb.GetMemoReque | |||||||
| 	return response, nil | 	return response, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // getVisibilityFilter will parse the simple filter such as `visibility = "PRIVATE"` to "PRIVATE" . | // ListMemosFilterCELAttributes are the CEL attributes for ListMemosFilter. | ||||||
| func getVisibilityFilter(filter string) (string, error) { | var ListMemosFilterCELAttributes = []cel.EnvOption{ | ||||||
| 	formatInvalidErr := errors.Errorf("invalid filter %q", filter) | 	cel.Variable("visibility", cel.StringType), | ||||||
| 	e, err := cel.NewEnv(cel.Variable("visibility", cel.StringType)) | 	cel.Variable("created_ts_before", cel.IntType), | ||||||
|  | 	cel.Variable("created_ts_after", cel.IntType), | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type ListMemosFilter struct { | ||||||
|  | 	Visibility      *store.Visibility | ||||||
|  | 	CreatedTsBefore *int64 | ||||||
|  | 	CreatedTsAfter  *int64 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func parseListMemosFilter(expression string) (*ListMemosFilter, error) { | ||||||
|  | 	e, err := cel.NewEnv(ListMemosFilterCELAttributes...) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return "", err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	ast, issues := e.Compile(filter) | 	ast, issues := e.Compile(expression) | ||||||
| 	if issues != nil { | 	if issues != nil { | ||||||
| 		return "", status.Errorf(codes.InvalidArgument, issues.String()) | 		return nil, errors.Errorf("found issue %v", issues) | ||||||
| 	} | 	} | ||||||
| 	expr := ast.Expr() | 	filter := &ListMemosFilter{} | ||||||
| 	if expr == nil { | 	callExpr := ast.Expr().GetCallExpr() | ||||||
| 		return "", formatInvalidErr | 	findField(callExpr, filter) | ||||||
|  | 	return filter, nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func findField(callExpr *v1alpha1.Expr_Call, filter *ListMemosFilter) { | ||||||
|  | 	if len(callExpr.Args) == 2 { | ||||||
|  | 		idExpr := callExpr.Args[0].GetIdentExpr() | ||||||
|  | 		if idExpr != nil { | ||||||
|  | 			if idExpr.Name == "visibility" { | ||||||
|  | 				visibility := store.Visibility(callExpr.Args[1].GetConstExpr().GetStringValue()) | ||||||
|  | 				filter.Visibility = &visibility | ||||||
| 			} | 			} | ||||||
| 	callExpr := expr.GetCallExpr() | 			if idExpr.Name == "created_ts_before" { | ||||||
| 	if callExpr == nil { | 				createdTsBefore := callExpr.Args[1].GetConstExpr().GetInt64Value() | ||||||
| 		return "", formatInvalidErr | 				filter.CreatedTsBefore = &createdTsBefore | ||||||
| 			} | 			} | ||||||
| 	if callExpr.Function != "_==_" { | 			if idExpr.Name == "created_ts_after" { | ||||||
| 		return "", formatInvalidErr | 				createdTsAfter := callExpr.Args[1].GetConstExpr().GetInt64Value() | ||||||
|  | 				filter.CreatedTsAfter = &createdTsAfter | ||||||
| 			} | 			} | ||||||
| 	if len(callExpr.Args) != 2 { | 			return | ||||||
| 		return "", formatInvalidErr |  | ||||||
| 		} | 		} | ||||||
| 	if callExpr.Args[0].GetIdentExpr() == nil || callExpr.Args[0].GetIdentExpr().Name != "visibility" { |  | ||||||
| 		return "", formatInvalidErr |  | ||||||
| 	} | 	} | ||||||
| 	constExpr := callExpr.Args[1].GetConstExpr() | 	for _, arg := range callExpr.Args { | ||||||
| 	if constExpr == nil { | 		callExpr := arg.GetCallExpr() | ||||||
| 		return "", formatInvalidErr | 		if callExpr != nil { | ||||||
|  | 			findField(callExpr, filter) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	return constExpr.GetStringValue(), nil |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func convertMemoFromStore(memo *store.Memo) *apiv2pb.Memo { | func convertMemoFromStore(memo *store.Memo) *apiv2pb.Memo { | ||||||
|   | |||||||
| @@ -48,8 +48,6 @@ message ListMemosRequest { | |||||||
|  |  | ||||||
| message ListMemosResponse { | message ListMemosResponse { | ||||||
|   repeated Memo memos = 1; |   repeated Memo memos = 1; | ||||||
|  |  | ||||||
|   int32 total = 2; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| message GetMemoRequest { | message GetMemoRequest { | ||||||
|   | |||||||
| @@ -143,7 +143,6 @@ | |||||||
| | Field | Type | Label | Description | | | Field | Type | Label | Description | | ||||||
| | ----- | ---- | ----- | ----------- | | | ----- | ---- | ----- | ----------- | | ||||||
| | memos | [Memo](#memos-api-v2-Memo) | repeated |  | | | memos | [Memo](#memos-api-v2-Memo) | repeated |  | | ||||||
| | total | [int32](#int32) |  |  | |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -246,7 +246,6 @@ type ListMemosResponse struct { | |||||||
| 	unknownFields protoimpl.UnknownFields | 	unknownFields protoimpl.UnknownFields | ||||||
|  |  | ||||||
| 	Memos []*Memo `protobuf:"bytes,1,rep,name=memos,proto3" json:"memos,omitempty"` | 	Memos []*Memo `protobuf:"bytes,1,rep,name=memos,proto3" json:"memos,omitempty"` | ||||||
| 	Total int32   `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x *ListMemosResponse) Reset() { | func (x *ListMemosResponse) Reset() { | ||||||
| @@ -288,13 +287,6 @@ func (x *ListMemosResponse) GetMemos() []*Memo { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (x *ListMemosResponse) GetTotal() int32 { |  | ||||||
| 	if x != nil { |  | ||||||
| 		return x.Total |  | ||||||
| 	} |  | ||||||
| 	return 0 |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type GetMemoRequest struct { | type GetMemoRequest struct { | ||||||
| 	state         protoimpl.MessageState | 	state         protoimpl.MessageState | ||||||
| 	sizeCache     protoimpl.SizeCache | 	sizeCache     protoimpl.SizeCache | ||||||
| @@ -422,49 +414,47 @@ var file_api_v2_memo_service_proto_rawDesc = []byte{ | |||||||
| 	0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, | 	0x05, 0x52, 0x04, 0x70, 0x61, 0x67, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, | ||||||
| 	0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, | 	0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, | ||||||
| 	0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, | 	0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, | ||||||
| 	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x53, 0x0a, 0x11, | 	0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x3d, 0x0a, 0x11, | ||||||
| 	0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, | 	0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, | ||||||
| 	0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, | 	0x65, 0x12, 0x28, 0x0a, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, | ||||||
| 	0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, | 	0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, | ||||||
| 	0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, | 	0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x22, 0x20, 0x0a, 0x0e, 0x47, | ||||||
| 	0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, | 	0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, | ||||||
| 	0x6c, 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, | 	0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x39, 0x0a, | ||||||
| 	0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, | 	0x0f, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, | ||||||
| 	0x02, 0x69, 0x64, 0x22, 0x39, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, | 	0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, | ||||||
| 	0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, | 	0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, | ||||||
| 	0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, | 	0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, | ||||||
| 	0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x2a, 0x50, | 	0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, | ||||||
| 	0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, | 	0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, | ||||||
| 	0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, | 	0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, | ||||||
| 	0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, | 	0x0d, 0x0a, 0x09, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, | ||||||
| 	0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, | 	0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, 0x32, 0xdb, 0x01, 0x0a, 0x0b, 0x4d, | ||||||
| 	0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, | 	0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, | ||||||
| 	0x32, 0xdb, 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, | 	0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, | ||||||
| 	0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x1e, 0x2e, | 	0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, | ||||||
| 	0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, | 	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, | ||||||
| 	0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, | 	0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, | ||||||
| 	0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, | 	0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, | ||||||
| 	0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, | 	0x12, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, | ||||||
| 	0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, | 	0x67, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, | ||||||
| 	0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x67, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, | 	0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, | ||||||
| 	0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, | 	0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, | ||||||
| 	0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, | 	0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, | ||||||
| 	0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, | 	0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, | ||||||
| 	0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0xda, | 	0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, | ||||||
| 	0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x61, 0x70, 0x69, | 	0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, | ||||||
| 	0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x42, 0xa8, | 	0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x4d, | ||||||
| 	0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, | 	0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, | ||||||
| 	0x2e, 0x76, 0x32, 0x42, 0x10, 0x4d, 0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, | 	0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, | ||||||
| 	0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, | 	0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, | ||||||
| 	0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, | 	0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, | ||||||
| 	0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, | 	0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, | ||||||
| 	0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, | 	0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, | ||||||
| 	0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, | 	0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, | ||||||
| 	0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, | 	0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, | ||||||
| 	0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, | 	0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, | ||||||
| 	0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, | 	0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, | ||||||
| 	0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, |  | ||||||
| 	0x33, |  | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
|   | |||||||
| @@ -59,6 +59,8 @@ type FindMemo struct { | |||||||
| 	// Standard fields | 	// Standard fields | ||||||
| 	RowStatus       *RowStatus | 	RowStatus       *RowStatus | ||||||
| 	CreatorID       *int32 | 	CreatorID       *int32 | ||||||
|  | 	CreatedTsAfter  *int64 | ||||||
|  | 	CreatedTsBefore *int64 | ||||||
|  |  | ||||||
| 	// Domain specific fields | 	// Domain specific fields | ||||||
| 	Pinned         *bool | 	Pinned         *bool | ||||||
| @@ -131,6 +133,12 @@ func (s *Store) ListMemos(ctx context.Context, find *FindMemo) ([]*Memo, error) | |||||||
| 	if v := find.RowStatus; v != nil { | 	if v := find.RowStatus; v != nil { | ||||||
| 		where, args = append(where, "memo.row_status = ?"), append(args, *v) | 		where, args = append(where, "memo.row_status = ?"), append(args, *v) | ||||||
| 	} | 	} | ||||||
|  | 	if v := find.CreatedTsBefore; v != nil { | ||||||
|  | 		where, args = append(where, "memo.created_ts < ?"), append(args, *v) | ||||||
|  | 	} | ||||||
|  | 	if v := find.CreatedTsAfter; v != nil { | ||||||
|  | 		where, args = append(where, "memo.created_ts > ?"), append(args, *v) | ||||||
|  | 	} | ||||||
| 	if v := find.Pinned; v != nil { | 	if v := find.Pinned; v != nil { | ||||||
| 		where = append(where, "memo_organizer.pinned = 1") | 		where = append(where, "memo_organizer.pinned = 1") | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -136,11 +136,6 @@ export declare class ListMemosResponse extends Message<ListMemosResponse> { | |||||||
|    */ |    */ | ||||||
|   memos: Memo[]; |   memos: Memo[]; | ||||||
|  |  | ||||||
|   /** |  | ||||||
|    * @generated from field: int32 total = 2; |  | ||||||
|    */ |  | ||||||
|   total: number; |  | ||||||
|  |  | ||||||
|   constructor(data?: PartialMessage<ListMemosResponse>); |   constructor(data?: PartialMessage<ListMemosResponse>); | ||||||
|  |  | ||||||
|   static readonly runtime: typeof proto3; |   static readonly runtime: typeof proto3; | ||||||
|   | |||||||
| @@ -55,7 +55,6 @@ export const ListMemosResponse = proto3.makeMessageType( | |||||||
|   "memos.api.v2.ListMemosResponse", |   "memos.api.v2.ListMemosResponse", | ||||||
|   () => [ |   () => [ | ||||||
|     { no: 1, name: "memos", kind: "message", T: Memo, repeated: true }, |     { no: 1, name: "memos", kind: "message", T: Memo, repeated: true }, | ||||||
|     { no: 2, name: "total", kind: "scalar", T: 5 /* ScalarType.INT32 */ }, |  | ||||||
|   ], |   ], | ||||||
| ); | ); | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user