Commit 1ab2c894 authored by Steven's avatar Steven

feat(api): implement get memo by uid

parent 34e938a1
This diff is collapsed.
......@@ -37,6 +37,11 @@ service MemoService {
option (google.api.http) = {get: "/api/v1/{name=memos/*}"};
option (google.api.method_signature) = "name";
}
// GetMemoByUid gets a memo by uid
rpc GetMemoByUid(GetMemoByUidRequest) returns (Memo) {
option (google.api.http) = {get: "/api/v1/memos:by-uid/{uid}"};
option (google.api.method_signature) = "uid";
}
// UpdateMemo updates a memo.
rpc UpdateMemo(UpdateMemoRequest) returns (Memo) {
option (google.api.http) = {
......@@ -254,6 +259,11 @@ message GetMemoRequest {
string name = 1;
}
message GetMemoByUidRequest {
// The uid of the memo.
string uid = 1;
}
message UpdateMemoRequest {
Memo memo = 1;
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -181,6 +181,58 @@ func local_request_MemoService_GetMemo_0(ctx context.Context, marshaler runtime.
}
func request_MemoService_GetMemoByUid_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetMemoByUidRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["uid"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "uid")
}
protoReq.Uid, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "uid", err)
}
msg, err := client.GetMemoByUid(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_MemoService_GetMemoByUid_0(ctx context.Context, marshaler runtime.Marshaler, server MemoServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetMemoByUidRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["uid"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "uid")
}
protoReq.Uid, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "uid", err)
}
msg, err := server.GetMemoByUid(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_MemoService_UpdateMemo_0 = &utilities.DoubleArray{Encoding: map[string]int{"memo": 0, "name": 1}, Base: []int{1, 2, 1, 0, 0}, Check: []int{0, 1, 2, 3, 2}}
)
......@@ -1333,6 +1385,31 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("GET", pattern_MemoService_GetMemoByUid_0, 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)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.MemoService/GetMemoByUid", runtime.WithHTTPPathPattern("/api/v1/memos:by-uid/{uid}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_MemoService_GetMemoByUid_0(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_GetMemoByUid_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("PATCH", pattern_MemoService_UpdateMemo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
......@@ -1912,6 +1989,28 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
})
mux.Handle("GET", pattern_MemoService_GetMemoByUid_0, 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)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.MemoService/GetMemoByUid", runtime.WithHTTPPathPattern("/api/v1/memos:by-uid/{uid}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_MemoService_GetMemoByUid_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_MemoService_GetMemoByUid_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("PATCH", pattern_MemoService_UpdateMemo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
......@@ -2320,6 +2419,8 @@ var (
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_GetMemoByUid_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "memos:by-uid", "uid"}, ""))
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"}, ""))
......@@ -2366,6 +2467,8 @@ var (
forward_MemoService_GetMemo_0 = runtime.ForwardResponseMessage
forward_MemoService_GetMemoByUid_0 = runtime.ForwardResponseMessage
forward_MemoService_UpdateMemo_0 = runtime.ForwardResponseMessage
forward_MemoService_DeleteMemo_0 = runtime.ForwardResponseMessage
......
......@@ -24,6 +24,7 @@ const (
MemoService_ListMemos_FullMethodName = "/memos.api.v1.MemoService/ListMemos"
MemoService_SearchMemos_FullMethodName = "/memos.api.v1.MemoService/SearchMemos"
MemoService_GetMemo_FullMethodName = "/memos.api.v1.MemoService/GetMemo"
MemoService_GetMemoByUid_FullMethodName = "/memos.api.v1.MemoService/GetMemoByUid"
MemoService_UpdateMemo_FullMethodName = "/memos.api.v1.MemoService/UpdateMemo"
MemoService_DeleteMemo_FullMethodName = "/memos.api.v1.MemoService/DeleteMemo"
MemoService_ExportMemos_FullMethodName = "/memos.api.v1.MemoService/ExportMemos"
......@@ -56,6 +57,8 @@ type MemoServiceClient interface {
SearchMemos(ctx context.Context, in *SearchMemosRequest, opts ...grpc.CallOption) (*SearchMemosResponse, error)
// GetMemo gets a memo.
GetMemo(ctx context.Context, in *GetMemoRequest, opts ...grpc.CallOption) (*Memo, error)
// GetMemoByUid gets a memo by uid
GetMemoByUid(ctx context.Context, in *GetMemoByUidRequest, opts ...grpc.CallOption) (*Memo, error)
// UpdateMemo updates a memo.
UpdateMemo(ctx context.Context, in *UpdateMemoRequest, opts ...grpc.CallOption) (*Memo, error)
// DeleteMemo deletes a memo.
......@@ -142,6 +145,16 @@ func (c *memoServiceClient) GetMemo(ctx context.Context, in *GetMemoRequest, opt
return out, nil
}
func (c *memoServiceClient) GetMemoByUid(ctx context.Context, in *GetMemoByUidRequest, opts ...grpc.CallOption) (*Memo, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Memo)
err := c.cc.Invoke(ctx, MemoService_GetMemoByUid_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *memoServiceClient) UpdateMemo(ctx context.Context, in *UpdateMemoRequest, opts ...grpc.CallOption) (*Memo, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Memo)
......@@ -334,6 +347,8 @@ type MemoServiceServer interface {
SearchMemos(context.Context, *SearchMemosRequest) (*SearchMemosResponse, error)
// GetMemo gets a memo.
GetMemo(context.Context, *GetMemoRequest) (*Memo, error)
// GetMemoByUid gets a memo by uid
GetMemoByUid(context.Context, *GetMemoByUidRequest) (*Memo, error)
// UpdateMemo updates a memo.
UpdateMemo(context.Context, *UpdateMemoRequest) (*Memo, error)
// DeleteMemo deletes a memo.
......@@ -389,6 +404,9 @@ func (UnimplementedMemoServiceServer) SearchMemos(context.Context, *SearchMemosR
func (UnimplementedMemoServiceServer) GetMemo(context.Context, *GetMemoRequest) (*Memo, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMemo not implemented")
}
func (UnimplementedMemoServiceServer) GetMemoByUid(context.Context, *GetMemoByUidRequest) (*Memo, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMemoByUid not implemented")
}
func (UnimplementedMemoServiceServer) UpdateMemo(context.Context, *UpdateMemoRequest) (*Memo, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateMemo not implemented")
}
......@@ -528,6 +546,24 @@ func _MemoService_GetMemo_Handler(srv interface{}, ctx context.Context, dec func
return interceptor(ctx, in, info, handler)
}
func _MemoService_GetMemoByUid_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetMemoByUidRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MemoServiceServer).GetMemoByUid(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MemoService_GetMemoByUid_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MemoServiceServer).GetMemoByUid(ctx, req.(*GetMemoByUidRequest))
}
return interceptor(ctx, in, info, handler)
}
func _MemoService_UpdateMemo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateMemoRequest)
if err := dec(in); err != nil {
......@@ -875,6 +911,10 @@ var MemoService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetMemo",
Handler: _MemoService_GetMemo_Handler,
},
{
MethodName: "GetMemoByUid",
Handler: _MemoService_GetMemoByUid_Handler,
},
{
MethodName: "UpdateMemo",
Handler: _MemoService_UpdateMemo_Handler,
......
......@@ -205,6 +205,36 @@ func (s *APIV1Service) GetMemo(ctx context.Context, request *v1pb.GetMemoRequest
return memoMessage, nil
}
func (s *APIV1Service) GetMemoByUID(ctx context.Context, request *v1pb.GetMemoByUidRequest) (*v1pb.Memo, error) {
memo, err := s.Store.GetMemo(ctx, &store.FindMemo{
UID: &request.Uid,
})
if err != nil {
return nil, err
}
if memo == nil {
return nil, status.Errorf(codes.NotFound, "memo not found")
}
if memo.Visibility != store.Public {
user, err := s.GetCurrentUser(ctx)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get user")
}
if user == nil {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
if memo.Visibility == store.Private && memo.CreatorID != user.ID {
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
}
}
memoMessage, err := s.convertMemoFromStore(ctx, memo)
if err != nil {
return nil, errors.Wrap(err, "failed to convert memo")
}
return memoMessage, nil
}
func (s *APIV1Service) UpdateMemo(ctx context.Context, request *v1pb.UpdateMemoRequest) (*v1pb.Memo, error) {
id, err := ExtractMemoIDFromName(request.Memo.Name)
if err != nil {
......@@ -968,9 +998,6 @@ func (s *APIV1Service) buildMemoFindWithFilter(ctx context.Context, find *store.
}
find.CreatorID = &user.ID
}
if filter.UID != nil {
find.UID = filter.UID
}
if filter.RowStatus != nil {
find.RowStatus = filter.RowStatus
}
......@@ -1059,7 +1086,6 @@ type SearchMemosFilter struct {
DisplayTimeBefore *int64
DisplayTimeAfter *int64
Creator *string
UID *string
RowStatus *store.RowStatus
Random bool
Limit *int
......@@ -1122,9 +1148,6 @@ func findSearchMemosField(callExpr *expr.Expr_Call, filter *SearchMemosFilter) {
} else if idExpr.Name == "creator" {
creator := callExpr.Args[1].GetConstExpr().GetStringValue()
filter.Creator = &creator
} else if idExpr.Name == "uid" {
uid := callExpr.Args[1].GetConstExpr().GetStringValue()
filter.UID = &uid
} else if idExpr.Name == "row_status" {
rowStatus := store.RowStatus(callExpr.Args[1].GetConstExpr().GetStringValue())
filter.RowStatus = &rowStatus
......
......@@ -13,22 +13,22 @@ interface Props {
params: string;
}
const EmbeddedMemo = ({ resourceId, params: paramsStr }: Props) => {
const EmbeddedMemo = ({ resourceId: uid, params: paramsStr }: Props) => {
const context = useContext(RendererContext);
const loadingState = useLoading();
const memoStore = useMemoStore();
const memo = memoStore.getMemoByUid(resourceId);
const resourceName = `memos/${resourceId}`;
const memo = memoStore.getMemoByUid(uid);
const resourceName = `memos/${uid}`;
useEffect(() => {
memoStore.searchMemos(`uid == "${resourceId}" && include_comments == true`).finally(() => loadingState.setFinish());
}, [resourceId]);
memoStore.fetchMemoByUid(uid).finally(() => loadingState.setFinish());
}, [uid]);
if (loadingState.isLoading) {
return null;
}
if (!memo) {
return <Error message={`Memo not found: ${resourceId}`} />;
return <Error message={`Memo not found: ${uid}`} />;
}
if (memo.name === context.memoName || context.embeddedMemos.has(resourceName)) {
return <Error message={`Nested Rendering Error: ![[${resourceName}]]`} />;
......
......@@ -9,22 +9,22 @@ interface Props {
params: string;
}
const ReferencedMemo = ({ resourceId, params: paramsStr }: Props) => {
const ReferencedMemo = ({ resourceId: uid, params: paramsStr }: Props) => {
const navigateTo = useNavigateTo();
const loadingState = useLoading();
const memoStore = useMemoStore();
const memo = memoStore.getMemoByUid(resourceId);
const memo = memoStore.getMemoByUid(uid);
const params = new URLSearchParams(paramsStr);
useEffect(() => {
memoStore.searchMemos(`uid == "${resourceId}" && include_comments == true`).finally(() => loadingState.setFinish());
}, [resourceId]);
memoStore.fetchMemoByUid(uid).finally(() => loadingState.setFinish());
}, [uid]);
if (loadingState.isLoading) {
return null;
}
if (!memo) {
return <Error message={`Memo not found: ${resourceId}`} />;
return <Error message={`Memo not found: ${uid}`} />;
}
const paramsText = params.has("text") ? params.get("text") : undefined;
......
......@@ -34,7 +34,7 @@ const MemoDetail = () => {
// Prepare memo.
useEffect(() => {
if (uid) {
memoStore.searchMemos(`uid == "${uid}"`).catch((error: ClientError) => {
memoStore.fetchMemoByUid(uid).catch((error: ClientError) => {
toast.error(error.details);
navigateTo("/403");
});
......
......@@ -59,6 +59,15 @@ export const useMemoStore = create(
set({ stateId: uniqueId(), memoMapByName: memoMap });
return memos;
},
fetchMemoByUid: async (uid: string) => {
const memo = await memoServiceClient.getMemoByUid({
uid,
});
const memoMap = get().memoMapByName;
memoMap[memo.name] = memo;
set({ stateId: uniqueId(), memoMapByName: memoMap });
return memo;
},
getMemoByUid: (uid: string) => {
const memoMap = get().memoMapByName;
return Object.values(memoMap).find((memo) => memo.uid === uid);
......
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