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