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
1f0bfd21
Commit
1f0bfd21
authored
Apr 14, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update tag store
parent
4aa72306
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
167 additions
and
259 deletions
+167
-259
tag_service.proto
proto/api/v2/tag_service.proto
+1
-5
README.md
proto/gen/api/v2/README.md
+0
-5
tag_service.pb.go
proto/gen/api/v2/tag_service.pb.go
+78
-91
tag_service.pb.gw.go
proto/gen/api/v2/tag_service.pb.gw.go
+0
-18
apidocs.swagger.yaml
server/route/api/v2/apidocs.swagger.yaml
+0
-8
tag_service.go
server/route/api/v2/tag_service.go
+8
-4
CreateTagDialog.tsx
web/src/components/CreateTagDialog.tsx
+4
-4
TagsSection.tsx
web/src/components/HomeSidebar/TagsSection.tsx
+11
-6
TagSelector.tsx
web/src/components/MemoEditor/ActionButton/TagSelector.tsx
+4
-4
TagSuggestions.tsx
web/src/components/MemoEditor/Editor/TagSuggestions.tsx
+6
-6
MemoEditorDialog.tsx
web/src/components/MemoEditor/MemoEditorDialog.tsx
+1
-1
index.tsx
web/src/components/MemoEditor/index.tsx
+1
-2
UserStatisticsView.tsx
web/src/components/UserStatisticsView.tsx
+2
-3
index.ts
web/src/store/index.ts
+0
-2
index.ts
web/src/store/module/index.ts
+0
-1
tag.ts
web/src/store/module/tag.ts
+0
-57
tag.ts
web/src/store/reducer/tag.ts
+0
-42
index.ts
web/src/store/v1/index.ts
+1
-0
tag.ts
web/src/store/v1/tag.ts
+49
-0
user.ts
web/src/store/v1/user.ts
+1
-0
No files found.
proto/api/v2/tag_service.proto
View file @
1f0bfd21
...
@@ -55,11 +55,7 @@ message BatchUpsertTagRequest {
...
@@ -55,11 +55,7 @@ message BatchUpsertTagRequest {
message
BatchUpsertTagResponse
{}
message
BatchUpsertTagResponse
{}
message
ListTagsRequest
{
message
ListTagsRequest
{}
// The creator of tags.
// Format: users/{id}
string
user
=
1
;
}
message
ListTagsResponse
{
message
ListTagsResponse
{
repeated
Tag
tags
=
1
;
repeated
Tag
tags
=
1
;
...
...
proto/gen/api/v2/README.md
View file @
1f0bfd21
...
@@ -2772,11 +2772,6 @@ Used internally for obfuscating the page token.
...
@@ -2772,11 +2772,6 @@ Used internally for obfuscating the page token.
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| user |
[
string
](
#string
)
| | The creator of tags. Format: users/{id} |
...
...
proto/gen/api/v2/tag_service.pb.go
View file @
1f0bfd21
This diff is collapsed.
Click to expand it.
proto/gen/api/v2/tag_service.pb.gw.go
View file @
1f0bfd21
...
@@ -103,21 +103,10 @@ func local_request_TagService_BatchUpsertTag_0(ctx context.Context, marshaler ru
...
@@ -103,21 +103,10 @@ func local_request_TagService_BatchUpsertTag_0(ctx context.Context, marshaler ru
}
}
var
(
filter_TagService_ListTags_0
=
&
utilities
.
DoubleArray
{
Encoding
:
map
[
string
]
int
{},
Base
:
[]
int
(
nil
),
Check
:
[]
int
(
nil
)}
)
func
request_TagService_ListTags_0
(
ctx
context
.
Context
,
marshaler
runtime
.
Marshaler
,
client
TagServiceClient
,
req
*
http
.
Request
,
pathParams
map
[
string
]
string
)
(
proto
.
Message
,
runtime
.
ServerMetadata
,
error
)
{
func
request_TagService_ListTags_0
(
ctx
context
.
Context
,
marshaler
runtime
.
Marshaler
,
client
TagServiceClient
,
req
*
http
.
Request
,
pathParams
map
[
string
]
string
)
(
proto
.
Message
,
runtime
.
ServerMetadata
,
error
)
{
var
protoReq
ListTagsRequest
var
protoReq
ListTagsRequest
var
metadata
runtime
.
ServerMetadata
var
metadata
runtime
.
ServerMetadata
if
err
:=
req
.
ParseForm
();
err
!=
nil
{
return
nil
,
metadata
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"%v"
,
err
)
}
if
err
:=
runtime
.
PopulateQueryParameters
(
&
protoReq
,
req
.
Form
,
filter_TagService_ListTags_0
);
err
!=
nil
{
return
nil
,
metadata
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"%v"
,
err
)
}
msg
,
err
:=
client
.
ListTags
(
ctx
,
&
protoReq
,
grpc
.
Header
(
&
metadata
.
HeaderMD
),
grpc
.
Trailer
(
&
metadata
.
TrailerMD
))
msg
,
err
:=
client
.
ListTags
(
ctx
,
&
protoReq
,
grpc
.
Header
(
&
metadata
.
HeaderMD
),
grpc
.
Trailer
(
&
metadata
.
TrailerMD
))
return
msg
,
metadata
,
err
return
msg
,
metadata
,
err
...
@@ -127,13 +116,6 @@ func local_request_TagService_ListTags_0(ctx context.Context, marshaler runtime.
...
@@ -127,13 +116,6 @@ func local_request_TagService_ListTags_0(ctx context.Context, marshaler runtime.
var
protoReq
ListTagsRequest
var
protoReq
ListTagsRequest
var
metadata
runtime
.
ServerMetadata
var
metadata
runtime
.
ServerMetadata
if
err
:=
req
.
ParseForm
();
err
!=
nil
{
return
nil
,
metadata
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"%v"
,
err
)
}
if
err
:=
runtime
.
PopulateQueryParameters
(
&
protoReq
,
req
.
Form
,
filter_TagService_ListTags_0
);
err
!=
nil
{
return
nil
,
metadata
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"%v"
,
err
)
}
msg
,
err
:=
server
.
ListTags
(
ctx
,
&
protoReq
)
msg
,
err
:=
server
.
ListTags
(
ctx
,
&
protoReq
)
return
msg
,
metadata
,
err
return
msg
,
metadata
,
err
...
...
server/route/api/v2/apidocs.swagger.yaml
View file @
1f0bfd21
...
@@ -638,14 +638,6 @@ paths:
...
@@ -638,14 +638,6 @@ paths:
description
:
An unexpected error response.
description
:
An unexpected error response.
schema
:
schema
:
$ref
:
'
#/definitions/googlerpcStatus'
$ref
:
'
#/definitions/googlerpcStatus'
parameters
:
-
name
:
user
description
:
|-
The creator of tags.
Format: users/{id}
in: query
required: false
type: string
tags
:
tags
:
-
TagService
-
TagService
delete
:
delete
:
...
...
server/route/api/v2/tag_service.go
View file @
1f0bfd21
...
@@ -51,12 +51,16 @@ func (s *APIV2Service) BatchUpsertTag(ctx context.Context, request *apiv2pb.Batc
...
@@ -51,12 +51,16 @@ func (s *APIV2Service) BatchUpsertTag(ctx context.Context, request *apiv2pb.Batc
}
}
func
(
s
*
APIV2Service
)
ListTags
(
ctx
context
.
Context
,
request
*
apiv2pb
.
ListTagsRequest
)
(
*
apiv2pb
.
ListTagsResponse
,
error
)
{
func
(
s
*
APIV2Service
)
ListTags
(
ctx
context
.
Context
,
request
*
apiv2pb
.
ListTagsRequest
)
(
*
apiv2pb
.
ListTagsResponse
,
error
)
{
tagFind
:=
&
store
.
FindTag
{}
user
,
err
:=
getCurrentUser
(
ctx
,
s
.
Store
)
userID
,
err
:=
ExtractUserIDFromName
(
request
.
User
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid user name: %v"
,
err
)
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to get user"
)
}
if
user
==
nil
{
return
nil
,
status
.
Errorf
(
codes
.
PermissionDenied
,
"permission denied"
)
}
tagFind
:=
&
store
.
FindTag
{
CreatorID
:
user
.
ID
,
}
}
tagFind
.
CreatorID
=
userID
tags
,
err
:=
s
.
Store
.
ListTags
(
ctx
,
tagFind
)
tags
,
err
:=
s
.
Store
.
ListTags
(
ctx
,
tagFind
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to list tags: %v"
,
err
)
return
nil
,
status
.
Errorf
(
codes
.
Internal
,
"failed to list tags: %v"
,
err
)
...
...
web/src/components/CreateTagDialog.tsx
View file @
1f0bfd21
...
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from "react";
...
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from "react";
import
{
toast
}
from
"react-hot-toast"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
tagServiceClient
}
from
"@/grpcweb"
;
import
{
tagServiceClient
}
from
"@/grpcweb"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useTagStore
}
from
"@/store/
module
"
;
import
{
useTagStore
}
from
"@/store/
v1
"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
TAG_REG
}
from
"@/utils/tag"
;
import
{
TAG_REG
}
from
"@/utils/tag"
;
import
{
generateDialog
}
from
"./Dialog"
;
import
{
generateDialog
}
from
"./Dialog"
;
...
@@ -28,8 +28,8 @@ const CreateTagDialog: React.FC<Props> = (props: Props) => {
...
@@ -28,8 +28,8 @@ const CreateTagDialog: React.FC<Props> = (props: Props) => {
const
[
tagName
,
setTagName
]
=
useState
<
string
>
(
""
);
const
[
tagName
,
setTagName
]
=
useState
<
string
>
(
""
);
const
[
suggestTagNameList
,
setSuggestTagNameList
]
=
useState
<
string
[]
>
([]);
const
[
suggestTagNameList
,
setSuggestTagNameList
]
=
useState
<
string
[]
>
([]);
const
[
showTagSuggestions
,
setShowTagSuggestions
]
=
useState
<
boolean
>
(
false
);
const
[
showTagSuggestions
,
setShowTagSuggestions
]
=
useState
<
boolean
>
(
false
);
const
tagNameList
=
tagStore
.
state
.
tags
;
const
tagNameList
=
tagStore
.
getState
()
.
tags
;
const
shownSuggestTagNameList
=
suggestTagNameList
.
filter
((
tag
)
=>
!
tagNameList
.
include
s
(
tag
));
const
shownSuggestTagNameList
=
suggestTagNameList
.
filter
((
tag
)
=>
!
tagNameList
.
ha
s
(
tag
));
useEffect
(()
=>
{
useEffect
(()
=>
{
tagServiceClient
tagServiceClient
...
@@ -107,7 +107,7 @@ const CreateTagDialog: React.FC<Props> = (props: Props) => {
...
@@ -107,7 +107,7 @@ const CreateTagDialog: React.FC<Props> = (props: Props) => {
startDecorator=
{
<
Icon
.
Hash
className=
"w-4 h-auto"
/>
}
startDecorator=
{
<
Icon
.
Hash
className=
"w-4 h-auto"
/>
}
endDecorator=
{
<
Icon
.
Check
onClick=
{
handleSaveBtnClick
}
className=
"w-4 h-auto cursor-pointer hover:opacity-80"
/>
}
endDecorator=
{
<
Icon
.
Check
onClick=
{
handleSaveBtnClick
}
className=
"w-4 h-auto cursor-pointer hover:opacity-80"
/>
}
/>
/>
{
tagNameList
.
length
>
0
&&
(
{
tagNameList
.
size
>
0
&&
(
<>
<>
<
p
className=
"w-full mt-2 mb-1 text-sm text-gray-400"
>
{
t
(
"tag.all-tags"
)
}
</
p
>
<
p
className=
"w-full mt-2 mb-1 text-sm text-gray-400"
>
{
t
(
"tag.all-tags"
)
}
</
p
>
<
div
className=
"w-full flex flex-row justify-start items-start flex-wrap"
>
<
div
className=
"w-full flex flex-row justify-start items-start flex-wrap"
>
...
...
web/src/components/HomeSidebar/TagsSection.tsx
View file @
1f0bfd21
import
{
Dropdown
,
Menu
,
MenuButton
,
MenuItem
}
from
"@mui/joy"
;
import
{
Dropdown
,
Menu
,
MenuButton
,
MenuItem
}
from
"@mui/joy"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
useDebounce
from
"react-use/lib/useDebounce"
;
import
useToggle
from
"react-use/lib/useToggle"
;
import
useToggle
from
"react-use/lib/useToggle"
;
import
{
useFilterStore
,
useTagStore
}
from
"@/store/module"
;
import
{
useFilterStore
}
from
"@/store/module"
;
import
{
useMemoList
}
from
"@/store/v1"
;
import
{
useMemoList
,
useTagStore
}
from
"@/store/v1"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
showCreateTagDialog
from
"../CreateTagDialog"
;
import
showCreateTagDialog
from
"../CreateTagDialog"
;
import
{
showCommonDialog
}
from
"../Dialog/CommonDialog"
;
import
{
showCommonDialog
}
from
"../Dialog/CommonDialog"
;
...
@@ -24,13 +25,17 @@ const TagsSection = () => {
...
@@ -24,13 +25,17 @@ const TagsSection = () => {
const
filterStore
=
useFilterStore
();
const
filterStore
=
useFilterStore
();
const
tagStore
=
useTagStore
();
const
tagStore
=
useTagStore
();
const
memoList
=
useMemoList
();
const
memoList
=
useMemoList
();
const
tagsText
=
tagStore
.
state
.
tags
;
const
tagsText
=
tagStore
.
getState
()
.
tags
;
const
filter
=
filterStore
.
state
;
const
filter
=
filterStore
.
state
;
const
[
tags
,
setTags
]
=
useState
<
Tag
[]
>
([]);
const
[
tags
,
setTags
]
=
useState
<
Tag
[]
>
([]);
useEffect
(()
=>
{
useDebounce
(
tagStore
.
fetchTags
();
()
=>
{
},
[
memoList
.
size
()]);
tagStore
.
fetchTags
();
},
300
,
[
memoList
.
size
()],
);
useEffect
(()
=>
{
useEffect
(()
=>
{
const
sortedTags
=
Array
.
from
(
tagsText
).
sort
();
const
sortedTags
=
Array
.
from
(
tagsText
).
sort
();
...
...
web/src/components/MemoEditor/ActionButton/TagSelector.tsx
View file @
1f0bfd21
...
@@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
...
@@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
import
useClickAway
from
"react-use/lib/useClickAway"
;
import
useClickAway
from
"react-use/lib/useClickAway"
;
import
Icon
from
"@/components/Icon"
;
import
Icon
from
"@/components/Icon"
;
import
OverflowTip
from
"@/components/kit/OverflowTip"
;
import
OverflowTip
from
"@/components/kit/OverflowTip"
;
import
{
useTagStore
}
from
"@/store/
module
"
;
import
{
useTagStore
}
from
"@/store/
v1
"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
EditorRefActions
}
from
"../Editor"
;
import
{
EditorRefActions
}
from
"../Editor"
;
...
@@ -17,7 +17,7 @@ const TagSelector = (props: Props) => {
...
@@ -17,7 +17,7 @@ const TagSelector = (props: Props) => {
const
tagStore
=
useTagStore
();
const
tagStore
=
useTagStore
();
const
[
open
,
setOpen
]
=
useState
(
false
);
const
[
open
,
setOpen
]
=
useState
(
false
);
const
containerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
containerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
tags
=
tagStore
.
state
.
tags
;
const
tags
=
tagStore
.
getState
()
.
tags
;
useEffect
(()
=>
{
useEffect
(()
=>
{
(
async
()
=>
{
(
async
()
=>
{
...
@@ -60,9 +60,9 @@ const TagSelector = (props: Props) => {
...
@@ -60,9 +60,9 @@ const TagSelector = (props: Props) => {
</
MenuButton
>
</
MenuButton
>
<
Menu
className=
"relative text-sm"
component=
"div"
size=
"sm"
placement=
"bottom-start"
>
<
Menu
className=
"relative text-sm"
component=
"div"
size=
"sm"
placement=
"bottom-start"
>
<
div
ref=
{
containerRef
}
>
<
div
ref=
{
containerRef
}
>
{
tags
.
length
>
0
?
(
{
tags
.
size
>
0
?
(
<
div
className=
"flex-row justify-start items-start flex-wrap px-1 max-w-[12rem] h-auto max-h-48 overflow-y-auto font-mono"
>
<
div
className=
"flex-row justify-start items-start flex-wrap px-1 max-w-[12rem] h-auto max-h-48 overflow-y-auto font-mono"
>
{
tags
.
map
((
tag
)
=>
{
{
Array
.
from
(
tags
)
.
map
((
tag
)
=>
{
return
(
return
(
<
div
<
div
key=
{
tag
}
key=
{
tag
}
...
...
web/src/components/MemoEditor/Editor/TagSuggestions.tsx
View file @
1f0bfd21
...
@@ -3,7 +3,7 @@ import Fuse from "fuse.js";
...
@@ -3,7 +3,7 @@ import Fuse from "fuse.js";
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
import
getCaretCoordinates
from
"textarea-caret"
;
import
getCaretCoordinates
from
"textarea-caret"
;
import
OverflowTip
from
"@/components/kit/OverflowTip"
;
import
OverflowTip
from
"@/components/kit/OverflowTip"
;
import
{
useTagStore
}
from
"@/store/
module
"
;
import
{
useTagStore
}
from
"@/store/
v1
"
;
import
{
EditorRefActions
}
from
"."
;
import
{
EditorRefActions
}
from
"."
;
type
Props
=
{
type
Props
=
{
...
@@ -15,16 +15,16 @@ type Position = { left: number; top: number; height: number };
...
@@ -15,16 +15,16 @@ type Position = { left: number; top: number; height: number };
const
TagSuggestions
=
({
editorRef
,
editorActions
}:
Props
)
=>
{
const
TagSuggestions
=
({
editorRef
,
editorActions
}:
Props
)
=>
{
const
[
position
,
setPosition
]
=
useState
<
Position
|
null
>
(
null
);
const
[
position
,
setPosition
]
=
useState
<
Position
|
null
>
(
null
);
const
hide
=
()
=>
setPosition
(
null
);
const
tagStore
=
useTagStore
();
const
tagsRef
=
useRef
(
Array
.
from
(
tagStore
.
getState
().
tags
));
const
{
state
}
=
useTagStore
();
tagsRef
.
current
=
Array
.
from
(
tagStore
.
getState
().
tags
);
const
tagsRef
=
useRef
(
state
.
tags
);
tagsRef
.
current
=
state
.
tags
;
const
[
selected
,
select
]
=
useState
(
0
);
const
[
selected
,
select
]
=
useState
(
0
);
const
selectedRef
=
useRef
(
selected
);
const
selectedRef
=
useRef
(
selected
);
selectedRef
.
current
=
selected
;
selectedRef
.
current
=
selected
;
const
hide
=
()
=>
setPosition
(
null
);
const
getCurrentWord
=
():
[
word
:
string
,
startIndex
:
number
]
=>
{
const
getCurrentWord
=
():
[
word
:
string
,
startIndex
:
number
]
=>
{
const
editor
=
editorRef
.
current
;
const
editor
=
editorRef
.
current
;
if
(
!
editor
)
return
[
""
,
0
];
if
(
!
editor
)
return
[
""
,
0
];
...
...
web/src/components/MemoEditor/MemoEditorDialog.tsx
View file @
1f0bfd21
import
{
IconButton
}
from
"@mui/joy"
;
import
{
IconButton
}
from
"@mui/joy"
;
import
{
useEffect
}
from
"react"
;
import
{
useEffect
}
from
"react"
;
import
{
useTagStore
}
from
"@/store/
module
"
;
import
{
useTagStore
}
from
"@/store/
v1
"
;
import
{
MemoRelation
}
from
"@/types/proto/api/v2/memo_relation_service"
;
import
{
MemoRelation
}
from
"@/types/proto/api/v2/memo_relation_service"
;
import
MemoEditor
from
"."
;
import
MemoEditor
from
"."
;
import
{
generateDialog
}
from
"../Dialog"
;
import
{
generateDialog
}
from
"../Dialog"
;
...
...
web/src/components/MemoEditor/index.tsx
View file @
1f0bfd21
...
@@ -7,8 +7,7 @@ import { memoServiceClient } from "@/grpcweb";
...
@@ -7,8 +7,7 @@ import { memoServiceClient } from "@/grpcweb";
import
{
TAB_SPACE_WIDTH
}
from
"@/helpers/consts"
;
import
{
TAB_SPACE_WIDTH
}
from
"@/helpers/consts"
;
import
{
isValidUrl
}
from
"@/helpers/utils"
;
import
{
isValidUrl
}
from
"@/helpers/utils"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useTagStore
}
from
"@/store/module"
;
import
{
useMemoStore
,
useResourceStore
,
useUserStore
,
useWorkspaceSettingStore
,
useTagStore
}
from
"@/store/v1"
;
import
{
useMemoStore
,
useResourceStore
,
useUserStore
,
useWorkspaceSettingStore
}
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
,
Visibility
}
from
"@/types/proto/api/v2/memo_service"
;
import
{
Memo
,
Visibility
}
from
"@/types/proto/api/v2/memo_service"
;
import
{
Resource
}
from
"@/types/proto/api/v2/resource_service"
;
import
{
Resource
}
from
"@/types/proto/api/v2/resource_service"
;
...
...
web/src/components/UserStatisticsView.tsx
View file @
1f0bfd21
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
useTagStore
}
from
"@/store/module"
;
import
{
useMemoStore
,
useTagStore
}
from
"@/store/v1"
;
import
{
useMemoStore
}
from
"@/store/v1"
;
import
{
User
}
from
"@/types/proto/api/v2/user_service"
;
import
{
User
}
from
"@/types/proto/api/v2/user_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
Icon
from
"./Icon"
;
import
Icon
from
"./Icon"
;
...
@@ -19,7 +18,7 @@ const UserStatisticsView = (props: Props) => {
...
@@ -19,7 +18,7 @@ const UserStatisticsView = (props: Props) => {
const
[
isRequesting
,
setIsRequesting
]
=
useState
(
false
);
const
[
isRequesting
,
setIsRequesting
]
=
useState
(
false
);
const
days
=
Math
.
ceil
((
Date
.
now
()
-
user
.
createTime
!
.
getTime
())
/
86400000
);
const
days
=
Math
.
ceil
((
Date
.
now
()
-
user
.
createTime
!
.
getTime
())
/
86400000
);
const
memos
=
Object
.
values
(
memoStore
.
getState
().
memoMapByName
);
const
memos
=
Object
.
values
(
memoStore
.
getState
().
memoMapByName
);
const
tags
=
tagStore
.
state
.
tags
.
length
;
const
tags
=
tagStore
.
getState
().
tags
.
size
;
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
memos
.
length
===
0
)
{
if
(
memos
.
length
===
0
)
{
...
...
web/src/store/index.ts
View file @
1f0bfd21
...
@@ -3,11 +3,9 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
...
@@ -3,11 +3,9 @@ import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
import
dialogReducer
from
"./reducer/dialog"
;
import
dialogReducer
from
"./reducer/dialog"
;
import
filterReducer
from
"./reducer/filter"
;
import
filterReducer
from
"./reducer/filter"
;
import
resourceReducer
from
"./reducer/resource"
;
import
resourceReducer
from
"./reducer/resource"
;
import
tagReducer
from
"./reducer/tag"
;
const
store
=
configureStore
({
const
store
=
configureStore
({
reducer
:
{
reducer
:
{
tag
:
tagReducer
,
filter
:
filterReducer
,
filter
:
filterReducer
,
resource
:
resourceReducer
,
resource
:
resourceReducer
,
dialog
:
dialogReducer
,
dialog
:
dialogReducer
,
...
...
web/src/store/module/index.ts
View file @
1f0bfd21
export
*
from
"./filter"
;
export
*
from
"./filter"
;
export
*
from
"./tag"
;
export
*
from
"./dialog"
;
export
*
from
"./dialog"
;
web/src/store/module/tag.ts
deleted
100644 → 0
View file @
4aa72306
import
{
tagServiceClient
}
from
"@/grpcweb"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
store
,
{
useAppSelector
}
from
".."
;
import
{
deleteTag
as
deleteTagAction
,
setTags
,
upsertTag
as
upsertTagAction
}
from
"../reducer/tag"
;
export
const
useTagStore
=
()
=>
{
const
state
=
useAppSelector
((
state
)
=>
state
.
tag
);
const
currentUser
=
useCurrentUser
();
const
getState
=
()
=>
{
return
store
.
getState
().
tag
;
};
const
fetchTags
=
async
()
=>
{
const
{
tags
}
=
await
tagServiceClient
.
listTags
({
user
:
currentUser
.
name
,
});
store
.
dispatch
(
setTags
(
tags
.
map
((
tag
)
=>
tag
.
name
)));
};
const
upsertTag
=
async
(
tagName
:
string
)
=>
{
await
tagServiceClient
.
upsertTag
({
name
:
tagName
,
});
store
.
dispatch
(
upsertTagAction
(
tagName
));
};
const
batchUpsertTag
=
async
(
tagNames
:
string
[])
=>
{
await
tagServiceClient
.
batchUpsertTag
({
requests
:
tagNames
.
map
((
name
)
=>
({
name
,
})),
});
for
(
const
tagName
of
tagNames
)
{
store
.
dispatch
(
upsertTagAction
(
tagName
));
}
};
const
deleteTag
=
async
(
tagName
:
string
)
=>
{
await
tagServiceClient
.
deleteTag
({
tag
:
{
name
:
tagName
,
creator
:
currentUser
.
name
,
},
});
store
.
dispatch
(
deleteTagAction
(
tagName
));
};
return
{
state
,
getState
,
fetchTags
,
upsertTag
,
batchUpsertTag
,
deleteTag
,
};
};
web/src/store/reducer/tag.ts
deleted
100644 → 0
View file @
4aa72306
import
{
createSlice
,
PayloadAction
}
from
"@reduxjs/toolkit"
;
interface
State
{
tags
:
string
[];
}
const
tagSlice
=
createSlice
({
name
:
"tag"
,
initialState
:
{
tags
:
[],
}
as
State
,
reducers
:
{
setTags
:
(
state
,
action
:
PayloadAction
<
string
[]
>
)
=>
{
return
{
...
state
,
tags
:
action
.
payload
,
};
},
upsertTag
:
(
state
,
action
:
PayloadAction
<
string
>
)
=>
{
if
(
state
.
tags
.
includes
(
action
.
payload
))
{
return
state
;
}
return
{
...
state
,
tags
:
state
.
tags
.
concat
(
action
.
payload
),
};
},
deleteTag
:
(
state
,
action
:
PayloadAction
<
string
>
)
=>
{
return
{
...
state
,
tags
:
state
.
tags
.
filter
((
tag
)
=>
{
return
tag
!==
action
.
payload
;
}),
};
},
},
});
export
const
{
setTags
,
upsertTag
,
deleteTag
}
=
tagSlice
.
actions
;
export
default
tagSlice
.
reducer
;
web/src/store/v1/index.ts
View file @
1f0bfd21
...
@@ -4,3 +4,4 @@ export * from "./inbox";
...
@@ -4,3 +4,4 @@ export * from "./inbox";
export
*
from
"./resourceName"
;
export
*
from
"./resourceName"
;
export
*
from
"./resource"
;
export
*
from
"./resource"
;
export
*
from
"./workspaceSetting"
;
export
*
from
"./workspaceSetting"
;
export
*
from
"./tag"
;
web/src/store/v1/tag.ts
0 → 100644
View file @
1f0bfd21
import
{
create
}
from
"zustand"
;
import
{
combine
}
from
"zustand/middleware"
;
import
{
tagServiceClient
}
from
"@/grpcweb"
;
interface
State
{
tags
:
Set
<
string
>
;
}
const
getDefaultState
=
():
State
=>
({
tags
:
new
Set
(),
});
export
const
useTagStore
=
create
(
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
setState
:
(
state
:
State
)
=>
set
(
state
),
getState
:
()
=>
get
(),
fetchTags
:
async
()
=>
{
const
{
tags
}
=
await
tagServiceClient
.
listTags
({});
set
({
tags
:
new
Set
(
tags
.
map
((
tag
)
=>
tag
.
name
))
});
return
tags
;
},
upsertTag
:
async
(
tagName
:
string
)
=>
{
await
tagServiceClient
.
upsertTag
({
name
:
tagName
,
});
const
{
tags
}
=
get
();
set
({
tags
:
new
Set
([...
tags
,
tagName
])
});
},
batchUpsertTag
:
async
(
tagNames
:
string
[])
=>
{
await
tagServiceClient
.
batchUpsertTag
({
requests
:
tagNames
.
map
((
name
)
=>
({
name
,
})),
});
const
{
tags
}
=
get
();
set
({
tags
:
new
Set
([...
tags
,
...
tagNames
])
});
},
deleteTag
:
async
(
tagName
:
string
)
=>
{
await
tagServiceClient
.
deleteTag
({
tag
:
{
name
:
tagName
,
},
});
const
{
tags
}
=
get
();
tags
.
delete
(
tagName
);
set
({
tags
});
},
})),
);
web/src/store/v1/user.ts
View file @
1f0bfd21
...
@@ -29,6 +29,7 @@ const requestCache = new Map<string, Promise<any>>();
...
@@ -29,6 +29,7 @@ const requestCache = new Map<string, Promise<any>>();
export
const
useUserStore
=
create
(
export
const
useUserStore
=
create
(
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
getState
:
()
=>
get
(),
fetchUsers
:
async
()
=>
{
fetchUsers
:
async
()
=>
{
const
{
users
}
=
await
userServiceClient
.
listUsers
({});
const
{
users
}
=
await
userServiceClient
.
listUsers
({});
const
userMap
=
get
().
userMapByName
;
const
userMap
=
get
().
userMapByName
;
...
...
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