From 9361613f23e81686a104669b7b66685c9ca0eaac Mon Sep 17 00:00:00 2001 From: Steven Date: Thu, 21 Dec 2023 21:24:08 +0800 Subject: [PATCH] chore: update timeline page --- api/v2/memo_service.go | 113 +++ proto/api/v2/memo_relation_service.proto | 17 + proto/api/v2/memo_service.proto | 46 + proto/gen/api/v2/README.md | 142 +++ proto/gen/api/v2/memo_relation_service.pb.go | 232 +++++ proto/gen/api/v2/memo_service.pb.go | 919 +++++++++++++----- proto/gen/api/v2/memo_service.pb.gw.go | 341 +++++++ proto/gen/api/v2/memo_service_grpc.pb.go | 111 +++ .../MemoEditorV1/ActionButton/TagSelector.tsx | 52 + .../MemoEditorV1/Editor/TagSuggestions.tsx | 136 +++ .../components/MemoEditorV1/Editor/index.tsx | 162 +++ .../MemoEditorV1/MemoEditorDialog.tsx | 59 ++ .../MemoEditorV1/RelationListView.tsx | 56 ++ .../MemoEditorV1/ResourceListView.tsx | 42 + web/src/components/MemoEditorV1/index.tsx | 454 +++++++++ web/src/components/MemoRelationListViewV1.tsx | 83 ++ web/src/components/TimelineMemo.tsx | 45 + web/src/components/VisibilityIconV1.tsx | 27 + web/src/pages/Timeline.tsx | 87 +- web/src/store/v1/memo.ts | 30 +- web/src/utils/memo.ts | 27 + 21 files changed, 2878 insertions(+), 303 deletions(-) create mode 100644 proto/api/v2/memo_relation_service.proto create mode 100644 proto/gen/api/v2/memo_relation_service.pb.go create mode 100644 web/src/components/MemoEditorV1/ActionButton/TagSelector.tsx create mode 100644 web/src/components/MemoEditorV1/Editor/TagSuggestions.tsx create mode 100644 web/src/components/MemoEditorV1/Editor/index.tsx create mode 100644 web/src/components/MemoEditorV1/MemoEditorDialog.tsx create mode 100644 web/src/components/MemoEditorV1/RelationListView.tsx create mode 100644 web/src/components/MemoEditorV1/ResourceListView.tsx create mode 100644 web/src/components/MemoEditorV1/index.tsx create mode 100644 web/src/components/MemoRelationListViewV1.tsx create mode 100644 web/src/components/TimelineMemo.tsx create mode 100644 web/src/components/VisibilityIconV1.tsx create mode 100644 web/src/utils/memo.ts diff --git a/api/v2/memo_service.go b/api/v2/memo_service.go index fb47b1602..b203c0967 100644 --- a/api/v2/memo_service.go +++ b/api/v2/memo_service.go @@ -233,6 +233,44 @@ func (s *APIV2Service) DeleteMemo(ctx context.Context, request *apiv2pb.DeleteMe return &apiv2pb.DeleteMemoResponse{}, nil } +func (s *APIV2Service) SetMemoResources(ctx context.Context, request *apiv2pb.SetMemoResourcesRequest) (*apiv2pb.SetMemoResourcesResponse, error) { + resources, err := s.Store.ListResources(ctx, &store.FindResource{MemoID: &request.Id}) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to list resources") + } + + // Delete resources that are not in the request. + for _, resource := range resources { + found := false + for _, requestResource := range request.Resources { + if resource.ID == int32(requestResource.Id) { + found = true + break + } + } + if !found { + if err = s.Store.DeleteResource(ctx, &store.DeleteResource{ + ID: int32(resource.ID), + MemoID: &request.Id, + }); err != nil { + return nil, status.Errorf(codes.Internal, "failed to delete resource") + } + } + } + + // Update resources' memo_id in the request. + for _, resource := range request.Resources { + if _, err := s.Store.UpdateResource(ctx, &store.UpdateResource{ + ID: resource.Id, + MemoID: &request.Id, + }); err != nil { + return nil, status.Errorf(codes.Internal, "failed to update resource") + } + } + + return &apiv2pb.SetMemoResourcesResponse{}, nil +} + func (s *APIV2Service) ListMemoResources(ctx context.Context, request *apiv2pb.ListMemoResourcesRequest) (*apiv2pb.ListMemoResourcesResponse, error) { resources, err := s.Store.ListResources(ctx, &store.FindResource{ MemoID: &request.Id, @@ -250,6 +288,51 @@ func (s *APIV2Service) ListMemoResources(ctx context.Context, request *apiv2pb.L return response, nil } +func (s *APIV2Service) SetMemoRelations(ctx context.Context, request *apiv2pb.SetMemoRelationsRequest) (*apiv2pb.SetMemoRelationsResponse, error) { + if err := s.Store.DeleteMemoRelation(ctx, &store.DeleteMemoRelation{MemoID: &request.Id}); err != nil { + return nil, status.Errorf(codes.Internal, "failed to delete memo relation") + } + + for _, relation := range request.Relations { + if _, err := s.Store.UpsertMemoRelation(ctx, &store.MemoRelation{ + MemoID: request.Id, + RelatedMemoID: relation.RelatedMemoId, + Type: convertMemoRelationTypeToStore(relation.Type), + }); err != nil { + return nil, status.Errorf(codes.Internal, "failed to upsert memo relation") + } + } + + return &apiv2pb.SetMemoRelationsResponse{}, nil +} + +func (s *APIV2Service) ListMemoRelations(ctx context.Context, request *apiv2pb.ListMemoRelationsRequest) (*apiv2pb.ListMemoRelationsResponse, error) { + relationList := []*apiv2pb.MemoRelation{} + tempList, err := s.Store.ListMemoRelations(ctx, &store.FindMemoRelation{ + MemoID: &request.Id, + }) + if err != nil { + return nil, err + } + for _, relation := range tempList { + relationList = append(relationList, convertMemoRelationFromStore(relation)) + } + tempList, err = s.Store.ListMemoRelations(ctx, &store.FindMemoRelation{ + RelatedMemoID: &request.Id, + }) + if err != nil { + return nil, err + } + for _, relation := range tempList { + relationList = append(relationList, convertMemoRelationFromStore(relation)) + } + + response := &apiv2pb.ListMemoRelationsResponse{ + Relations: relationList, + } + return response, nil +} + func (s *APIV2Service) CreateMemoComment(ctx context.Context, request *apiv2pb.CreateMemoCommentRequest) (*apiv2pb.CreateMemoCommentResponse, error) { // Create the comment memo first. createMemoResponse, err := s.CreateMemo(ctx, request.Create) @@ -348,6 +431,36 @@ func (s *APIV2Service) getMemoDisplayWithUpdatedTsSettingValue(ctx context.Conte return memoDisplayWithUpdatedTs, nil } +func convertMemoRelationFromStore(memoRelation *store.MemoRelation) *apiv2pb.MemoRelation { + return &apiv2pb.MemoRelation{ + MemoId: memoRelation.MemoID, + RelatedMemoId: memoRelation.RelatedMemoID, + Type: convertMemoRelationTypeFromStore(memoRelation.Type), + } +} + +func convertMemoRelationTypeFromStore(relationType store.MemoRelationType) apiv2pb.MemoRelation_Type { + switch relationType { + case store.MemoRelationReference: + return apiv2pb.MemoRelation_REFERENCE + case store.MemoRelationComment: + return apiv2pb.MemoRelation_COMMENT + default: + return apiv2pb.MemoRelation_TYPE_UNSPECIFIED + } +} + +func convertMemoRelationTypeToStore(relationType apiv2pb.MemoRelation_Type) store.MemoRelationType { + switch relationType { + case apiv2pb.MemoRelation_REFERENCE: + return store.MemoRelationReference + case apiv2pb.MemoRelation_COMMENT: + return store.MemoRelationComment + default: + return store.MemoRelationReference + } +} + func convertVisibilityFromStore(visibility store.Visibility) apiv2pb.Visibility { switch visibility { case store.Private: diff --git a/proto/api/v2/memo_relation_service.proto b/proto/api/v2/memo_relation_service.proto new file mode 100644 index 000000000..8bd917574 --- /dev/null +++ b/proto/api/v2/memo_relation_service.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package memos.api.v2; + +option go_package = "gen/api/v2"; + +message MemoRelation { + int32 memo_id = 1; + int32 related_memo_id = 2; + + enum Type { + TYPE_UNSPECIFIED = 0; + REFERENCE = 1; + COMMENT = 2; + } + Type type = 3; +} diff --git a/proto/api/v2/memo_service.proto b/proto/api/v2/memo_service.proto index c90a89b08..901ade06a 100644 --- a/proto/api/v2/memo_service.proto +++ b/proto/api/v2/memo_service.proto @@ -4,6 +4,7 @@ package memos.api.v2; import "api/v2/common.proto"; import "api/v2/markdown_service.proto"; +import "api/v2/memo_relation_service.proto"; import "api/v2/resource_service.proto"; import "google/api/annotations.proto"; import "google/api/client.proto"; @@ -42,11 +43,32 @@ service MemoService { option (google.api.method_signature) = "id"; } + rpc SetMemoResources(SetMemoResourcesRequest) returns (SetMemoResourcesResponse) { + option (google.api.http) = { + post: "/api/v2/memos/{id}/resources" + body: "*" + }; + option (google.api.method_signature) = "id"; + } + rpc ListMemoResources(ListMemoResourcesRequest) returns (ListMemoResourcesResponse) { option (google.api.http) = {get: "/api/v2/memos/{id}/resources"}; option (google.api.method_signature) = "id"; } + rpc SetMemoRelations(SetMemoRelationsRequest) returns (SetMemoRelationsResponse) { + option (google.api.http) = { + post: "/api/v2/memos/{id}/relations" + body: "*" + }; + option (google.api.method_signature) = "id"; + } + + rpc ListMemoRelations(ListMemoRelationsRequest) returns (ListMemoRelationsResponse) { + option (google.api.http) = {get: "/api/v2/memos/{id}/relations"}; + option (google.api.method_signature) = "id"; + } + rpc CreateMemoComment(CreateMemoCommentRequest) returns (CreateMemoCommentResponse) { option (google.api.http) = {post: "/api/v2/memos/{id}/comments"}; option (google.api.method_signature) = "id"; @@ -139,6 +161,14 @@ message DeleteMemoRequest { message DeleteMemoResponse {} +message SetMemoResourcesRequest { + int32 id = 1; + + repeated Resource resources = 2; +} + +message SetMemoResourcesResponse {} + message ListMemoResourcesRequest { int32 id = 1; } @@ -147,6 +177,22 @@ message ListMemoResourcesResponse { repeated Resource resources = 1; } +message SetMemoRelationsRequest { + int32 id = 1; + + repeated MemoRelation relations = 2; +} + +message SetMemoRelationsResponse {} + +message ListMemoRelationsRequest { + int32 id = 1; +} + +message ListMemoRelationsResponse { + repeated MemoRelation relations = 1; +} + message CreateMemoCommentRequest { // id is the memo id to create comment for. int32 id = 1; diff --git a/proto/gen/api/v2/README.md b/proto/gen/api/v2/README.md index cad213ed9..68463d9da 100644 --- a/proto/gen/api/v2/README.md +++ b/proto/gen/api/v2/README.md @@ -91,6 +91,11 @@ - [MarkdownService](#memos-api-v2-MarkdownService) +- [api/v2/memo_relation_service.proto](#api_v2_memo_relation_service-proto) + - [MemoRelation](#memos-api-v2-MemoRelation) + + - [MemoRelation.Type](#memos-api-v2-MemoRelation-Type) + - [api/v2/resource_service.proto](#api_v2_resource_service-proto) - [CreateResourceRequest](#memos-api-v2-CreateResourceRequest) - [CreateResourceResponse](#memos-api-v2-CreateResourceResponse) @@ -115,11 +120,17 @@ - [GetMemoResponse](#memos-api-v2-GetMemoResponse) - [ListMemoCommentsRequest](#memos-api-v2-ListMemoCommentsRequest) - [ListMemoCommentsResponse](#memos-api-v2-ListMemoCommentsResponse) + - [ListMemoRelationsRequest](#memos-api-v2-ListMemoRelationsRequest) + - [ListMemoRelationsResponse](#memos-api-v2-ListMemoRelationsResponse) - [ListMemoResourcesRequest](#memos-api-v2-ListMemoResourcesRequest) - [ListMemoResourcesResponse](#memos-api-v2-ListMemoResourcesResponse) - [ListMemosRequest](#memos-api-v2-ListMemosRequest) - [ListMemosResponse](#memos-api-v2-ListMemosResponse) - [Memo](#memos-api-v2-Memo) + - [SetMemoRelationsRequest](#memos-api-v2-SetMemoRelationsRequest) + - [SetMemoRelationsResponse](#memos-api-v2-SetMemoRelationsResponse) + - [SetMemoResourcesRequest](#memos-api-v2-SetMemoResourcesRequest) + - [SetMemoResourcesResponse](#memos-api-v2-SetMemoResourcesResponse) - [UpdateMemoRequest](#memos-api-v2-UpdateMemoRequest) - [UpdateMemoResponse](#memos-api-v2-UpdateMemoResponse) @@ -1317,6 +1328,52 @@ + +

Top

+ +## api/v2/memo_relation_service.proto + + + + + +### MemoRelation + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| memo_id | [int32](#int32) | | | +| related_memo_id | [int32](#int32) | | | +| type | [MemoRelation.Type](#memos-api-v2-MemoRelation-Type) | | | + + + + + + + + + + +### MemoRelation.Type + + +| Name | Number | Description | +| ---- | ------ | ----------- | +| TYPE_UNSPECIFIED | 0 | | +| REFERENCE | 1 | | +| COMMENT | 2 | | + + + + + + + + + +

Top

@@ -1635,6 +1692,36 @@ + + +### ListMemoRelationsRequest + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| id | [int32](#int32) | | | + + + + + + + + +### ListMemoRelationsResponse + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| relations | [MemoRelation](#memos-api-v2-MemoRelation) | repeated | | + + + + + + ### ListMemoResourcesRequest @@ -1721,6 +1808,58 @@ + + +### SetMemoRelationsRequest + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| id | [int32](#int32) | | | +| relations | [MemoRelation](#memos-api-v2-MemoRelation) | repeated | | + + + + + + + + +### SetMemoRelationsResponse + + + + + + + + + +### SetMemoResourcesRequest + + + +| Field | Type | Label | Description | +| ----- | ---- | ----- | ----------- | +| id | [int32](#int32) | | | +| resources | [Resource](#memos-api-v2-Resource) | repeated | | + + + + + + + + +### SetMemoResourcesResponse + + + + + + + ### UpdateMemoRequest @@ -1785,7 +1924,10 @@ | GetMemo | [GetMemoRequest](#memos-api-v2-GetMemoRequest) | [GetMemoResponse](#memos-api-v2-GetMemoResponse) | | | UpdateMemo | [UpdateMemoRequest](#memos-api-v2-UpdateMemoRequest) | [UpdateMemoResponse](#memos-api-v2-UpdateMemoResponse) | | | DeleteMemo | [DeleteMemoRequest](#memos-api-v2-DeleteMemoRequest) | [DeleteMemoResponse](#memos-api-v2-DeleteMemoResponse) | | +| SetMemoResources | [SetMemoResourcesRequest](#memos-api-v2-SetMemoResourcesRequest) | [SetMemoResourcesResponse](#memos-api-v2-SetMemoResourcesResponse) | | | ListMemoResources | [ListMemoResourcesRequest](#memos-api-v2-ListMemoResourcesRequest) | [ListMemoResourcesResponse](#memos-api-v2-ListMemoResourcesResponse) | | +| SetMemoRelations | [SetMemoRelationsRequest](#memos-api-v2-SetMemoRelationsRequest) | [SetMemoRelationsResponse](#memos-api-v2-SetMemoRelationsResponse) | | +| ListMemoRelations | [ListMemoRelationsRequest](#memos-api-v2-ListMemoRelationsRequest) | [ListMemoRelationsResponse](#memos-api-v2-ListMemoRelationsResponse) | | | CreateMemoComment | [CreateMemoCommentRequest](#memos-api-v2-CreateMemoCommentRequest) | [CreateMemoCommentResponse](#memos-api-v2-CreateMemoCommentResponse) | | | ListMemoComments | [ListMemoCommentsRequest](#memos-api-v2-ListMemoCommentsRequest) | [ListMemoCommentsResponse](#memos-api-v2-ListMemoCommentsResponse) | | diff --git a/proto/gen/api/v2/memo_relation_service.pb.go b/proto/gen/api/v2/memo_relation_service.pb.go new file mode 100644 index 000000000..28d0644dd --- /dev/null +++ b/proto/gen/api/v2/memo_relation_service.pb.go @@ -0,0 +1,232 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.31.0 +// protoc (unknown) +// source: api/v2/memo_relation_service.proto + +package apiv2 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type MemoRelation_Type int32 + +const ( + MemoRelation_TYPE_UNSPECIFIED MemoRelation_Type = 0 + MemoRelation_REFERENCE MemoRelation_Type = 1 + MemoRelation_COMMENT MemoRelation_Type = 2 +) + +// Enum value maps for MemoRelation_Type. +var ( + MemoRelation_Type_name = map[int32]string{ + 0: "TYPE_UNSPECIFIED", + 1: "REFERENCE", + 2: "COMMENT", + } + MemoRelation_Type_value = map[string]int32{ + "TYPE_UNSPECIFIED": 0, + "REFERENCE": 1, + "COMMENT": 2, + } +) + +func (x MemoRelation_Type) Enum() *MemoRelation_Type { + p := new(MemoRelation_Type) + *p = x + return p +} + +func (x MemoRelation_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (MemoRelation_Type) Descriptor() protoreflect.EnumDescriptor { + return file_api_v2_memo_relation_service_proto_enumTypes[0].Descriptor() +} + +func (MemoRelation_Type) Type() protoreflect.EnumType { + return &file_api_v2_memo_relation_service_proto_enumTypes[0] +} + +func (x MemoRelation_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use MemoRelation_Type.Descriptor instead. +func (MemoRelation_Type) EnumDescriptor() ([]byte, []int) { + return file_api_v2_memo_relation_service_proto_rawDescGZIP(), []int{0, 0} +} + +type MemoRelation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + MemoId int32 `protobuf:"varint,1,opt,name=memo_id,json=memoId,proto3" json:"memo_id,omitempty"` + RelatedMemoId int32 `protobuf:"varint,2,opt,name=related_memo_id,json=relatedMemoId,proto3" json:"related_memo_id,omitempty"` + Type MemoRelation_Type `protobuf:"varint,3,opt,name=type,proto3,enum=memos.api.v2.MemoRelation_Type" json:"type,omitempty"` +} + +func (x *MemoRelation) Reset() { + *x = MemoRelation{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_relation_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MemoRelation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MemoRelation) ProtoMessage() {} + +func (x *MemoRelation) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_relation_service_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MemoRelation.ProtoReflect.Descriptor instead. +func (*MemoRelation) Descriptor() ([]byte, []int) { + return file_api_v2_memo_relation_service_proto_rawDescGZIP(), []int{0} +} + +func (x *MemoRelation) GetMemoId() int32 { + if x != nil { + return x.MemoId + } + return 0 +} + +func (x *MemoRelation) GetRelatedMemoId() int32 { + if x != nil { + return x.RelatedMemoId + } + return 0 +} + +func (x *MemoRelation) GetType() MemoRelation_Type { + if x != nil { + return x.Type + } + return MemoRelation_TYPE_UNSPECIFIED +} + +var File_api_v2_memo_relation_service_proto protoreflect.FileDescriptor + +var file_api_v2_memo_relation_service_proto_rawDesc = []byte{ + 0x0a, 0x22, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x32, 0x22, 0xbe, 0x01, 0x0a, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, + 0x6d, 0x6f, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x38, 0x0a, 0x04, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, + 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x46, 0x45, 0x52, + 0x45, 0x4e, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, + 0x54, 0x10, 0x02, 0x42, 0xb0, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, + 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, + 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, + 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 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, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_api_v2_memo_relation_service_proto_rawDescOnce sync.Once + file_api_v2_memo_relation_service_proto_rawDescData = file_api_v2_memo_relation_service_proto_rawDesc +) + +func file_api_v2_memo_relation_service_proto_rawDescGZIP() []byte { + file_api_v2_memo_relation_service_proto_rawDescOnce.Do(func() { + file_api_v2_memo_relation_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_v2_memo_relation_service_proto_rawDescData) + }) + return file_api_v2_memo_relation_service_proto_rawDescData +} + +var file_api_v2_memo_relation_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_api_v2_memo_relation_service_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_api_v2_memo_relation_service_proto_goTypes = []interface{}{ + (MemoRelation_Type)(0), // 0: memos.api.v2.MemoRelation.Type + (*MemoRelation)(nil), // 1: memos.api.v2.MemoRelation +} +var file_api_v2_memo_relation_service_proto_depIdxs = []int32{ + 0, // 0: memos.api.v2.MemoRelation.type:type_name -> memos.api.v2.MemoRelation.Type + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_api_v2_memo_relation_service_proto_init() } +func file_api_v2_memo_relation_service_proto_init() { + if File_api_v2_memo_relation_service_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_api_v2_memo_relation_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MemoRelation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_api_v2_memo_relation_service_proto_rawDesc, + NumEnums: 1, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_api_v2_memo_relation_service_proto_goTypes, + DependencyIndexes: file_api_v2_memo_relation_service_proto_depIdxs, + EnumInfos: file_api_v2_memo_relation_service_proto_enumTypes, + MessageInfos: file_api_v2_memo_relation_service_proto_msgTypes, + }.Build() + File_api_v2_memo_relation_service_proto = out.File + file_api_v2_memo_relation_service_proto_rawDesc = nil + file_api_v2_memo_relation_service_proto_goTypes = nil + file_api_v2_memo_relation_service_proto_depIdxs = nil +} diff --git a/proto/gen/api/v2/memo_service.pb.go b/proto/gen/api/v2/memo_service.pb.go index ef6207fd1..44a74df3a 100644 --- a/proto/gen/api/v2/memo_service.pb.go +++ b/proto/gen/api/v2/memo_service.pb.go @@ -696,6 +696,99 @@ func (*DeleteMemoResponse) Descriptor() ([]byte, []int) { return file_api_v2_memo_service_proto_rawDescGZIP(), []int{10} } +type SetMemoResourcesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` +} + +func (x *SetMemoResourcesRequest) Reset() { + *x = SetMemoResourcesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_service_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetMemoResourcesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetMemoResourcesRequest) ProtoMessage() {} + +func (x *SetMemoResourcesRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_service_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetMemoResourcesRequest.ProtoReflect.Descriptor instead. +func (*SetMemoResourcesRequest) Descriptor() ([]byte, []int) { + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{11} +} + +func (x *SetMemoResourcesRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *SetMemoResourcesRequest) GetResources() []*Resource { + if x != nil { + return x.Resources + } + return nil +} + +type SetMemoResourcesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SetMemoResourcesResponse) Reset() { + *x = SetMemoResourcesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetMemoResourcesResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetMemoResourcesResponse) ProtoMessage() {} + +func (x *SetMemoResourcesResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_service_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetMemoResourcesResponse.ProtoReflect.Descriptor instead. +func (*SetMemoResourcesResponse) Descriptor() ([]byte, []int) { + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{12} +} + type ListMemoResourcesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -707,7 +800,7 @@ type ListMemoResourcesRequest struct { func (x *ListMemoResourcesRequest) Reset() { *x = ListMemoResourcesRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_v2_memo_service_proto_msgTypes[11] + mi := &file_api_v2_memo_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -720,7 +813,7 @@ func (x *ListMemoResourcesRequest) String() string { func (*ListMemoResourcesRequest) ProtoMessage() {} func (x *ListMemoResourcesRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_memo_service_proto_msgTypes[11] + mi := &file_api_v2_memo_service_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -733,7 +826,7 @@ func (x *ListMemoResourcesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMemoResourcesRequest.ProtoReflect.Descriptor instead. func (*ListMemoResourcesRequest) Descriptor() ([]byte, []int) { - return file_api_v2_memo_service_proto_rawDescGZIP(), []int{11} + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{13} } func (x *ListMemoResourcesRequest) GetId() int32 { @@ -754,7 +847,7 @@ type ListMemoResourcesResponse struct { func (x *ListMemoResourcesResponse) Reset() { *x = ListMemoResourcesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_v2_memo_service_proto_msgTypes[12] + mi := &file_api_v2_memo_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -767,7 +860,7 @@ func (x *ListMemoResourcesResponse) String() string { func (*ListMemoResourcesResponse) ProtoMessage() {} func (x *ListMemoResourcesResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_memo_service_proto_msgTypes[12] + mi := &file_api_v2_memo_service_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -780,7 +873,7 @@ func (x *ListMemoResourcesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMemoResourcesResponse.ProtoReflect.Descriptor instead. func (*ListMemoResourcesResponse) Descriptor() ([]byte, []int) { - return file_api_v2_memo_service_proto_rawDescGZIP(), []int{12} + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{14} } func (x *ListMemoResourcesResponse) GetResources() []*Resource { @@ -790,6 +883,193 @@ func (x *ListMemoResourcesResponse) GetResources() []*Resource { return nil } +type SetMemoRelationsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Relations []*MemoRelation `protobuf:"bytes,2,rep,name=relations,proto3" json:"relations,omitempty"` +} + +func (x *SetMemoRelationsRequest) Reset() { + *x = SetMemoRelationsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetMemoRelationsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetMemoRelationsRequest) ProtoMessage() {} + +func (x *SetMemoRelationsRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_service_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetMemoRelationsRequest.ProtoReflect.Descriptor instead. +func (*SetMemoRelationsRequest) Descriptor() ([]byte, []int) { + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{15} +} + +func (x *SetMemoRelationsRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *SetMemoRelationsRequest) GetRelations() []*MemoRelation { + if x != nil { + return x.Relations + } + return nil +} + +type SetMemoRelationsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *SetMemoRelationsResponse) Reset() { + *x = SetMemoRelationsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SetMemoRelationsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetMemoRelationsResponse) ProtoMessage() {} + +func (x *SetMemoRelationsResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_service_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SetMemoRelationsResponse.ProtoReflect.Descriptor instead. +func (*SetMemoRelationsResponse) Descriptor() ([]byte, []int) { + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{16} +} + +type ListMemoRelationsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *ListMemoRelationsRequest) Reset() { + *x = ListMemoRelationsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListMemoRelationsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListMemoRelationsRequest) ProtoMessage() {} + +func (x *ListMemoRelationsRequest) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_service_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListMemoRelationsRequest.ProtoReflect.Descriptor instead. +func (*ListMemoRelationsRequest) Descriptor() ([]byte, []int) { + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{17} +} + +func (x *ListMemoRelationsRequest) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type ListMemoRelationsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Relations []*MemoRelation `protobuf:"bytes,1,rep,name=relations,proto3" json:"relations,omitempty"` +} + +func (x *ListMemoRelationsResponse) Reset() { + *x = ListMemoRelationsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_api_v2_memo_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListMemoRelationsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListMemoRelationsResponse) ProtoMessage() {} + +func (x *ListMemoRelationsResponse) ProtoReflect() protoreflect.Message { + mi := &file_api_v2_memo_service_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListMemoRelationsResponse.ProtoReflect.Descriptor instead. +func (*ListMemoRelationsResponse) Descriptor() ([]byte, []int) { + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{18} +} + +func (x *ListMemoRelationsResponse) GetRelations() []*MemoRelation { + if x != nil { + return x.Relations + } + return nil +} + type CreateMemoCommentRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -803,7 +1083,7 @@ type CreateMemoCommentRequest struct { func (x *CreateMemoCommentRequest) Reset() { *x = CreateMemoCommentRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_v2_memo_service_proto_msgTypes[13] + mi := &file_api_v2_memo_service_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -816,7 +1096,7 @@ func (x *CreateMemoCommentRequest) String() string { func (*CreateMemoCommentRequest) ProtoMessage() {} func (x *CreateMemoCommentRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_memo_service_proto_msgTypes[13] + mi := &file_api_v2_memo_service_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -829,7 +1109,7 @@ func (x *CreateMemoCommentRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateMemoCommentRequest.ProtoReflect.Descriptor instead. func (*CreateMemoCommentRequest) Descriptor() ([]byte, []int) { - return file_api_v2_memo_service_proto_rawDescGZIP(), []int{13} + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{19} } func (x *CreateMemoCommentRequest) GetId() int32 { @@ -857,7 +1137,7 @@ type CreateMemoCommentResponse struct { func (x *CreateMemoCommentResponse) Reset() { *x = CreateMemoCommentResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_v2_memo_service_proto_msgTypes[14] + mi := &file_api_v2_memo_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -870,7 +1150,7 @@ func (x *CreateMemoCommentResponse) String() string { func (*CreateMemoCommentResponse) ProtoMessage() {} func (x *CreateMemoCommentResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_memo_service_proto_msgTypes[14] + mi := &file_api_v2_memo_service_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -883,7 +1163,7 @@ func (x *CreateMemoCommentResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateMemoCommentResponse.ProtoReflect.Descriptor instead. func (*CreateMemoCommentResponse) Descriptor() ([]byte, []int) { - return file_api_v2_memo_service_proto_rawDescGZIP(), []int{14} + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{20} } func (x *CreateMemoCommentResponse) GetMemo() *Memo { @@ -904,7 +1184,7 @@ type ListMemoCommentsRequest struct { func (x *ListMemoCommentsRequest) Reset() { *x = ListMemoCommentsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_api_v2_memo_service_proto_msgTypes[15] + mi := &file_api_v2_memo_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -917,7 +1197,7 @@ func (x *ListMemoCommentsRequest) String() string { func (*ListMemoCommentsRequest) ProtoMessage() {} func (x *ListMemoCommentsRequest) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_memo_service_proto_msgTypes[15] + mi := &file_api_v2_memo_service_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -930,7 +1210,7 @@ func (x *ListMemoCommentsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMemoCommentsRequest.ProtoReflect.Descriptor instead. func (*ListMemoCommentsRequest) Descriptor() ([]byte, []int) { - return file_api_v2_memo_service_proto_rawDescGZIP(), []int{15} + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{21} } func (x *ListMemoCommentsRequest) GetId() int32 { @@ -951,7 +1231,7 @@ type ListMemoCommentsResponse struct { func (x *ListMemoCommentsResponse) Reset() { *x = ListMemoCommentsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_api_v2_memo_service_proto_msgTypes[16] + mi := &file_api_v2_memo_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -964,7 +1244,7 @@ func (x *ListMemoCommentsResponse) String() string { func (*ListMemoCommentsResponse) ProtoMessage() {} func (x *ListMemoCommentsResponse) ProtoReflect() protoreflect.Message { - mi := &file_api_v2_memo_service_proto_msgTypes[16] + mi := &file_api_v2_memo_service_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -977,7 +1257,7 @@ func (x *ListMemoCommentsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ListMemoCommentsResponse.ProtoReflect.Descriptor instead. func (*ListMemoCommentsResponse) Descriptor() ([]byte, []int) { - return file_api_v2_memo_service_proto_rawDescGZIP(), []int{16} + return file_api_v2_memo_service_proto_rawDescGZIP(), []int{22} } func (x *ListMemoCommentsResponse) GetMemos() []*Memo { @@ -995,192 +1275,246 @@ var file_api_v2_memo_service_proto_rawDesc = []byte{ 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x1a, 0x13, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x61, 0x72, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x5f, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1d, 0x61, - 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x03, 0x0a, 0x04, 0x4d, 0x65, 0x6d, 0x6f, 0x12, + 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x1a, 0x1d, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, + 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, + 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbc, 0x03, 0x0a, 0x04, 0x4d, + 0x65, 0x6d, 0x6f, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x02, 0x69, 0x64, 0x12, 0x36, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x09, 0x72, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, + 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4e, 0x6f, 0x64, 0x65, + 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, + 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x22, 0x67, 0x0a, 0x11, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, + 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x69, 0x73, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, + 0x74, 0x79, 0x22, 0x3c, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, + 0x22, 0x5b, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 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, 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, 0x3d, 0x0a, + 0x11, 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, 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, 0x22, 0x20, 0x0a, 0x0e, + 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x39, + 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, + 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x22, 0x88, 0x01, 0x0a, 0x11, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x36, 0x0a, 0x0a, 0x72, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x32, 0x2e, 0x52, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x09, 0x72, 0x6f, - 0x77, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x12, 0x3b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x3d, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, - 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x05, 0x6e, 0x6f, 0x64, - 0x65, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x05, 0x6e, 0x6f, - 0x64, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, - 0x06, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, - 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x22, 0x67, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, - 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, - 0x74, 0x79, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x22, 0x3c, - 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x22, 0x5b, 0x0a, 0x10, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 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, 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, 0x3d, 0x0a, 0x11, 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, 0x32, 0x12, 0x2e, + 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 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, 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x39, 0x0a, 0x0f, 0x47, 0x65, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, - 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, - 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x22, 0x88, 0x01, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x26, 0x0a, 0x04, 0x6d, - 0x65, 0x6d, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, - 0x65, 0x6d, 0x6f, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, - 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, - 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, - 0x22, 0x3c, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x22, 0x23, - 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x02, 0x69, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, - 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x22, 0x43, 0x0a, - 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, + 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x3b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, + 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x3c, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x04, 0x6d, 0x65, - 0x6d, 0x6f, 0x22, 0x29, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x44, 0x0a, - 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 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, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x05, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, - 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, - 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x52, - 0x4f, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, - 0x4c, 0x49, 0x43, 0x10, 0x03, 0x32, 0xec, 0x07, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, - 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x01, - 0x2a, 0x22, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, - 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x1e, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x67, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, - 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, - 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, - 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0xda, - 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x80, - 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, - 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, - 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x2f, 0xda, 0x41, 0x0f, 0x69, 0x64, 0x2c, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, - 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x01, 0x2a, 0x32, 0x12, 0x2f, - 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0x70, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x12, - 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1f, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x2a, - 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0x8f, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, - 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, - 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0xda, 0x41, 0x02, 0x69, - 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, - 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0xda, 0x41, - 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, - 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, - 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x6d, 0x6f, 0x22, 0x23, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x0a, + 0x17, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x1a, + 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x51, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x22, 0x63, 0x0a, 0x17, 0x53, 0x65, 0x74, + 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x1a, + 0x0a, 0x18, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x0a, 0x18, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x22, 0x55, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x09, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x63, 0x0a, + 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x37, 0x0a, 0x06, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, + 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x22, 0x43, 0x0a, 0x19, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, + 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x26, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, + 0x6f, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x22, 0x29, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, - 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0xda, 0x41, 0x02, 0x69, - 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, - 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x74, 0x73, 0x42, 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x4d, 0x65, 0x6d, 0x6f, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, - 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, - 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, - 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, - 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, - 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, - 0x56, 0x32, 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, 0x32, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, + 0x69, 0x64, 0x22, 0x44, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 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, 0x4d, 0x65, 0x6d, + 0x6f, 0x52, 0x05, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2a, 0x50, 0x0a, 0x0a, 0x56, 0x69, 0x73, 0x69, + 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x16, 0x56, 0x49, 0x53, 0x49, 0x42, 0x49, + 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, + 0x0d, 0x0a, 0x09, 0x50, 0x52, 0x4f, 0x54, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x12, 0x0a, + 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, 0x10, 0x03, 0x32, 0xa2, 0x0b, 0x0a, 0x0b, 0x4d, + 0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x0a, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, + 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, + 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x12, 0x3a, 0x01, 0x2a, 0x22, 0x0d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x63, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, + 0x6f, 0x73, 0x12, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x12, 0x67, 0x0a, 0x07, 0x47, 0x65, + 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1c, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1f, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, + 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0x80, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, + 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, + 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0xda, 0x41, 0x0f, 0x69, 0x64, 0x2c, 0x20, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, + 0x01, 0x2a, 0x32, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x70, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x14, 0x2a, 0x12, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x8f, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x74, + 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x25, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x74, + 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2c, 0xda, 0x41, + 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, + 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x8f, 0x01, 0x0a, 0x11, 0x4c, + 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x29, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x8f, 0x01, 0x0a, + 0x10, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, + 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2c, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, + 0x22, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, + 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x8f, + 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, + 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x8e, 0x01, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x26, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, + 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, + 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x1d, 0x22, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x25, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, + 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0xda, 0x41, 0x02, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1d, 0x12, 0x1b, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x42, + 0xa8, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x76, 0x32, 0x42, 0x10, 0x4d, 0x65, 0x6d, 0x6f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, + 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, + 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, + 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, + 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, + 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 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, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1196,7 +1530,7 @@ func file_api_v2_memo_service_proto_rawDescGZIP() []byte { } var file_api_v2_memo_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_api_v2_memo_service_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_api_v2_memo_service_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_api_v2_memo_service_proto_goTypes = []interface{}{ (Visibility)(0), // 0: memos.api.v2.Visibility (*Memo)(nil), // 1: memos.api.v2.Memo @@ -1210,57 +1544,73 @@ var file_api_v2_memo_service_proto_goTypes = []interface{}{ (*UpdateMemoResponse)(nil), // 9: memos.api.v2.UpdateMemoResponse (*DeleteMemoRequest)(nil), // 10: memos.api.v2.DeleteMemoRequest (*DeleteMemoResponse)(nil), // 11: memos.api.v2.DeleteMemoResponse - (*ListMemoResourcesRequest)(nil), // 12: memos.api.v2.ListMemoResourcesRequest - (*ListMemoResourcesResponse)(nil), // 13: memos.api.v2.ListMemoResourcesResponse - (*CreateMemoCommentRequest)(nil), // 14: memos.api.v2.CreateMemoCommentRequest - (*CreateMemoCommentResponse)(nil), // 15: memos.api.v2.CreateMemoCommentResponse - (*ListMemoCommentsRequest)(nil), // 16: memos.api.v2.ListMemoCommentsRequest - (*ListMemoCommentsResponse)(nil), // 17: memos.api.v2.ListMemoCommentsResponse - (RowStatus)(0), // 18: memos.api.v2.RowStatus - (*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp - (*Node)(nil), // 20: memos.api.v2.Node - (*fieldmaskpb.FieldMask)(nil), // 21: google.protobuf.FieldMask - (*Resource)(nil), // 22: memos.api.v2.Resource + (*SetMemoResourcesRequest)(nil), // 12: memos.api.v2.SetMemoResourcesRequest + (*SetMemoResourcesResponse)(nil), // 13: memos.api.v2.SetMemoResourcesResponse + (*ListMemoResourcesRequest)(nil), // 14: memos.api.v2.ListMemoResourcesRequest + (*ListMemoResourcesResponse)(nil), // 15: memos.api.v2.ListMemoResourcesResponse + (*SetMemoRelationsRequest)(nil), // 16: memos.api.v2.SetMemoRelationsRequest + (*SetMemoRelationsResponse)(nil), // 17: memos.api.v2.SetMemoRelationsResponse + (*ListMemoRelationsRequest)(nil), // 18: memos.api.v2.ListMemoRelationsRequest + (*ListMemoRelationsResponse)(nil), // 19: memos.api.v2.ListMemoRelationsResponse + (*CreateMemoCommentRequest)(nil), // 20: memos.api.v2.CreateMemoCommentRequest + (*CreateMemoCommentResponse)(nil), // 21: memos.api.v2.CreateMemoCommentResponse + (*ListMemoCommentsRequest)(nil), // 22: memos.api.v2.ListMemoCommentsRequest + (*ListMemoCommentsResponse)(nil), // 23: memos.api.v2.ListMemoCommentsResponse + (RowStatus)(0), // 24: memos.api.v2.RowStatus + (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp + (*Node)(nil), // 26: memos.api.v2.Node + (*fieldmaskpb.FieldMask)(nil), // 27: google.protobuf.FieldMask + (*Resource)(nil), // 28: memos.api.v2.Resource + (*MemoRelation)(nil), // 29: memos.api.v2.MemoRelation } var file_api_v2_memo_service_proto_depIdxs = []int32{ - 18, // 0: memos.api.v2.Memo.row_status:type_name -> memos.api.v2.RowStatus - 19, // 1: memos.api.v2.Memo.create_time:type_name -> google.protobuf.Timestamp - 19, // 2: memos.api.v2.Memo.update_time:type_name -> google.protobuf.Timestamp - 19, // 3: memos.api.v2.Memo.display_time:type_name -> google.protobuf.Timestamp - 20, // 4: memos.api.v2.Memo.nodes:type_name -> memos.api.v2.Node + 24, // 0: memos.api.v2.Memo.row_status:type_name -> memos.api.v2.RowStatus + 25, // 1: memos.api.v2.Memo.create_time:type_name -> google.protobuf.Timestamp + 25, // 2: memos.api.v2.Memo.update_time:type_name -> google.protobuf.Timestamp + 25, // 3: memos.api.v2.Memo.display_time:type_name -> google.protobuf.Timestamp + 26, // 4: memos.api.v2.Memo.nodes:type_name -> memos.api.v2.Node 0, // 5: memos.api.v2.Memo.visibility:type_name -> memos.api.v2.Visibility 0, // 6: memos.api.v2.CreateMemoRequest.visibility:type_name -> memos.api.v2.Visibility 1, // 7: memos.api.v2.CreateMemoResponse.memo:type_name -> memos.api.v2.Memo 1, // 8: memos.api.v2.ListMemosResponse.memos:type_name -> memos.api.v2.Memo 1, // 9: memos.api.v2.GetMemoResponse.memo:type_name -> memos.api.v2.Memo 1, // 10: memos.api.v2.UpdateMemoRequest.memo:type_name -> memos.api.v2.Memo - 21, // 11: memos.api.v2.UpdateMemoRequest.update_mask:type_name -> google.protobuf.FieldMask + 27, // 11: memos.api.v2.UpdateMemoRequest.update_mask:type_name -> google.protobuf.FieldMask 1, // 12: memos.api.v2.UpdateMemoResponse.memo:type_name -> memos.api.v2.Memo - 22, // 13: memos.api.v2.ListMemoResourcesResponse.resources:type_name -> memos.api.v2.Resource - 2, // 14: memos.api.v2.CreateMemoCommentRequest.create:type_name -> memos.api.v2.CreateMemoRequest - 1, // 15: memos.api.v2.CreateMemoCommentResponse.memo:type_name -> memos.api.v2.Memo - 1, // 16: memos.api.v2.ListMemoCommentsResponse.memos:type_name -> memos.api.v2.Memo - 2, // 17: memos.api.v2.MemoService.CreateMemo:input_type -> memos.api.v2.CreateMemoRequest - 4, // 18: memos.api.v2.MemoService.ListMemos:input_type -> memos.api.v2.ListMemosRequest - 6, // 19: memos.api.v2.MemoService.GetMemo:input_type -> memos.api.v2.GetMemoRequest - 8, // 20: memos.api.v2.MemoService.UpdateMemo:input_type -> memos.api.v2.UpdateMemoRequest - 10, // 21: memos.api.v2.MemoService.DeleteMemo:input_type -> memos.api.v2.DeleteMemoRequest - 12, // 22: memos.api.v2.MemoService.ListMemoResources:input_type -> memos.api.v2.ListMemoResourcesRequest - 14, // 23: memos.api.v2.MemoService.CreateMemoComment:input_type -> memos.api.v2.CreateMemoCommentRequest - 16, // 24: memos.api.v2.MemoService.ListMemoComments:input_type -> memos.api.v2.ListMemoCommentsRequest - 3, // 25: memos.api.v2.MemoService.CreateMemo:output_type -> memos.api.v2.CreateMemoResponse - 5, // 26: memos.api.v2.MemoService.ListMemos:output_type -> memos.api.v2.ListMemosResponse - 7, // 27: memos.api.v2.MemoService.GetMemo:output_type -> memos.api.v2.GetMemoResponse - 9, // 28: memos.api.v2.MemoService.UpdateMemo:output_type -> memos.api.v2.UpdateMemoResponse - 11, // 29: memos.api.v2.MemoService.DeleteMemo:output_type -> memos.api.v2.DeleteMemoResponse - 13, // 30: memos.api.v2.MemoService.ListMemoResources:output_type -> memos.api.v2.ListMemoResourcesResponse - 15, // 31: memos.api.v2.MemoService.CreateMemoComment:output_type -> memos.api.v2.CreateMemoCommentResponse - 17, // 32: memos.api.v2.MemoService.ListMemoComments:output_type -> memos.api.v2.ListMemoCommentsResponse - 25, // [25:33] is the sub-list for method output_type - 17, // [17:25] is the sub-list for method input_type - 17, // [17:17] is the sub-list for extension type_name - 17, // [17:17] is the sub-list for extension extendee - 0, // [0:17] is the sub-list for field type_name + 28, // 13: memos.api.v2.SetMemoResourcesRequest.resources:type_name -> memos.api.v2.Resource + 28, // 14: memos.api.v2.ListMemoResourcesResponse.resources:type_name -> memos.api.v2.Resource + 29, // 15: memos.api.v2.SetMemoRelationsRequest.relations:type_name -> memos.api.v2.MemoRelation + 29, // 16: memos.api.v2.ListMemoRelationsResponse.relations:type_name -> memos.api.v2.MemoRelation + 2, // 17: memos.api.v2.CreateMemoCommentRequest.create:type_name -> memos.api.v2.CreateMemoRequest + 1, // 18: memos.api.v2.CreateMemoCommentResponse.memo:type_name -> memos.api.v2.Memo + 1, // 19: memos.api.v2.ListMemoCommentsResponse.memos:type_name -> memos.api.v2.Memo + 2, // 20: memos.api.v2.MemoService.CreateMemo:input_type -> memos.api.v2.CreateMemoRequest + 4, // 21: memos.api.v2.MemoService.ListMemos:input_type -> memos.api.v2.ListMemosRequest + 6, // 22: memos.api.v2.MemoService.GetMemo:input_type -> memos.api.v2.GetMemoRequest + 8, // 23: memos.api.v2.MemoService.UpdateMemo:input_type -> memos.api.v2.UpdateMemoRequest + 10, // 24: memos.api.v2.MemoService.DeleteMemo:input_type -> memos.api.v2.DeleteMemoRequest + 12, // 25: memos.api.v2.MemoService.SetMemoResources:input_type -> memos.api.v2.SetMemoResourcesRequest + 14, // 26: memos.api.v2.MemoService.ListMemoResources:input_type -> memos.api.v2.ListMemoResourcesRequest + 16, // 27: memos.api.v2.MemoService.SetMemoRelations:input_type -> memos.api.v2.SetMemoRelationsRequest + 18, // 28: memos.api.v2.MemoService.ListMemoRelations:input_type -> memos.api.v2.ListMemoRelationsRequest + 20, // 29: memos.api.v2.MemoService.CreateMemoComment:input_type -> memos.api.v2.CreateMemoCommentRequest + 22, // 30: memos.api.v2.MemoService.ListMemoComments:input_type -> memos.api.v2.ListMemoCommentsRequest + 3, // 31: memos.api.v2.MemoService.CreateMemo:output_type -> memos.api.v2.CreateMemoResponse + 5, // 32: memos.api.v2.MemoService.ListMemos:output_type -> memos.api.v2.ListMemosResponse + 7, // 33: memos.api.v2.MemoService.GetMemo:output_type -> memos.api.v2.GetMemoResponse + 9, // 34: memos.api.v2.MemoService.UpdateMemo:output_type -> memos.api.v2.UpdateMemoResponse + 11, // 35: memos.api.v2.MemoService.DeleteMemo:output_type -> memos.api.v2.DeleteMemoResponse + 13, // 36: memos.api.v2.MemoService.SetMemoResources:output_type -> memos.api.v2.SetMemoResourcesResponse + 15, // 37: memos.api.v2.MemoService.ListMemoResources:output_type -> memos.api.v2.ListMemoResourcesResponse + 17, // 38: memos.api.v2.MemoService.SetMemoRelations:output_type -> memos.api.v2.SetMemoRelationsResponse + 19, // 39: memos.api.v2.MemoService.ListMemoRelations:output_type -> memos.api.v2.ListMemoRelationsResponse + 21, // 40: memos.api.v2.MemoService.CreateMemoComment:output_type -> memos.api.v2.CreateMemoCommentResponse + 23, // 41: memos.api.v2.MemoService.ListMemoComments:output_type -> memos.api.v2.ListMemoCommentsResponse + 31, // [31:42] is the sub-list for method output_type + 20, // [20:31] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name } func init() { file_api_v2_memo_service_proto_init() } @@ -1270,6 +1620,7 @@ func file_api_v2_memo_service_proto_init() { } file_api_v2_common_proto_init() file_api_v2_markdown_service_proto_init() + file_api_v2_memo_relation_service_proto_init() file_api_v2_resource_service_proto_init() if !protoimpl.UnsafeEnabled { file_api_v2_memo_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { @@ -1405,7 +1756,7 @@ func file_api_v2_memo_service_proto_init() { } } file_api_v2_memo_service_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMemoResourcesRequest); i { + switch v := v.(*SetMemoResourcesRequest); i { case 0: return &v.state case 1: @@ -1417,7 +1768,7 @@ func file_api_v2_memo_service_proto_init() { } } file_api_v2_memo_service_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMemoResourcesResponse); i { + switch v := v.(*SetMemoResourcesResponse); i { case 0: return &v.state case 1: @@ -1429,7 +1780,7 @@ func file_api_v2_memo_service_proto_init() { } } file_api_v2_memo_service_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateMemoCommentRequest); i { + switch v := v.(*ListMemoResourcesRequest); i { case 0: return &v.state case 1: @@ -1441,7 +1792,7 @@ func file_api_v2_memo_service_proto_init() { } } file_api_v2_memo_service_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateMemoCommentResponse); i { + switch v := v.(*ListMemoResourcesResponse); i { case 0: return &v.state case 1: @@ -1453,7 +1804,7 @@ func file_api_v2_memo_service_proto_init() { } } file_api_v2_memo_service_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListMemoCommentsRequest); i { + switch v := v.(*SetMemoRelationsRequest); i { case 0: return &v.state case 1: @@ -1465,6 +1816,78 @@ func file_api_v2_memo_service_proto_init() { } } file_api_v2_memo_service_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SetMemoRelationsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_memo_service_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListMemoRelationsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_memo_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListMemoRelationsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_memo_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateMemoCommentRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_memo_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateMemoCommentResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_memo_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListMemoCommentsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_api_v2_memo_service_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListMemoCommentsResponse); i { case 0: return &v.state @@ -1483,7 +1906,7 @@ func file_api_v2_memo_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_api_v2_memo_service_proto_rawDesc, NumEnums: 1, - NumMessages: 17, + NumMessages: 23, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/gen/api/v2/memo_service.pb.gw.go b/proto/gen/api/v2/memo_service.pb.gw.go index 4e008548c..2d95f4cc9 100644 --- a/proto/gen/api/v2/memo_service.pb.gw.go +++ b/proto/gen/api/v2/memo_service.pb.gw.go @@ -273,6 +273,74 @@ func local_request_MemoService_DeleteMemo_0(ctx context.Context, marshaler runti } +func request_MemoService_SetMemoResources_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetMemoResourcesRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.SetMemoResources(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_MemoService_SetMemoResources_0(ctx context.Context, marshaler runtime.Marshaler, server MemoServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetMemoResourcesRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.SetMemoResources(ctx, &protoReq) + return msg, metadata, err + +} + func request_MemoService_ListMemoResources_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListMemoResourcesRequest var metadata runtime.ServerMetadata @@ -325,6 +393,126 @@ func local_request_MemoService_ListMemoResources_0(ctx context.Context, marshale } +func request_MemoService_SetMemoRelations_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetMemoRelationsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.SetMemoRelations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_MemoService_SetMemoRelations_0(ctx context.Context, marshaler runtime.Marshaler, server MemoServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetMemoRelationsRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) + } + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.SetMemoRelations(ctx, &protoReq) + return msg, metadata, err + +} + +func request_MemoService_ListMemoRelations_0(ctx context.Context, marshaler runtime.Marshaler, client MemoServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListMemoRelationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := client.ListMemoRelations(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_MemoService_ListMemoRelations_0(ctx context.Context, marshaler runtime.Marshaler, server MemoServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListMemoRelationsRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["id"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + } + + protoReq.Id, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + } + + msg, err := server.ListMemoRelations(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_MemoService_CreateMemoComment_0 = &utilities.DoubleArray{Encoding: map[string]int{"id": 0}, Base: []int{1, 2, 0, 0}, Check: []int{0, 1, 2, 2}} ) @@ -578,6 +766,31 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_MemoService_SetMemoResources_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.v2.MemoService/SetMemoResources", runtime.WithHTTPPathPattern("/api/v2/memos/{id}/resources")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_MemoService_SetMemoResources_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_SetMemoResources_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_MemoService_ListMemoResources_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -603,6 +816,56 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_MemoService_SetMemoRelations_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.v2.MemoService/SetMemoRelations", runtime.WithHTTPPathPattern("/api/v2/memos/{id}/relations")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_MemoService_SetMemoRelations_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_SetMemoRelations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_MemoService_ListMemoRelations_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.v2.MemoService/ListMemoRelations", runtime.WithHTTPPathPattern("/api/v2/memos/{id}/relations")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_MemoService_ListMemoRelations_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_ListMemoRelations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_MemoService_CreateMemoComment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -804,6 +1067,28 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_MemoService_SetMemoResources_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.v2.MemoService/SetMemoResources", runtime.WithHTTPPathPattern("/api/v2/memos/{id}/resources")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_MemoService_SetMemoResources_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_SetMemoResources_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("GET", pattern_MemoService_ListMemoResources_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -826,6 +1111,50 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux }) + mux.Handle("POST", pattern_MemoService_SetMemoRelations_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.v2.MemoService/SetMemoRelations", runtime.WithHTTPPathPattern("/api/v2/memos/{id}/relations")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_MemoService_SetMemoRelations_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_SetMemoRelations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_MemoService_ListMemoRelations_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.v2.MemoService/ListMemoRelations", runtime.WithHTTPPathPattern("/api/v2/memos/{id}/relations")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_MemoService_ListMemoRelations_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_ListMemoRelations_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + mux.Handle("POST", pattern_MemoService_CreateMemoComment_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -884,8 +1213,14 @@ var ( pattern_MemoService_DeleteMemo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v2", "memos", "id"}, "")) + pattern_MemoService_SetMemoResources_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v2", "memos", "id", "resources"}, "")) + pattern_MemoService_ListMemoResources_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v2", "memos", "id", "resources"}, "")) + pattern_MemoService_SetMemoRelations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v2", "memos", "id", "relations"}, "")) + + pattern_MemoService_ListMemoRelations_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v2", "memos", "id", "relations"}, "")) + pattern_MemoService_CreateMemoComment_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v2", "memos", "id", "comments"}, "")) pattern_MemoService_ListMemoComments_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v2", "memos", "id", "comments"}, "")) @@ -902,8 +1237,14 @@ var ( forward_MemoService_DeleteMemo_0 = runtime.ForwardResponseMessage + forward_MemoService_SetMemoResources_0 = runtime.ForwardResponseMessage + forward_MemoService_ListMemoResources_0 = runtime.ForwardResponseMessage + forward_MemoService_SetMemoRelations_0 = runtime.ForwardResponseMessage + + forward_MemoService_ListMemoRelations_0 = runtime.ForwardResponseMessage + forward_MemoService_CreateMemoComment_0 = runtime.ForwardResponseMessage forward_MemoService_ListMemoComments_0 = runtime.ForwardResponseMessage diff --git a/proto/gen/api/v2/memo_service_grpc.pb.go b/proto/gen/api/v2/memo_service_grpc.pb.go index c03e6a1df..9154f826d 100644 --- a/proto/gen/api/v2/memo_service_grpc.pb.go +++ b/proto/gen/api/v2/memo_service_grpc.pb.go @@ -24,7 +24,10 @@ const ( MemoService_GetMemo_FullMethodName = "/memos.api.v2.MemoService/GetMemo" MemoService_UpdateMemo_FullMethodName = "/memos.api.v2.MemoService/UpdateMemo" MemoService_DeleteMemo_FullMethodName = "/memos.api.v2.MemoService/DeleteMemo" + MemoService_SetMemoResources_FullMethodName = "/memos.api.v2.MemoService/SetMemoResources" MemoService_ListMemoResources_FullMethodName = "/memos.api.v2.MemoService/ListMemoResources" + MemoService_SetMemoRelations_FullMethodName = "/memos.api.v2.MemoService/SetMemoRelations" + MemoService_ListMemoRelations_FullMethodName = "/memos.api.v2.MemoService/ListMemoRelations" MemoService_CreateMemoComment_FullMethodName = "/memos.api.v2.MemoService/CreateMemoComment" MemoService_ListMemoComments_FullMethodName = "/memos.api.v2.MemoService/ListMemoComments" ) @@ -38,7 +41,10 @@ type MemoServiceClient interface { GetMemo(ctx context.Context, in *GetMemoRequest, opts ...grpc.CallOption) (*GetMemoResponse, error) UpdateMemo(ctx context.Context, in *UpdateMemoRequest, opts ...grpc.CallOption) (*UpdateMemoResponse, error) DeleteMemo(ctx context.Context, in *DeleteMemoRequest, opts ...grpc.CallOption) (*DeleteMemoResponse, error) + SetMemoResources(ctx context.Context, in *SetMemoResourcesRequest, opts ...grpc.CallOption) (*SetMemoResourcesResponse, error) ListMemoResources(ctx context.Context, in *ListMemoResourcesRequest, opts ...grpc.CallOption) (*ListMemoResourcesResponse, error) + SetMemoRelations(ctx context.Context, in *SetMemoRelationsRequest, opts ...grpc.CallOption) (*SetMemoRelationsResponse, error) + ListMemoRelations(ctx context.Context, in *ListMemoRelationsRequest, opts ...grpc.CallOption) (*ListMemoRelationsResponse, error) CreateMemoComment(ctx context.Context, in *CreateMemoCommentRequest, opts ...grpc.CallOption) (*CreateMemoCommentResponse, error) ListMemoComments(ctx context.Context, in *ListMemoCommentsRequest, opts ...grpc.CallOption) (*ListMemoCommentsResponse, error) } @@ -96,6 +102,15 @@ func (c *memoServiceClient) DeleteMemo(ctx context.Context, in *DeleteMemoReques return out, nil } +func (c *memoServiceClient) SetMemoResources(ctx context.Context, in *SetMemoResourcesRequest, opts ...grpc.CallOption) (*SetMemoResourcesResponse, error) { + out := new(SetMemoResourcesResponse) + err := c.cc.Invoke(ctx, MemoService_SetMemoResources_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *memoServiceClient) ListMemoResources(ctx context.Context, in *ListMemoResourcesRequest, opts ...grpc.CallOption) (*ListMemoResourcesResponse, error) { out := new(ListMemoResourcesResponse) err := c.cc.Invoke(ctx, MemoService_ListMemoResources_FullMethodName, in, out, opts...) @@ -105,6 +120,24 @@ func (c *memoServiceClient) ListMemoResources(ctx context.Context, in *ListMemoR return out, nil } +func (c *memoServiceClient) SetMemoRelations(ctx context.Context, in *SetMemoRelationsRequest, opts ...grpc.CallOption) (*SetMemoRelationsResponse, error) { + out := new(SetMemoRelationsResponse) + err := c.cc.Invoke(ctx, MemoService_SetMemoRelations_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *memoServiceClient) ListMemoRelations(ctx context.Context, in *ListMemoRelationsRequest, opts ...grpc.CallOption) (*ListMemoRelationsResponse, error) { + out := new(ListMemoRelationsResponse) + err := c.cc.Invoke(ctx, MemoService_ListMemoRelations_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *memoServiceClient) CreateMemoComment(ctx context.Context, in *CreateMemoCommentRequest, opts ...grpc.CallOption) (*CreateMemoCommentResponse, error) { out := new(CreateMemoCommentResponse) err := c.cc.Invoke(ctx, MemoService_CreateMemoComment_FullMethodName, in, out, opts...) @@ -132,7 +165,10 @@ type MemoServiceServer interface { GetMemo(context.Context, *GetMemoRequest) (*GetMemoResponse, error) UpdateMemo(context.Context, *UpdateMemoRequest) (*UpdateMemoResponse, error) DeleteMemo(context.Context, *DeleteMemoRequest) (*DeleteMemoResponse, error) + SetMemoResources(context.Context, *SetMemoResourcesRequest) (*SetMemoResourcesResponse, error) ListMemoResources(context.Context, *ListMemoResourcesRequest) (*ListMemoResourcesResponse, error) + SetMemoRelations(context.Context, *SetMemoRelationsRequest) (*SetMemoRelationsResponse, error) + ListMemoRelations(context.Context, *ListMemoRelationsRequest) (*ListMemoRelationsResponse, error) CreateMemoComment(context.Context, *CreateMemoCommentRequest) (*CreateMemoCommentResponse, error) ListMemoComments(context.Context, *ListMemoCommentsRequest) (*ListMemoCommentsResponse, error) mustEmbedUnimplementedMemoServiceServer() @@ -157,9 +193,18 @@ func (UnimplementedMemoServiceServer) UpdateMemo(context.Context, *UpdateMemoReq func (UnimplementedMemoServiceServer) DeleteMemo(context.Context, *DeleteMemoRequest) (*DeleteMemoResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method DeleteMemo not implemented") } +func (UnimplementedMemoServiceServer) SetMemoResources(context.Context, *SetMemoResourcesRequest) (*SetMemoResourcesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetMemoResources not implemented") +} func (UnimplementedMemoServiceServer) ListMemoResources(context.Context, *ListMemoResourcesRequest) (*ListMemoResourcesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListMemoResources not implemented") } +func (UnimplementedMemoServiceServer) SetMemoRelations(context.Context, *SetMemoRelationsRequest) (*SetMemoRelationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetMemoRelations not implemented") +} +func (UnimplementedMemoServiceServer) ListMemoRelations(context.Context, *ListMemoRelationsRequest) (*ListMemoRelationsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListMemoRelations not implemented") +} func (UnimplementedMemoServiceServer) CreateMemoComment(context.Context, *CreateMemoCommentRequest) (*CreateMemoCommentResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateMemoComment not implemented") } @@ -269,6 +314,24 @@ func _MemoService_DeleteMemo_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _MemoService_SetMemoResources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetMemoResourcesRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemoServiceServer).SetMemoResources(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MemoService_SetMemoResources_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemoServiceServer).SetMemoResources(ctx, req.(*SetMemoResourcesRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _MemoService_ListMemoResources_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListMemoResourcesRequest) if err := dec(in); err != nil { @@ -287,6 +350,42 @@ func _MemoService_ListMemoResources_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _MemoService_SetMemoRelations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetMemoRelationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemoServiceServer).SetMemoRelations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MemoService_SetMemoRelations_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemoServiceServer).SetMemoRelations(ctx, req.(*SetMemoRelationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MemoService_ListMemoRelations_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListMemoRelationsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MemoServiceServer).ListMemoRelations(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MemoService_ListMemoRelations_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MemoServiceServer).ListMemoRelations(ctx, req.(*ListMemoRelationsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _MemoService_CreateMemoComment_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreateMemoCommentRequest) if err := dec(in); err != nil { @@ -350,10 +449,22 @@ var MemoService_ServiceDesc = grpc.ServiceDesc{ MethodName: "DeleteMemo", Handler: _MemoService_DeleteMemo_Handler, }, + { + MethodName: "SetMemoResources", + Handler: _MemoService_SetMemoResources_Handler, + }, { MethodName: "ListMemoResources", Handler: _MemoService_ListMemoResources_Handler, }, + { + MethodName: "SetMemoRelations", + Handler: _MemoService_SetMemoRelations_Handler, + }, + { + MethodName: "ListMemoRelations", + Handler: _MemoService_ListMemoRelations_Handler, + }, { MethodName: "CreateMemoComment", Handler: _MemoService_CreateMemoComment_Handler, diff --git a/web/src/components/MemoEditorV1/ActionButton/TagSelector.tsx b/web/src/components/MemoEditorV1/ActionButton/TagSelector.tsx new file mode 100644 index 000000000..f9cbbd97b --- /dev/null +++ b/web/src/components/MemoEditorV1/ActionButton/TagSelector.tsx @@ -0,0 +1,52 @@ +import { IconButton } from "@mui/joy"; +import { useEffect } from "react"; +import Icon from "@/components/Icon"; +import OverflowTip from "@/components/kit/OverflowTip"; +import { useTagStore } from "@/store/module"; + +interface Props { + onTagSelectorClick: (tag: string) => void; +} + +const TagSelector = (props: Props) => { + const { onTagSelectorClick } = props; + const tagStore = useTagStore(); + const tags = tagStore.state.tags; + + useEffect(() => { + (async () => { + try { + await tagStore.fetchTags(); + } catch (error) { + // do nothing. + } + })(); + }, []); + + return ( + + +
+ {tags.length > 0 ? ( + tags.map((tag) => { + return ( +
onTagSelectorClick(tag)} + key={tag} + > + #{tag} +
+ ); + }) + ) : ( +

e.stopPropagation()}> + No tags found +

+ )} +
+
+ ); +}; + +export default TagSelector; diff --git a/web/src/components/MemoEditorV1/Editor/TagSuggestions.tsx b/web/src/components/MemoEditorV1/Editor/TagSuggestions.tsx new file mode 100644 index 000000000..7ba64b140 --- /dev/null +++ b/web/src/components/MemoEditorV1/Editor/TagSuggestions.tsx @@ -0,0 +1,136 @@ +import classNames from "classnames"; +import { useEffect, useRef, useState } from "react"; +import getCaretCoordinates from "textarea-caret"; +import OverflowTip from "@/components/kit/OverflowTip"; +import { useTagStore } from "@/store/module"; +import { EditorRefActions } from "."; + +type Props = { + editorRef: React.RefObject; + editorActions: React.ForwardedRef; +}; + +type Position = { left: number; top: number; height: number }; + +const TagSuggestions = ({ editorRef, editorActions }: Props) => { + const [position, setPosition] = useState(null); + const hide = () => setPosition(null); + + const { state } = useTagStore(); + const tagsRef = useRef(state.tags); + tagsRef.current = state.tags; + + const [selected, select] = useState(0); + const selectedRef = useRef(selected); + selectedRef.current = selected; + + const getCurrentWord = (): [word: string, startIndex: number] => { + const editor = editorRef.current; + if (!editor) return ["", 0]; + const cursorPos = editor.selectionEnd; + const before = editor.value.slice(0, cursorPos).match(/\S*$/) || { 0: "", index: cursorPos }; + const after = editor.value.slice(cursorPos).match(/^\S*/) || { 0: "" }; + return [before[0] + after[0], before.index ?? cursorPos]; + }; + + const suggestionsRef = useRef([]); + suggestionsRef.current = (() => { + const input = getCurrentWord()[0].slice(1).toLowerCase(); + + const customMatches = (tag: string, input: string) => { + const tagLowerCase = tag.toLowerCase(); + const inputLowerCase = input.toLowerCase(); + let inputIndex = 0; + + for (let i = 0; i < tagLowerCase.length; i++) { + if (tagLowerCase[i] === inputLowerCase[inputIndex]) { + inputIndex++; + if (inputIndex === inputLowerCase.length) { + return true; + } + } + } + + return false; + }; + + const matchedTags = tagsRef.current.filter((tag) => customMatches(tag, input)); + return matchedTags.slice(0, 5); + })(); + + const isVisibleRef = useRef(false); + isVisibleRef.current = !!(position && suggestionsRef.current.length > 0); + + const autocomplete = (tag: string) => { + if (!editorActions || !("current" in editorActions) || !editorActions.current) return; + const [word, index] = getCurrentWord(); + editorActions.current.removeText(index, word.length); + editorActions.current.insertText(`#${tag}`); + hide(); + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (!isVisibleRef.current) return; + const suggestions = suggestionsRef.current; + const selected = selectedRef.current; + if (["Escape", "ArrowLeft", "ArrowRight"].includes(e.code)) hide(); + if ("ArrowDown" === e.code) { + select((selected + 1) % suggestions.length); + e.preventDefault(); + e.stopPropagation(); + } + if ("ArrowUp" === e.code) { + select((selected - 1 + suggestions.length) % suggestions.length); + e.preventDefault(); + e.stopPropagation(); + } + if (["Enter", "Tab"].includes(e.code)) { + autocomplete(suggestions[selected]); + e.preventDefault(); + e.stopPropagation(); + } + }; + + const handleInput = () => { + if (!editorRef.current) return; + select(0); + const [word, index] = getCurrentWord(); + const isActive = word.startsWith("#") && !word.slice(1).includes("#"); + isActive ? setPosition(getCaretCoordinates(editorRef.current, index)) : hide(); + }; + + const listenersAreRegisteredRef = useRef(false); + const registerListeners = () => { + const editor = editorRef.current; + if (!editor || listenersAreRegisteredRef.current) return; + editor.addEventListener("click", hide); + editor.addEventListener("blur", hide); + editor.addEventListener("keydown", handleKeyDown); + editor.addEventListener("input", handleInput); + listenersAreRegisteredRef.current = true; + }; + useEffect(registerListeners, [!!editorRef.current]); + + if (!isVisibleRef.current || !position) return null; + return ( +
+ {suggestionsRef.current.map((tag, i) => ( +
autocomplete(tag)} + className={classNames( + "rounded p-1 px-2 w-full truncate text-sm dark:text-gray-300 cursor-pointer hover:bg-zinc-300 dark:hover:bg-zinc-700", + i === selected ? "bg-zinc-300 dark:bg-zinc-700" : "" + )} + > + #{tag} +
+ ))} +
+ ); +}; + +export default TagSuggestions; diff --git a/web/src/components/MemoEditorV1/Editor/index.tsx b/web/src/components/MemoEditorV1/Editor/index.tsx new file mode 100644 index 000000000..41fa11eb8 --- /dev/null +++ b/web/src/components/MemoEditorV1/Editor/index.tsx @@ -0,0 +1,162 @@ +import classNames from "classnames"; +import { forwardRef, ReactNode, useCallback, useEffect, useImperativeHandle, useRef } from "react"; +import TagSuggestions from "./TagSuggestions"; + +export interface EditorRefActions { + focus: FunctionType; + scrollToCursor: FunctionType; + insertText: (text: string, prefix?: string, suffix?: string) => void; + removeText: (start: number, length: number) => void; + setContent: (text: string) => void; + getContent: () => string; + getSelectedContent: () => string; + getCursorPosition: () => number; + setCursorPosition: (startPos: number, endPos?: number) => void; + getCursorLineNumber: () => number; + getLine: (lineNumber: number) => string; + setLine: (lineNumber: number, text: string) => void; +} + +interface Props { + className: string; + initialContent: string; + placeholder: string; + tools?: ReactNode; + onContentChange: (content: string) => void; + onPaste: (event: React.ClipboardEvent) => void; +} + +const Editor = forwardRef(function Editor(props: Props, ref: React.ForwardedRef) { + const { className, initialContent, placeholder, onPaste, onContentChange: handleContentChangeCallback } = props; + const editorRef = useRef(null); + + useEffect(() => { + if (editorRef.current && initialContent) { + editorRef.current.value = initialContent; + handleContentChangeCallback(initialContent); + } + }, []); + + useEffect(() => { + if (editorRef.current) { + updateEditorHeight(); + } + }, [editorRef.current?.value]); + + const updateEditorHeight = () => { + if (editorRef.current) { + editorRef.current.style.height = "auto"; + editorRef.current.style.height = (editorRef.current.scrollHeight ?? 0) + "px"; + } + }; + + useImperativeHandle( + ref, + () => ({ + focus: () => { + editorRef.current?.focus(); + }, + scrollToCursor: () => { + if (editorRef.current) { + editorRef.current.scrollTop = editorRef.current.scrollHeight; + } + }, + insertText: (content = "", prefix = "", suffix = "") => { + if (!editorRef.current) { + return; + } + + const cursorPosition = editorRef.current.selectionStart; + const endPosition = editorRef.current.selectionEnd; + const prevValue = editorRef.current.value; + const value = + prevValue.slice(0, cursorPosition) + + prefix + + (content || prevValue.slice(cursorPosition, endPosition)) + + suffix + + prevValue.slice(endPosition); + + editorRef.current.value = value; + editorRef.current.focus(); + editorRef.current.selectionEnd = endPosition + prefix.length + content.length; + handleContentChangeCallback(editorRef.current.value); + updateEditorHeight(); + }, + removeText: (start: number, length: number) => { + if (!editorRef.current) { + return; + } + + const prevValue = editorRef.current.value; + const value = prevValue.slice(0, start) + prevValue.slice(start + length); + editorRef.current.value = value; + editorRef.current.focus(); + editorRef.current.selectionEnd = start; + handleContentChangeCallback(editorRef.current.value); + updateEditorHeight(); + }, + setContent: (text: string) => { + if (editorRef.current) { + editorRef.current.value = text; + handleContentChangeCallback(editorRef.current.value); + updateEditorHeight(); + } + }, + getContent: (): string => { + return editorRef.current?.value ?? ""; + }, + getCursorPosition: (): number => { + return editorRef.current?.selectionStart ?? 0; + }, + getSelectedContent: () => { + const start = editorRef.current?.selectionStart; + const end = editorRef.current?.selectionEnd; + return editorRef.current?.value.slice(start, end) ?? ""; + }, + setCursorPosition: (startPos: number, endPos?: number) => { + const _endPos = isNaN(endPos as number) ? startPos : (endPos as number); + editorRef.current?.setSelectionRange(startPos, _endPos); + }, + getCursorLineNumber: () => { + const cursorPosition = editorRef.current?.selectionStart ?? 0; + const lines = editorRef.current?.value.slice(0, cursorPosition).split("\n") ?? []; + return lines.length - 1; + }, + getLine: (lineNumber: number) => { + return editorRef.current?.value.split("\n")[lineNumber] ?? ""; + }, + setLine: (lineNumber: number, text: string) => { + const lines = editorRef.current?.value.split("\n") ?? []; + lines[lineNumber] = text; + if (editorRef.current) { + editorRef.current.value = lines.join("\n"); + editorRef.current.focus(); + handleContentChangeCallback(editorRef.current.value); + updateEditorHeight(); + } + }, + }), + [] + ); + + const handleEditorInput = useCallback(() => { + handleContentChangeCallback(editorRef.current?.value ?? ""); + updateEditorHeight(); + }, []); + + return ( +
+ + +
+ ); +}); + +export default Editor; diff --git a/web/src/components/MemoEditorV1/MemoEditorDialog.tsx b/web/src/components/MemoEditorV1/MemoEditorDialog.tsx new file mode 100644 index 000000000..57e878436 --- /dev/null +++ b/web/src/components/MemoEditorV1/MemoEditorDialog.tsx @@ -0,0 +1,59 @@ +import { useEffect } from "react"; +import { useGlobalStore, useTagStore } from "@/store/module"; +import MemoEditor from "."; +import { generateDialog } from "../Dialog"; +import Icon from "../Icon"; + +interface Props extends DialogProps { + memoId?: MemoId; + relationList?: MemoRelation[]; +} + +const MemoEditorDialog: React.FC = ({ memoId, relationList, destroy }: Props) => { + const globalStore = useGlobalStore(); + const tagStore = useTagStore(); + const { systemStatus } = globalStore.state; + + useEffect(() => { + tagStore.fetchTags(); + }, []); + + const handleCloseBtnClick = () => { + destroy(); + }; + + return ( + <> +
+
+ +

{systemStatus.customizedProfile.name}

+
+ +
+
+ +
+ + ); +}; + +export default function showMemoEditorDialog(props: Pick = {}): void { + generateDialog( + { + className: "memo-editor-dialog", + dialogName: "memo-editor-dialog", + containerClassName: "dark:!bg-zinc-700", + }, + MemoEditorDialog, + props + ); +} diff --git a/web/src/components/MemoEditorV1/RelationListView.tsx b/web/src/components/MemoEditorV1/RelationListView.tsx new file mode 100644 index 000000000..8eb8e5c50 --- /dev/null +++ b/web/src/components/MemoEditorV1/RelationListView.tsx @@ -0,0 +1,56 @@ +import { useEffect, useState } from "react"; +import { useMemoCacheStore } from "@/store/v1"; +import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service"; +import Icon from "../Icon"; + +interface Props { + relationList: MemoRelation[]; + setRelationList: (relationList: MemoRelation[]) => void; +} + +const RelationListView = (props: Props) => { + const { relationList, setRelationList } = props; + const memoCacheStore = useMemoCacheStore(); + const [referencingMemoList, setReferencingMemoList] = useState([]); + + useEffect(() => { + (async () => { + const requests = relationList + .filter((relation) => relation.type === MemoRelation_Type.REFERENCE) + .map(async (relation) => { + return await memoCacheStore.getOrFetchMemoById(relation.relatedMemoId); + }); + const list = await Promise.all(requests); + setReferencingMemoList(list); + })(); + }, [relationList]); + + const handleDeleteRelation = async (memo: Memo) => { + setRelationList(relationList.filter((relation) => relation.relatedMemoId !== memo.id)); + }; + + return ( + <> + {referencingMemoList.length > 0 && ( +
+ {referencingMemoList.map((memo) => { + return ( +
handleDeleteRelation(memo)} + > + + #{memo.id} + {memo.content} + +
+ ); + })} +
+ )} + + ); +}; + +export default RelationListView; diff --git a/web/src/components/MemoEditorV1/ResourceListView.tsx b/web/src/components/MemoEditorV1/ResourceListView.tsx new file mode 100644 index 000000000..be9af0897 --- /dev/null +++ b/web/src/components/MemoEditorV1/ResourceListView.tsx @@ -0,0 +1,42 @@ +import { Resource } from "@/types/proto/api/v2/resource_service"; +import Icon from "../Icon"; +import ResourceIcon from "../ResourceIcon"; + +interface Props { + resourceList: Resource[]; + setResourceList: (resourceList: Resource[]) => void; +} + +const ResourceListView = (props: Props) => { + const { resourceList, setResourceList } = props; + + const handleDeleteResource = async (resourceId: ResourceId) => { + setResourceList(resourceList.filter((resource) => resource.id !== resourceId)); + }; + + return ( + <> + {resourceList.length > 0 && ( +
+ {resourceList.map((resource) => { + return ( +
+ + {resource.filename} + handleDeleteResource(resource.id)} + /> +
+ ); + })} +
+ )} + + ); +}; + +export default ResourceListView; diff --git a/web/src/components/MemoEditorV1/index.tsx b/web/src/components/MemoEditorV1/index.tsx new file mode 100644 index 000000000..61db7a452 --- /dev/null +++ b/web/src/components/MemoEditorV1/index.tsx @@ -0,0 +1,454 @@ +import { Select, Option, Button, IconButton, Divider } from "@mui/joy"; +import { uniqBy } from "lodash-es"; +import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { toast } from "react-hot-toast"; +import { useTranslation } from "react-i18next"; +import useLocalStorage from "react-use/lib/useLocalStorage"; +import { memoServiceClient } from "@/grpcweb"; +import { TAB_SPACE_WIDTH, UNKNOWN_ID } from "@/helpers/consts"; +import { useGlobalStore, useResourceStore } from "@/store/module"; +import { useMemoV1Store, useUserV1Store } from "@/store/v1"; +import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service"; +import { Visibility } from "@/types/proto/api/v2/memo_service"; +import { Resource } from "@/types/proto/api/v2/resource_service"; +import { UserSetting } from "@/types/proto/api/v2/user_service"; +import { useTranslate } from "@/utils/i18n"; +import { convertVisibilityFromString, convertVisibilityToString } from "@/utils/memo"; +import showCreateMemoRelationDialog from "../CreateMemoRelationDialog"; +import showCreateResourceDialog from "../CreateResourceDialog"; +import Icon from "../Icon"; +import VisibilityIconV1 from "../VisibilityIconV1"; +import TagSelector from "./ActionButton/TagSelector"; +import Editor, { EditorRefActions } from "./Editor"; +import RelationListView from "./RelationListView"; +import ResourceListView from "./ResourceListView"; + +interface Props { + className?: string; + editorClassName?: string; + cacheKey?: string; + memoId?: number; + relationList?: MemoRelation[]; + onConfirm?: (memoId: number) => void; +} + +interface State { + memoVisibility: Visibility; + resourceList: Resource[]; + relationList: MemoRelation[]; + isUploadingResource: boolean; + isRequesting: boolean; +} + +const MemoEditor = (props: Props) => { + const { className, editorClassName, cacheKey, memoId, onConfirm } = props; + const { i18n } = useTranslation(); + const t = useTranslate(); + const contentCacheKey = `memo-editor-${cacheKey}`; + const [contentCache, setContentCache] = useLocalStorage(contentCacheKey, ""); + const { + state: { systemStatus }, + } = useGlobalStore(); + const userV1Store = useUserV1Store(); + const memoStore = useMemoV1Store(); + const resourceStore = useResourceStore(); + const [state, setState] = useState({ + memoVisibility: Visibility.PRIVATE, + resourceList: [], + relationList: props.relationList ?? [], + isUploadingResource: false, + isRequesting: false, + }); + const [hasContent, setHasContent] = useState(false); + const editorRef = useRef(null); + const userSetting = userV1Store.userSetting as UserSetting; + const referenceRelations = memoId + ? state.relationList.filter( + (relation) => relation.memoId === memoId && relation.relatedMemoId !== memoId && relation.type === MemoRelation_Type.REFERENCE + ) + : state.relationList.filter((relation) => relation.type === MemoRelation_Type.REFERENCE); + + useEffect(() => { + editorRef.current?.setContent(contentCache || ""); + }, []); + + useEffect(() => { + let visibility = userSetting.memoVisibility; + if (systemStatus.disablePublicMemos && visibility === "PUBLIC") { + visibility = "PRIVATE"; + } + setState((prevState) => ({ + ...prevState, + memoVisibility: convertVisibilityFromString(visibility), + })); + }, [userSetting.memoVisibility, systemStatus.disablePublicMemos]); + + useEffect(() => { + if (memoId) { + memoStore.getOrFetchMemoById(memoId ?? UNKNOWN_ID).then((memo) => { + if (memo) { + handleEditorFocus(); + setState((prevState) => ({ + ...prevState, + memoVisibility: memo.visibility, + })); + if (!contentCache) { + editorRef.current?.setContent(memo.content ?? ""); + } + } + }); + } + }, [memoId]); + + const handleKeyDown = (event: React.KeyboardEvent) => { + if (!editorRef.current) { + return; + } + + const isMetaKey = event.ctrlKey || event.metaKey; + if (isMetaKey) { + if (event.key === "Enter") { + handleSaveBtnClick(); + return; + } + } + if (event.key === "Tab") { + event.preventDefault(); + const tabSpace = " ".repeat(TAB_SPACE_WIDTH); + const cursorPosition = editorRef.current.getCursorPosition(); + const selectedContent = editorRef.current.getSelectedContent(); + editorRef.current.insertText(tabSpace); + if (selectedContent) { + editorRef.current.setCursorPosition(cursorPosition + TAB_SPACE_WIDTH); + } + return; + } + }; + + const handleMemoVisibilityChange = (visibility: Visibility) => { + setState((prevState) => ({ + ...prevState, + memoVisibility: visibility, + })); + }; + + const handleUploadFileBtnClick = () => { + showCreateResourceDialog({ + onConfirm: (resourceList) => { + setState((prevState) => ({ + ...prevState, + resourceList: [...prevState.resourceList, ...resourceList], + })); + }, + }); + }; + + const handleAddMemoRelationBtnClick = () => { + showCreateMemoRelationDialog({ + onConfirm: (memoIdList) => { + setState((prevState) => ({ + ...prevState, + relationList: uniqBy( + [ + ...memoIdList.map((id) => ({ memoId: memoId || UNKNOWN_ID, relatedMemoId: id, type: MemoRelation_Type.REFERENCE })), + ...state.relationList, + ].filter((relation) => relation.relatedMemoId !== (memoId || UNKNOWN_ID)), + "relatedMemoId" + ), + })); + }, + }); + }; + + const handleSetResourceList = (resourceList: Resource[]) => { + setState((prevState) => ({ + ...prevState, + resourceList, + })); + }; + + const handleSetRelationList = (relationList: MemoRelation[]) => { + setState((prevState) => ({ + ...prevState, + relationList, + })); + }; + + const handleUploadResource = async (file: File) => { + setState((state) => { + return { + ...state, + isUploadingResource: true, + }; + }); + + let resource = undefined; + try { + resource = await resourceStore.createResourceWithBlob(file); + } catch (error: any) { + console.error(error); + toast.error(typeof error === "string" ? error : error.response.data.message); + } + + setState((state) => { + return { + ...state, + isUploadingResource: false, + }; + }); + return resource; + }; + + const uploadMultiFiles = async (files: FileList) => { + const uploadedResourceList: Resource[] = []; + for (const file of files) { + const resource = await handleUploadResource(file); + if (resource) { + uploadedResourceList.push(resource); + if (memoId) { + await resourceStore.updateResource({ + resource: Resource.fromPartial({ + id: resource.id, + memoId, + }), + updateMask: ["memo_id"], + }); + } + } + } + if (uploadedResourceList.length > 0) { + setState((prevState) => ({ + ...prevState, + resourceList: [...prevState.resourceList, ...uploadedResourceList], + })); + } + }; + + const handleDropEvent = async (event: React.DragEvent) => { + if (event.dataTransfer && event.dataTransfer.files.length > 0) { + event.preventDefault(); + await uploadMultiFiles(event.dataTransfer.files); + } + }; + + const handlePasteEvent = async (event: React.ClipboardEvent) => { + if (event.clipboardData && event.clipboardData.files.length > 0) { + event.preventDefault(); + await uploadMultiFiles(event.clipboardData.files); + } + }; + + const handleContentChange = (content: string) => { + setHasContent(content !== ""); + if (content !== "") { + setContentCache(content); + } else { + localStorage.removeItem(contentCacheKey); + } + }; + + const handleSaveBtnClick = async () => { + if (state.isRequesting) { + return; + } + + setState((state) => { + return { + ...state, + isRequesting: true, + }; + }); + const content = editorRef.current?.getContent() ?? ""; + try { + if (memoId && memoId !== UNKNOWN_ID) { + const prevMemo = await memoStore.getOrFetchMemoById(memoId ?? UNKNOWN_ID); + if (prevMemo) { + const memo = await memoStore.updateMemo( + { + id: prevMemo.id, + content, + visibility: state.memoVisibility, + }, + ["content", "visibility"] + ); + await memoServiceClient.setMemoResources({ + id: memo.id, + resources: state.resourceList, + }); + await memoServiceClient.setMemoRelations({ + id: memo.id, + relations: state.relationList, + }); + if (onConfirm) { + onConfirm(memo.id); + } + } + } else { + const memo = await memoStore.createMemo({ + content, + visibility: state.memoVisibility, + }); + await memoServiceClient.setMemoResources({ + id: memo.id, + resources: state.resourceList, + }); + await memoServiceClient.setMemoRelations({ + id: memo.id, + relations: state.relationList, + }); + if (onConfirm) { + onConfirm(memo.id); + } + } + editorRef.current?.setContent(""); + } catch (error: any) { + console.error(error); + toast.error(error.response.data.message); + } + setState((state) => { + return { + ...state, + isRequesting: false, + }; + }); + + setState((prevState) => ({ + ...prevState, + resourceList: [], + })); + }; + + const handleCheckBoxBtnClick = () => { + if (!editorRef.current) { + return; + } + const currentPosition = editorRef.current?.getCursorPosition(); + const currentLineNumber = editorRef.current?.getCursorLineNumber(); + const currentLine = editorRef.current?.getLine(currentLineNumber); + let newLine = ""; + let cursorChange = 0; + if (/^- \[( |x|X)\] /.test(currentLine)) { + newLine = currentLine.replace(/^- \[( |x|X)\] /, ""); + cursorChange = -6; + } else if (/^\d+\. |- /.test(currentLine)) { + const match = currentLine.match(/^\d+\. |- /) ?? [""]; + newLine = currentLine.replace(/^\d+\. |- /, "- [ ] "); + cursorChange = -match[0].length + 6; + } else { + newLine = "- [ ] " + currentLine; + cursorChange = 6; + } + editorRef.current?.setLine(currentLineNumber, newLine); + editorRef.current.setCursorPosition(currentPosition + cursorChange); + editorRef.current?.scrollToCursor(); + }; + + const handleCodeBlockBtnClick = () => { + if (!editorRef.current) { + return; + } + + const cursorPosition = editorRef.current.getCursorPosition(); + const prevValue = editorRef.current.getContent().slice(0, cursorPosition); + if (prevValue === "" || prevValue.endsWith("\n")) { + editorRef.current?.insertText("", "```\n", "\n```"); + } else { + editorRef.current?.insertText("", "\n```\n", "\n```"); + } + editorRef.current?.scrollToCursor(); + }; + + const handleTagSelectorClick = useCallback((tag: string) => { + editorRef.current?.insertText(`#${tag} `); + }, []); + + const handleEditorFocus = () => { + editorRef.current?.focus(); + }; + + const editorConfig = useMemo( + () => ({ + className: editorClassName ?? "", + initialContent: "", + placeholder: t("editor.placeholder"), + onContentChange: handleContentChange, + onPaste: handlePasteEvent, + }), + [i18n.language] + ); + + const allowSave = (hasContent || state.resourceList.length > 0) && !state.isUploadingResource && !state.isRequesting; + + return ( +
+ +
+
+ handleTagSelectorClick(tag)} /> + + + + + + + + + + + + +
+
+ + + +
+
e.stopPropagation()}> + +
+
+ +
+
+
+ ); +}; + +export default MemoEditor; diff --git a/web/src/components/MemoRelationListViewV1.tsx b/web/src/components/MemoRelationListViewV1.tsx new file mode 100644 index 000000000..0423c0570 --- /dev/null +++ b/web/src/components/MemoRelationListViewV1.tsx @@ -0,0 +1,83 @@ +import { Tooltip } from "@mui/joy"; +import { useEffect, useState } from "react"; +import { Link } from "react-router-dom"; +import { useMemoV1Store } from "@/store/v1"; +import { MemoRelation } from "@/types/proto/api/v2/memo_relation_service"; +import { Memo } from "@/types/proto/api/v2/memo_service"; +import Icon from "./Icon"; + +interface Props { + memo: Memo; + relationList: MemoRelation[]; +} + +const MemoRelationListViewV1 = (props: Props) => { + const { memo, relationList } = props; + const memoStore = useMemoV1Store(); + const [referencingMemoList, setReferencingMemoList] = useState([]); + const [referencedMemoList, setReferencedMemoList] = useState([]); + + useEffect(() => { + (async () => { + const referencingMemoList = await Promise.all( + relationList + .filter((relation) => relation.memoId === memo.id && relation.relatedMemoId !== memo.id) + .map((relation) => memoStore.getOrFetchMemoById(relation.relatedMemoId)) + ); + setReferencingMemoList(referencingMemoList); + const referencedMemoList = await Promise.all( + relationList + .filter((relation) => relation.memoId !== memo.id && relation.relatedMemoId === memo.id) + .map((relation) => memoStore.getOrFetchMemoById(relation.memoId)) + ); + setReferencedMemoList(referencedMemoList); + })(); + }, [memo, relationList]); + + return ( + <> + {referencingMemoList.length > 0 && ( +
+ {referencingMemoList.map((memo) => { + return ( +
+ + + + + #{memo.id} + {memo.content} + +
+ ); + })} +
+ )} + {referencedMemoList.length > 0 && ( +
+ {referencedMemoList.map((memo) => { + return ( +
+ + + + + #{memo.id} + {memo.content} + +
+ ); + })} +
+ )} + + ); +}; + +export default MemoRelationListViewV1; diff --git a/web/src/components/TimelineMemo.tsx b/web/src/components/TimelineMemo.tsx new file mode 100644 index 000000000..9e82ec1e9 --- /dev/null +++ b/web/src/components/TimelineMemo.tsx @@ -0,0 +1,45 @@ +import { useEffect, useState } from "react"; +import Icon from "@/components/Icon"; +import MemoContentV1 from "@/components/MemoContentV1"; +import MemoResourceListView from "@/components/MemoResourceListView"; +import { getTimeString } from "@/helpers/datetime"; +import { useMemoV1Store } from "@/store/v1"; +import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service"; +import { Memo } from "@/types/proto/api/v2/memo_service"; +import { Resource } from "@/types/proto/api/v2/resource_service"; +import MemoRelationListViewV1 from "./MemoRelationListViewV1"; + +interface Props { + memo: Memo; +} + +const TimelineMemo = (props: Props) => { + const { memo } = props; + const memoStore = useMemoV1Store(); + const [resources, setResources] = useState([]); + const [relations, setRelations] = useState([]); + + useEffect(() => { + memoStore.fetchMemoResources(memo.id).then((resources: Resource[]) => { + setResources(resources); + }); + memoStore.fetchMemoRelations(memo.id).then((relations: MemoRelation[]) => { + setRelations(relations.filter((relation) => relation.type === MemoRelation_Type.REFERENCE)); + }); + }, [memo.id]); + + return ( +
+
+ {getTimeString(memo.displayTime)} + + #{memo.id} +
+ + + +
+ ); +}; + +export default TimelineMemo; diff --git a/web/src/components/VisibilityIconV1.tsx b/web/src/components/VisibilityIconV1.tsx new file mode 100644 index 000000000..dfbd8a897 --- /dev/null +++ b/web/src/components/VisibilityIconV1.tsx @@ -0,0 +1,27 @@ +import classNames from "classnames"; +import { Visibility } from "@/types/proto/api/v2/memo_service"; +import Icon from "./Icon"; + +interface Props { + visibility: Visibility; +} + +const VisibilityIcon = (props: Props) => { + const { visibility } = props; + + let VIcon = null; + if (visibility === Visibility.PRIVATE) { + VIcon = Icon.Lock; + } else if (visibility === Visibility.PROTECTED) { + VIcon = Icon.Users; + } else if (visibility === Visibility.PUBLIC) { + VIcon = Icon.Globe2; + } + if (!VIcon) { + return null; + } + + return ; +}; + +export default VisibilityIcon; diff --git a/web/src/pages/Timeline.tsx b/web/src/pages/Timeline.tsx index 0e00e026a..dc3aea232 100644 --- a/web/src/pages/Timeline.tsx +++ b/web/src/pages/Timeline.tsx @@ -1,61 +1,42 @@ import { Button } from "@mui/joy"; -import { last } from "lodash-es"; import { useEffect, useState } from "react"; -import toast from "react-hot-toast"; import useToggle from "react-use/lib/useToggle"; import Empty from "@/components/Empty"; import Icon from "@/components/Icon"; -import MemoContentV1 from "@/components/MemoContentV1"; -import MemoEditor from "@/components/MemoEditor"; -import MemoRelationListView from "@/components/MemoRelationListView"; -import MemoResourceListView from "@/components/MemoResourceListView"; +import MemoEditorV1 from "@/components/MemoEditorV1"; import MobileHeader from "@/components/MobileHeader"; +import TimelineMemo from "@/components/TimelineMemo"; import DatePicker from "@/components/kit/DatePicker"; -import { DAILY_TIMESTAMP, DEFAULT_MEMO_LIMIT } from "@/helpers/consts"; -import { getDateStampByDate, getNormalizedDateString, getTimeStampByDate, getTimeString } from "@/helpers/datetime"; +import { DAILY_TIMESTAMP } from "@/helpers/consts"; +import { getDateStampByDate, getNormalizedDateString, getTimeStampByDate } from "@/helpers/datetime"; import useCurrentUser from "@/hooks/useCurrentUser"; -import { useMemoStore } from "@/store/module"; -import { extractUsernameFromName } from "@/store/v1"; +import { useMemoV1Store } from "@/store/v1"; +import { Memo } from "@/types/proto/api/v2/memo_service"; import { useTranslate } from "@/utils/i18n"; const Timeline = () => { const t = useTranslate(); - const memoStore = useMemoStore(); + const memoStore = useMemoV1Store(); const currentUser = useCurrentUser(); const currentDateStamp = getDateStampByDate(getNormalizedDateString()) as number; const [selectedDateStamp, setSelectedDateStamp] = useState(currentDateStamp as number); + const [memos, setMemos] = useState([]); const [showDatePicker, toggleShowDatePicker] = useToggle(false); - const dailyMemos = memoStore.state.memos - .filter((m) => { - const displayTimestamp = getTimeStampByDate(m.displayTs); - const selectedDateStampWithOffset = selectedDateStamp; - return ( - m.rowStatus === "NORMAL" && - m.creatorUsername === extractUsernameFromName(currentUser.name) && - displayTimestamp >= selectedDateStampWithOffset && - displayTimestamp < selectedDateStampWithOffset + DAILY_TIMESTAMP - ); - }) - .sort((a, b) => getTimeStampByDate(a.displayTs) - getTimeStampByDate(b.displayTs)); + const sortedMemos = memos.sort((a, b) => getTimeStampByDate(a.createTime) - getTimeStampByDate(b.createTime)); useEffect(() => { - let offset = 0; - const fetchMoreMemos = async () => { - try { - const fetchedMemos = await memoStore.fetchMemos("", DEFAULT_MEMO_LIMIT, offset); - offset += fetchedMemos.length; - if (fetchedMemos.length === DEFAULT_MEMO_LIMIT) { - const lastMemo = last(fetchedMemos); - if (lastMemo && lastMemo.displayTs > selectedDateStamp) { - await fetchMoreMemos(); - } - } - } catch (error: any) { - console.error(error); - toast.error(error.response.data.message); - } - }; - fetchMoreMemos(); + const filters = [ + `creator == "${currentUser.name}"`, + `created_ts_after == ${selectedDateStamp / 1000}`, + `created_ts_before == ${(selectedDateStamp + DAILY_TIMESTAMP) / 1000}`, + ]; + memoStore + .fetchMemos({ + filter: filters.join(" && "), + }) + .then((memos: Memo[]) => { + setMemos(memos); + }); }, [selectedDateStamp]); const handleDataPickerChange = (datestamp: number): void => { @@ -63,6 +44,12 @@ const Timeline = () => { toggleShowDatePicker(false); }; + const handleMemoCreate = async (id: number) => { + await memoStore.getOrFetchMemoById(id).then((memo: Memo) => { + setMemos([memo, ...memos]); + }); + }; + return (
@@ -96,28 +83,21 @@ const Timeline = () => { />
- {dailyMemos.length === 0 && ( + {sortedMemos.length === 0 && (

{t("message.no-data")}

)}
- {dailyMemos.map((memo, index) => ( + {sortedMemos.map((memo, index) => (
-
- {getTimeString(memo.displayTs)} - - #{memo.id} -
- - - relation.type === "REFERENCE")} /> +
- {index !== dailyMemos.length - 1 && ( + {index !== sortedMemos.length - 1 && (
)}
@@ -126,10 +106,9 @@ const Timeline = () => {
))} - {selectedDateStamp === currentDateStamp && (
- +
)}
diff --git a/web/src/store/v1/memo.ts b/web/src/store/v1/memo.ts index 35eeea28f..07a3fc642 100644 --- a/web/src/store/v1/memo.ts +++ b/web/src/store/v1/memo.ts @@ -1,11 +1,15 @@ import { create } from "zustand"; import { combine } from "zustand/middleware"; import { memoServiceClient } from "@/grpcweb"; -import { Memo } from "@/types/proto/api/v2/memo_service"; +import { CreateMemoRequest, ListMemosRequest, Memo } from "@/types/proto/api/v2/memo_service"; export const useMemoV1Store = create( combine({ memoById: new Map() }, (set, get) => ({ getState: () => get(), + fetchMemos: async (request: Partial) => { + const { memos } = await memoServiceClient.listMemos(request); + return memos; + }, getOrFetchMemoById: async (id: MemoId) => { const memo = get().memoById.get(id); if (memo) { @@ -29,6 +33,18 @@ export const useMemoV1Store = create( getMemoById: (id: number) => { return get().memoById.get(id); }, + createMemo: async (request: CreateMemoRequest) => { + const { memo } = await memoServiceClient.createMemo(request); + if (!memo) { + throw new Error("Memo not found"); + } + + set((state) => { + state.memoById.set(memo.id, memo); + return state; + }); + return memo; + }, updateMemo: async (update: Partial, updateMask: string[]) => { const { memo } = await memoServiceClient.updateMemo({ id: update.id!, @@ -55,5 +71,17 @@ export const useMemoV1Store = create( return state; }); }, + fetchMemoResources: async (id: number) => { + const { resources } = await memoServiceClient.listMemoResources({ + id, + }); + return resources; + }, + fetchMemoRelations: async (id: number) => { + const { relations } = await memoServiceClient.listMemoRelations({ + id, + }); + return relations; + }, })) ); diff --git a/web/src/utils/memo.ts b/web/src/utils/memo.ts new file mode 100644 index 000000000..532741586 --- /dev/null +++ b/web/src/utils/memo.ts @@ -0,0 +1,27 @@ +import { Visibility } from "@/types/proto/api/v2/memo_service"; + +export const convertVisibilityFromString = (visibility: string) => { + switch (visibility) { + case "PUBLIC": + return Visibility.PUBLIC; + case "PROTECTED": + return Visibility.PROTECTED; + case "PRIVATE": + return Visibility.PRIVATE; + default: + return Visibility.PUBLIC; + } +}; + +export const convertVisibilityToString = (visibility: Visibility) => { + switch (visibility) { + case Visibility.PUBLIC: + return "PUBLIC"; + case Visibility.PROTECTED: + return "PROTECTED"; + case Visibility.PRIVATE: + return "PRIVATE"; + default: + return "PRIVATE"; + } +};