chore: update memo relation definition

This commit is contained in:
Steven
2024-03-19 21:53:44 +08:00
parent 722e356044
commit ed89cb8310
13 changed files with 369 additions and 357 deletions

View File

@ -5,8 +5,13 @@ package memos.api.v2;
option go_package = "gen/api/v2"; option go_package = "gen/api/v2";
message MemoRelation { message MemoRelation {
int32 memo_id = 1; // The name of memo.
int32 related_memo_id = 2; // Format: "memos/{uid}"
string memo = 1;
// The name of related memo.
// Format: "memos/{uid}"
string related_memo = 2;
enum Type { enum Type {
TYPE_UNSPECIFIED = 0; TYPE_UNSPECIFIED = 0;

View File

@ -1226,8 +1226,8 @@ Used internally for obfuscating the page token.
| Field | Type | Label | Description | | Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- | | ----- | ---- | ----- | ----------- |
| memo_id | [int32](#int32) | | | | memo | [string](#string) | | The name of memo. Format: "memos/{uid}" |
| related_memo_id | [int32](#int32) | | | | related_memo | [string](#string) | | The name of related memo. Format: "memos/{uid}" |
| type | [MemoRelation.Type](#memos-api-v2-MemoRelation-Type) | | | | type | [MemoRelation.Type](#memos-api-v2-MemoRelation-Type) | | |

View File

@ -74,8 +74,12 @@ type MemoRelation struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
MemoId int32 `protobuf:"varint,1,opt,name=memo_id,json=memoId,proto3" json:"memo_id,omitempty"` // The name of memo.
RelatedMemoId int32 `protobuf:"varint,2,opt,name=related_memo_id,json=relatedMemoId,proto3" json:"related_memo_id,omitempty"` // Format: "memos/{uid}"
Memo string `protobuf:"bytes,1,opt,name=memo,proto3" json:"memo,omitempty"`
// The name of related memo.
// Format: "memos/{uid}"
RelatedMemo string `protobuf:"bytes,2,opt,name=related_memo,json=relatedMemo,proto3" json:"related_memo,omitempty"`
Type MemoRelation_Type `protobuf:"varint,3,opt,name=type,proto3,enum=memos.api.v2.MemoRelation_Type" json:"type,omitempty"` Type MemoRelation_Type `protobuf:"varint,3,opt,name=type,proto3,enum=memos.api.v2.MemoRelation_Type" json:"type,omitempty"`
} }
@ -111,18 +115,18 @@ func (*MemoRelation) Descriptor() ([]byte, []int) {
return file_api_v2_memo_relation_service_proto_rawDescGZIP(), []int{0} return file_api_v2_memo_relation_service_proto_rawDescGZIP(), []int{0}
} }
func (x *MemoRelation) GetMemoId() int32 { func (x *MemoRelation) GetMemo() string {
if x != nil { if x != nil {
return x.MemoId return x.Memo
} }
return 0 return ""
} }
func (x *MemoRelation) GetRelatedMemoId() int32 { func (x *MemoRelation) GetRelatedMemo() string {
if x != nil { if x != nil {
return x.RelatedMemoId return x.RelatedMemo
} }
return 0 return ""
} }
func (x *MemoRelation) GetType() MemoRelation_Type { func (x *MemoRelation) GetType() MemoRelation_Type {
@ -138,30 +142,30 @@ 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, 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, 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, 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, 0x76, 0x32, 0x22, 0xb4, 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, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28,
0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x09, 0x52, 0x04, 0x6d, 0x65, 0x6d, 0x6f, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x6c, 0x61, 0x74,
0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x69, 0x64, 0x18, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x6d, 0x6f, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79,
0x6d, 0x6f, 0x49, 0x64, 0x12, 0x33, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73,
0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61,
0x32, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22,
0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x38, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x38, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x65, 0x12, 0x14, 0x0a, 0x10, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a,
0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x52, 0x45, 0x46, 0x45, 0x52, 0x09, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07,
0x45, 0x4e, 0x43, 0x45, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x42, 0xb0, 0x01, 0x0a, 0x10, 0x63, 0x6f,
0x54, 0x10, 0x02, 0x42, 0xb0, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x18,
0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x32, 0x42, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76,
0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68,
0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f,
0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x32, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d,
0x3b, 0x61, 0x70, 0x69, 0x76, 0x32, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56,
0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x32, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32,
0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c,
0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x32, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65,
0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72,
0x70, 0x69, 0x3a, 0x3a, 0x56, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@ -143,6 +143,24 @@ UpdateInbox updates an inbox.
### /api/v2/{name_1} ### /api/v2/{name_1}
#### GET
##### Summary
GetMemo gets a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name_1 | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2GetMemoResponse](#v2getmemoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### DELETE #### DELETE
##### Summary ##### Summary
@ -223,26 +241,6 @@ CreateMemo creates a memo.
| 200 | A successful response. | [v2CreateMemoResponse](#v2creatememoresponse) | | 200 | A successful response. | [v2CreateMemoResponse](#v2creatememoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) | | default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/name/{name}
#### GET
##### Summary
GetMemoByName gets a memo by name.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2GetMemoByNameResponse](#v2getmemobynameresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/stats ### /api/v2/memos/stats
#### GET #### GET
@ -254,7 +252,7 @@ GetUserMemosStats gets stats of memos for a user.
| Name | Located in | Description | Required | Schema | | Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ | | ---- | ---------- | ----------- | -------- | ------ |
| name | query | name is the name of the user to get stats for. Format: users/{username} | No | string | | name | query | name is the name of the user to get stats for. Format: users/{uid} | No | string |
| timezone | query | timezone location Format: uses tz identifier https://en.wikipedia.org/wiki/List_of_tz_database_time_zones | No | string | | timezone | query | timezone location Format: uses tz identifier https://en.wikipedia.org/wiki/List_of_tz_database_time_zones | No | string |
| filter | query | Same as ListMemosRequest.filter | No | string | | filter | query | Same as ListMemosRequest.filter | No | string |
@ -265,246 +263,6 @@ GetUserMemosStats gets stats of memos for a user.
| 200 | A successful response. | [v2GetUserMemosStatsResponse](#v2getusermemosstatsresponse) | | 200 | A successful response. | [v2GetUserMemosStatsResponse](#v2getusermemosstatsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) | | default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{id}
#### GET
##### Summary
GetMemo gets a memo by id.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2GetMemoResponse](#v2getmemoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### DELETE
##### Summary
DeleteMemo deletes a memo by id.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2DeleteMemoResponse](#v2deletememoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{id}/comments
#### GET
##### Summary
ListMemoComments lists comments for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoCommentsResponse](#v2listmemocommentsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
CreateMemoComment creates a comment for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | id is the memo id to create comment for. | Yes | integer |
| create.content | query | | No | string |
| create.visibility | query | | No | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2CreateMemoCommentResponse](#v2creatememocommentresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{id}/reactions
#### GET
##### Summary
ListMemoReactions lists reactions for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoReactionsResponse](#v2listmemoreactionsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
UpsertMemoReaction upserts a reaction for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
| reaction.id | query | | No | integer |
| reaction.creator | query | The name of the creator. Format: users/{uid} | No | string |
| reaction.contentId | query | | No | string |
| reaction.reactionType | query | | No | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2UpsertMemoReactionResponse](#v2upsertmemoreactionresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{id}/reactions/{reactionId}
#### DELETE
##### Summary
DeleteMemoReaction deletes a reaction for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
| reactionId | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2DeleteMemoReactionResponse](#v2deletememoreactionresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{id}/relations
#### GET
##### Summary
ListMemoRelations lists relations for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoRelationsResponse](#v2listmemorelationsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
SetMemoRelations sets relations for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
| body | body | | Yes | [MemoServiceSetMemoRelationsBody](#memoservicesetmemorelationsbody) |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2SetMemoRelationsResponse](#v2setmemorelationsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{id}/resources
#### GET
##### Summary
ListMemoResources lists resources for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoResourcesResponse](#v2listmemoresourcesresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
SetMemoResources sets resources for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| id | path | | Yes | integer |
| body | body | | Yes | [MemoServiceSetMemoResourcesBody](#memoservicesetmemoresourcesbody) |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2SetMemoResourcesResponse](#v2setmemoresourcesresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos/{memo.id}
#### PATCH
##### Summary
UpdateMemo updates a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| memo.id | path | id is the system generated unique identifier. | Yes | integer |
| memo | body | | Yes | { **"name"**: string, **"rowStatus"**: [apiv2RowStatus](#apiv2rowstatus), **"creator"**: string, **"createTime"**: dateTime, **"updateTime"**: dateTime, **"displayTime"**: dateTime, **"content"**: string, **"visibility"**: [v2Visibility](#v2visibility), **"pinned"**: boolean, **"parentId"**: integer, **"resources"**: [ [v2Resource](#v2resource) ], **"relations"**: [ [v2MemoRelation](#v2memorelation) ], **"reactions"**: [ [apiv2Reaction](#apiv2reaction) ] } |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2UpdateMemoResponse](#v2updatememoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/memos:export ### /api/v2/memos:export
#### POST #### POST
@ -545,6 +303,266 @@ SearchMemosRequest searches memos.
| 200 | A successful response. | [v2SearchMemosResponse](#v2searchmemosresponse) | | 200 | A successful response. | [v2SearchMemosResponse](#v2searchmemosresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) | | default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{memo.name}
#### PATCH
##### Summary
UpdateMemo updates a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| memo.name | path | The name of the memo. Format: memos/{uid} | Yes | string |
| memo | body | | Yes | { **"resourceId"**: string, **"rowStatus"**: [apiv2RowStatus](#apiv2rowstatus), **"creator"**: string, **"createTime"**: dateTime, **"updateTime"**: dateTime, **"displayTime"**: dateTime, **"content"**: string, **"visibility"**: [v2Visibility](#v2visibility), **"pinned"**: boolean, **"parentId"**: integer, **"resources"**: [ [v2Resource](#v2resource) ], **"relations"**: [ [v2MemoRelation](#v2memorelation) ], **"reactions"**: [ [apiv2Reaction](#apiv2reaction) ] } |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2UpdateMemoResponse](#v2updatememoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name_1}
#### GET
##### Summary
GetMemo gets a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name_1 | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2GetMemoResponse](#v2getmemoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### DELETE
##### Summary
DeleteInbox deletes an inbox.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name_1 | path | The name of the inbox to delete. Format: inboxes/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2DeleteInboxResponse](#v2deleteinboxresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name_2}
#### DELETE
##### Summary
DeleteMemo deletes a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name_2 | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2DeleteMemoResponse](#v2deletememoresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name}/comments
#### GET
##### Summary
ListMemoComments lists comments for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoCommentsResponse](#v2listmemocommentsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
CreateMemoComment creates a comment for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
| comment.content | query | | No | string |
| comment.visibility | query | | No | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2CreateMemoCommentResponse](#v2creatememocommentresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name}/reactions
#### GET
##### Summary
ListMemoReactions lists reactions for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoReactionsResponse](#v2listmemoreactionsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
UpsertMemoReaction upserts a reaction for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
| reaction.id | query | | No | integer |
| reaction.creator | query | The name of the creator. Format: users/{uid} | No | string |
| reaction.contentId | query | | No | string |
| reaction.reactionType | query | | No | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2UpsertMemoReactionResponse](#v2upsertmemoreactionresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name}/reactions/{reactionId}
#### DELETE
##### Summary
DeleteMemoReaction deletes a reaction for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
| reactionId | path | | Yes | integer |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2DeleteMemoReactionResponse](#v2deletememoreactionresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name}/relations
#### GET
##### Summary
ListMemoRelations lists relations for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoRelationsResponse](#v2listmemorelationsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
SetMemoRelations sets relations for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
| body | body | | Yes | [MemoServiceSetMemoRelationsBody](#memoservicesetmemorelationsbody) |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2SetMemoRelationsResponse](#v2setmemorelationsresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
### /api/v2/{name}/resources
#### GET
##### Summary
ListMemoResources lists resources for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2ListMemoResourcesResponse](#v2listmemoresourcesresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
#### POST
##### Summary
SetMemoResources sets resources for a memo.
##### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| name | path | The name of the memo. Format: memos/{uid} | Yes | string |
| body | body | | Yes | [MemoServiceSetMemoResourcesBody](#memoservicesetmemoresourcesbody) |
##### Responses
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | A successful response. | [v2SetMemoResourcesResponse](#v2setmemoresourcesresponse) |
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
--- ---
## ResourceService ## ResourceService
@ -1439,12 +1457,6 @@ GetActivity returns the activity with the given id.
| ---- | ---- | ----------- | -------- | | ---- | ---- | ----------- | -------- |
| linkMetadata | [v2LinkMetadata](#v2linkmetadata) | | No | | linkMetadata | [v2LinkMetadata](#v2linkmetadata) | | No |
#### v2GetMemoByNameResponse
| Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- |
| memo | [v2Memo](#v2memo) | | No |
#### v2GetMemoResponse #### v2GetMemoResponse
| Name | Type | Description | Required | | Name | Type | Description | Required |
@ -1608,8 +1620,8 @@ GetActivity returns the activity with the given id.
| Name | Type | Description | Required | | Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- | | ---- | ---- | ----------- | -------- |
| id | integer | id is the system generated unique identifier. | No | | name | string | | No |
| name | string | name is the user provided name. | No | | resourceId | string | | No |
| rowStatus | [apiv2RowStatus](#apiv2rowstatus) | | No | | rowStatus | [apiv2RowStatus](#apiv2rowstatus) | | No |
| creator | string | | No | | creator | string | | No |
| createTime | dateTime | | No | | createTime | dateTime | | No |
@ -1627,8 +1639,8 @@ GetActivity returns the activity with the given id.
| Name | Type | Description | Required | | Name | Type | Description | Required |
| ---- | ---- | ----------- | -------- | | ---- | ---- | ----------- | -------- |
| memoId | integer | | No | | memo | string | | No |
| relatedMemoId | integer | | No | | relatedMemo | string | | No |
| type | [v2MemoRelationType](#v2memorelationtype) | | No | | type | [v2MemoRelationType](#v2memorelationtype) | | No |
#### v2MemoRelationType #### v2MemoRelationType

View File

@ -2130,12 +2130,16 @@ definitions:
v2MemoRelation: v2MemoRelation:
type: object type: object
properties: properties:
memoId: memo:
type: integer type: string
format: int32 title: |-
relatedMemoId: The name of memo.
type: integer Format: "memos/{uid}"
format: int32 relatedMemo:
type: string
title: |-
The name of related memo.
Format: "memos/{uid}"
type: type:
$ref: '#/definitions/v2MemoRelationType' $ref: '#/definitions/v2MemoRelationType'
v2MemoRelationType: v2MemoRelationType:

View File

@ -2,6 +2,7 @@ package v2
import ( import (
"context" "context"
"fmt"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
@ -26,7 +27,7 @@ func (s *APIV2Service) SetMemoRelations(ctx context.Context, request *apiv2pb.Se
for _, relation := range request.Relations { for _, relation := range request.Relations {
// Ignore reflexive relations. // Ignore reflexive relations.
if id == relation.RelatedMemoId { if request.Name == relation.RelatedMemo {
continue continue
} }
// Ignore comment relations as there's no need to update a comment's relation. // Ignore comment relations as there's no need to update a comment's relation.
@ -34,9 +35,13 @@ func (s *APIV2Service) SetMemoRelations(ctx context.Context, request *apiv2pb.Se
if relation.Type == apiv2pb.MemoRelation_COMMENT { if relation.Type == apiv2pb.MemoRelation_COMMENT {
continue continue
} }
relatedMemoID, err := ExtractMemoIDFromName(relation.RelatedMemo)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid related memo name: %v", err)
}
if _, err := s.Store.UpsertMemoRelation(ctx, &store.MemoRelation{ if _, err := s.Store.UpsertMemoRelation(ctx, &store.MemoRelation{
MemoID: id, MemoID: id,
RelatedMemoID: relation.RelatedMemoId, RelatedMemoID: relatedMemoID,
Type: convertMemoRelationTypeToStore(relation.Type), Type: convertMemoRelationTypeToStore(relation.Type),
}); err != nil { }); err != nil {
return nil, status.Errorf(codes.Internal, "failed to upsert memo relation") return nil, status.Errorf(codes.Internal, "failed to upsert memo relation")
@ -79,8 +84,8 @@ func (s *APIV2Service) ListMemoRelations(ctx context.Context, request *apiv2pb.L
func convertMemoRelationFromStore(memoRelation *store.MemoRelation) *apiv2pb.MemoRelation { func convertMemoRelationFromStore(memoRelation *store.MemoRelation) *apiv2pb.MemoRelation {
return &apiv2pb.MemoRelation{ return &apiv2pb.MemoRelation{
MemoId: memoRelation.MemoID, Memo: fmt.Sprintf("%s%d", MemoNamePrefix, memoRelation.MemoID),
RelatedMemoId: memoRelation.RelatedMemoID, RelatedMemo: fmt.Sprintf("%s%d", MemoNamePrefix, memoRelation.RelatedMemoID),
Type: convertMemoRelationTypeFromStore(memoRelation.Type), Type: convertMemoRelationTypeFromStore(memoRelation.Type),
} }
} }

View File

@ -883,17 +883,6 @@ func convertMemoToWebhookPayload(memo *apiv2pb.Memo) (*webhook.WebhookPayload, e
} }
return resources return resources
}(), }(),
RelationList: func() []*webhook.MemoRelation {
relations := []*webhook.MemoRelation{}
for _, relation := range memo.Relations {
relations = append(relations, &webhook.MemoRelation{
MemoID: relation.MemoId,
RelatedMemoID: relation.RelatedMemoId,
Type: relation.Type.String(),
})
}
return relations
}(),
}, },
}, nil }, nil
} }

View File

@ -5,7 +5,7 @@ import toast from "react-hot-toast";
import showCreateMemoRelationDialog from "@/components/CreateMemoRelationDialog"; import showCreateMemoRelationDialog from "@/components/CreateMemoRelationDialog";
import Icon from "@/components/Icon"; import Icon from "@/components/Icon";
import { UNKNOWN_ID } from "@/helpers/consts"; import { UNKNOWN_ID } from "@/helpers/consts";
import { extractMemoIdFromName } from "@/store/v1"; import { MemoNamePrefix } from "@/store/v1";
import { MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service"; import { MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service";
import { EditorRefActions } from "../Editor"; import { EditorRefActions } from "../Editor";
import { MemoEditorContext } from "../types"; import { MemoEditorContext } from "../types";
@ -47,12 +47,12 @@ const AddMemoRelationButton = (props: Props) => {
uniqBy( uniqBy(
[ [
...memos.map((memo) => ({ ...memos.map((memo) => ({
memoId: context.memoId || UNKNOWN_ID, memo: `${MemoNamePrefix}${context.memoId || UNKNOWN_ID}`,
relatedMemoId: extractMemoIdFromName(memo.name), relatedMemo: memo.name,
type: MemoRelation_Type.REFERENCE, type: MemoRelation_Type.REFERENCE,
})), })),
...context.relationList, ...context.relationList,
].filter((relation) => relation.relatedMemoId !== (context.memoId || UNKNOWN_ID)), ].filter((relation) => relation.relatedMemo !== `${MemoNamePrefix}${context.memoId || UNKNOWN_ID}`),
"relatedMemoId", "relatedMemoId",
), ),
); );

View File

@ -1,5 +1,5 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { MemoNamePrefix, extractMemoIdFromName, useMemoStore } from "@/store/v1"; import { useMemoStore } from "@/store/v1";
import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service"; import { MemoRelation, MemoRelation_Type } from "@/types/proto/api/v2/memo_relation_service";
import { Memo } from "@/types/proto/api/v2/memo_service"; import { Memo } from "@/types/proto/api/v2/memo_service";
import Icon from "../Icon"; import Icon from "../Icon";
@ -19,7 +19,7 @@ const RelationListView = (props: Props) => {
const requests = relationList const requests = relationList
.filter((relation) => relation.type === MemoRelation_Type.REFERENCE) .filter((relation) => relation.type === MemoRelation_Type.REFERENCE)
.map(async (relation) => { .map(async (relation) => {
return await memoStore.getOrFetchMemoByName(`${MemoNamePrefix}${relation.relatedMemoId}`, { skipStore: true }); return await memoStore.getOrFetchMemoByName(relation.relatedMemo, { skipStore: true });
}); });
const list = await Promise.all(requests); const list = await Promise.all(requests);
setReferencingMemoList(list); setReferencingMemoList(list);
@ -27,7 +27,7 @@ const RelationListView = (props: Props) => {
}, [relationList]); }, [relationList]);
const handleDeleteRelation = async (memo: Memo) => { const handleDeleteRelation = async (memo: Memo) => {
setRelationList(relationList.filter((relation) => relation.relatedMemoId !== extractMemoIdFromName(memo.name))); setRelationList(relationList.filter((relation) => relation.relatedMemo !== memo.name));
}; };
return ( return (

View File

@ -75,7 +75,10 @@ const MemoEditor = (props: Props) => {
const [contentCache, setContentCache] = useLocalStorage<string>(contentCacheKey, ""); const [contentCache, setContentCache] = useLocalStorage<string>(contentCacheKey, "");
const referenceRelations = memoId const referenceRelations = memoId
? state.relationList.filter( ? state.relationList.filter(
(relation) => relation.memoId === memoId && relation.relatedMemoId !== memoId && relation.type === MemoRelation_Type.REFERENCE, (relation) =>
extractMemoIdFromName(relation.memo) === memoId &&
extractMemoIdFromName(relation.relatedMemo) !== memoId &&
relation.type === MemoRelation_Type.REFERENCE,
) )
: state.relationList.filter((relation) => relation.type === MemoRelation_Type.REFERENCE); : state.relationList.filter((relation) => relation.type === MemoRelation_Type.REFERENCE);

View File

@ -1,7 +1,7 @@
import { Tooltip } from "@mui/joy"; import { Tooltip } from "@mui/joy";
import { memo, useEffect, useState } from "react"; import { memo, useEffect, useState } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { MemoNamePrefix, extractMemoIdFromName, useMemoStore } from "@/store/v1"; import { useMemoStore } from "@/store/v1";
import { MemoRelation } from "@/types/proto/api/v2/memo_relation_service"; import { MemoRelation } from "@/types/proto/api/v2/memo_relation_service";
import { Memo } from "@/types/proto/api/v2/memo_service"; import { Memo } from "@/types/proto/api/v2/memo_service";
import Icon from "./Icon"; import Icon from "./Icon";
@ -21,20 +21,14 @@ const MemoRelationListView = (props: Props) => {
(async () => { (async () => {
const referencingMemoList = await Promise.all( const referencingMemoList = await Promise.all(
relationList relationList
.filter( .filter((relation) => relation.memo === memo.name && relation.relatedMemo !== memo.name)
(relation) => .map((relation) => memoStore.getOrFetchMemoByName(relation.relatedMemo, { skipStore: true })),
relation.memoId === extractMemoIdFromName(memo.name) && relation.relatedMemoId !== extractMemoIdFromName(memo.name),
)
.map((relation) => memoStore.getOrFetchMemoByName(`${MemoNamePrefix}${relation.relatedMemoId}`, { skipStore: true })),
); );
setReferencingMemoList(referencingMemoList); setReferencingMemoList(referencingMemoList);
const referencedMemoList = await Promise.all( const referencedMemoList = await Promise.all(
relationList relationList
.filter( .filter((relation) => relation.memo !== memo.name && relation.relatedMemo === memo.name)
(relation) => .map((relation) => memoStore.getOrFetchMemoByName(relation.memo, { skipStore: true })),
relation.memoId !== extractMemoIdFromName(memo.name) && relation.relatedMemoId === extractMemoIdFromName(memo.name),
)
.map((relation) => memoStore.getOrFetchMemoByName(`${MemoNamePrefix}${relation.memoId}`, { skipStore: true })),
); );
setReferencedMemoList(referencedMemoList); setReferencedMemoList(referencedMemoList);
})(); })();

View File

@ -41,7 +41,7 @@ const MemoView: React.FC<Props> = (props: Props) => {
const memoContainerRef = useRef<HTMLDivElement>(null); const memoContainerRef = useRef<HTMLDivElement>(null);
const referencedMemos = memo.relations.filter((relation) => relation.type === MemoRelation_Type.REFERENCE); const referencedMemos = memo.relations.filter((relation) => relation.type === MemoRelation_Type.REFERENCE);
const commentAmount = memo.relations.filter( const commentAmount = memo.relations.filter(
(relation) => relation.type === MemoRelation_Type.COMMENT && relation.relatedMemoId === extractMemoIdFromName(memo.name), (relation) => relation.type === MemoRelation_Type.COMMENT && relation.relatedMemo === memo.name,
).length; ).length;
const readonly = memo.creator !== user?.name; const readonly = memo.creator !== user?.name;
const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.name}`); const isInMemoDetailPage = location.pathname.startsWith(`/m/${memo.name}`);

View File

@ -23,12 +23,8 @@ const MemoDetail = () => {
const memo = memoStore.getMemoByResourceId(resourceId || ""); const memo = memoStore.getMemoByResourceId(resourceId || "");
const [parentMemo, setParentMemo] = useState<Memo | undefined>(undefined); const [parentMemo, setParentMemo] = useState<Memo | undefined>(undefined);
const commentRelations = const commentRelations =
memo?.relations.filter( memo?.relations.filter((relation) => relation.relatedMemo === memo.name && relation.type === MemoRelation_Type.COMMENT) || [];
(relation) => relation.relatedMemoId === extractMemoIdFromName(memo.name) && relation.type === MemoRelation_Type.COMMENT, const comments = commentRelations.map((relation) => memoStore.getMemoByName(relation.memo)).filter((memo) => memo) as any as Memo[];
) || [];
const comments = commentRelations
.map((relation) => memoStore.getMemoByName(`${MemoNamePrefix}${relation.memoId}`))
.filter((memo) => memo) as any as Memo[];
// Prepare memo. // Prepare memo.
useEffect(() => { useEffect(() => {
@ -56,7 +52,7 @@ const MemoDetail = () => {
} else { } else {
setParentMemo(undefined); setParentMemo(undefined);
} }
await Promise.all(commentRelations.map((relation) => memoStore.getOrFetchMemoByName(`${MemoNamePrefix}${relation.memoId}`))); await Promise.all(commentRelations.map((relation) => memoStore.getOrFetchMemoByName(relation.memo)));
})(); })();
}, [memo]); }, [memo]);