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
dc15e8f3
Commit
dc15e8f3
authored
Oct 08, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: implement memo metadata store
parent
831c254d
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
130 additions
and
64 deletions
+130
-64
ExploreSidebar.tsx
web/src/components/ExploreSidebar/ExploreSidebar.tsx
+16
-0
HomeSidebar.tsx
web/src/components/HomeSidebar/HomeSidebar.tsx
+17
-0
TagsSection.tsx
web/src/components/HomeSidebar/TagsSection.tsx
+8
-23
TagSelector.tsx
web/src/components/MemoEditor/ActionButton/TagSelector.tsx
+5
-16
TagSuggestions.tsx
web/src/components/MemoEditor/Editor/TagSuggestions.tsx
+5
-4
RenameTagDialog.tsx
web/src/components/RenameTagDialog.tsx
+3
-3
UserStatisticsView.tsx
web/src/components/UserStatisticsView.tsx
+7
-17
index.ts
web/src/store/v1/index.ts
+1
-1
memoMetadata.ts
web/src/store/v1/memoMetadata.ts
+68
-0
No files found.
web/src/components/ExploreSidebar/ExploreSidebar.tsx
View file @
dc15e8f3
import
clsx
from
"clsx"
;
import
clsx
from
"clsx"
;
import
{
useLocation
}
from
"react-router-dom"
;
import
useDebounce
from
"react-use/lib/useDebounce"
;
import
SearchBar
from
"@/components/SearchBar"
;
import
SearchBar
from
"@/components/SearchBar"
;
import
{
useMemoList
,
useMemoMetadataStore
}
from
"@/store/v1"
;
import
TagsSection
from
"../HomeSidebar/TagsSection"
;
import
TagsSection
from
"../HomeSidebar/TagsSection"
;
interface
Props
{
interface
Props
{
...
@@ -7,6 +10,19 @@ interface Props {
...
@@ -7,6 +10,19 @@ interface Props {
}
}
const
ExploreSidebar
=
(
props
:
Props
)
=>
{
const
ExploreSidebar
=
(
props
:
Props
)
=>
{
const
location
=
useLocation
();
const
memoList
=
useMemoList
();
const
memoMetadataStore
=
useMemoMetadataStore
();
useDebounce
(
async
()
=>
{
if
(
memoList
.
size
()
===
0
)
return
;
await
memoMetadataStore
.
fetchMemoMetadata
({
location
});
},
300
,
[
memoList
.
size
(),
location
.
pathname
],
);
return
(
return
(
<
aside
<
aside
className=
{
clsx
(
className=
{
clsx
(
...
...
web/src/components/HomeSidebar/HomeSidebar.tsx
View file @
dc15e8f3
import
clsx
from
"clsx"
;
import
clsx
from
"clsx"
;
import
{
useLocation
}
from
"react-router-dom"
;
import
useDebounce
from
"react-use/lib/useDebounce"
;
import
SearchBar
from
"@/components/SearchBar"
;
import
SearchBar
from
"@/components/SearchBar"
;
import
UserStatisticsView
from
"@/components/UserStatisticsView"
;
import
UserStatisticsView
from
"@/components/UserStatisticsView"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoList
,
useMemoMetadataStore
}
from
"@/store/v1"
;
import
TagsSection
from
"./TagsSection"
;
import
TagsSection
from
"./TagsSection"
;
interface
Props
{
interface
Props
{
...
@@ -8,6 +12,19 @@ interface Props {
...
@@ -8,6 +12,19 @@ interface Props {
}
}
const
HomeSidebar
=
(
props
:
Props
)
=>
{
const
HomeSidebar
=
(
props
:
Props
)
=>
{
const
location
=
useLocation
();
const
user
=
useCurrentUser
();
const
memoList
=
useMemoList
();
const
memoMetadataStore
=
useMemoMetadataStore
();
useDebounce
(
async
()
=>
{
await
memoMetadataStore
.
fetchMemoMetadata
({
user
,
location
});
},
300
,
[
memoList
.
size
(),
user
,
location
.
pathname
],
);
return
(
return
(
<
aside
<
aside
className=
{
clsx
(
className=
{
clsx
(
...
...
web/src/components/HomeSidebar/TagsSection.tsx
View file @
dc15e8f3
...
@@ -3,11 +3,10 @@ import clsx from "clsx";
...
@@ -3,11 +3,10 @@ import clsx from "clsx";
import
{
Edit3Icon
,
HashIcon
,
MoreVerticalIcon
,
TagsIcon
,
TrashIcon
}
from
"lucide-react"
;
import
{
Edit3Icon
,
HashIcon
,
MoreVerticalIcon
,
TagsIcon
,
TrashIcon
}
from
"lucide-react"
;
import
toast
from
"react-hot-toast"
;
import
toast
from
"react-hot-toast"
;
import
{
useLocation
}
from
"react-router-dom"
;
import
{
useLocation
}
from
"react-router-dom"
;
import
useDebounce
from
"react-use/lib/useDebounce"
;
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useMemoFilterStore
,
useMemo
List
,
useTagStore
}
from
"@/store/v1"
;
import
{
useMemoFilterStore
,
useMemo
MetadataStore
,
useMemoTagList
}
from
"@/store/v1"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
showRenameTagDialog
from
"../RenameTagDialog"
;
import
showRenameTagDialog
from
"../RenameTagDialog"
;
import
TagTree
from
"../TagTree"
;
import
TagTree
from
"../TagTree"
;
...
@@ -22,26 +21,12 @@ const TagsSection = (props: Props) => {
...
@@ -22,26 +21,12 @@ const TagsSection = (props: Props) => {
const
location
=
useLocation
();
const
location
=
useLocation
();
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
const
memoFilterStore
=
useMemoFilterStore
();
const
memoFilterStore
=
useMemoFilterStore
();
const
tagStore
=
useTagStore
();
const
memoMetadataStore
=
useMemoMetadataStore
();
const
memoList
=
useMemoList
();
const
[
treeMode
,
setTreeMode
]
=
useLocalStorage
<
boolean
>
(
"tag-view-as-tree"
,
false
);
const
[
treeMode
,
setTreeMode
]
=
useLocalStorage
<
boolean
>
(
"tag-view-as-tree"
,
false
);
const
tag
Amounts
=
Object
.
entries
(
tagStore
.
getState
().
tagAmounts
)
const
tag
s
=
Object
.
entries
(
useMemoTagList
()
)
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
]);
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
]);
useDebounce
(
()
=>
{
if
(
memoList
.
size
()
===
0
)
return
;
fetchTags
();
},
300
,
[
memoList
.
size
(),
location
.
pathname
],
);
const
fetchTags
=
async
()
=>
{
await
tagStore
.
fetchTags
({
user
,
location
});
};
const
handleTagClick
=
(
tag
:
string
)
=>
{
const
handleTagClick
=
(
tag
:
string
)
=>
{
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
).
some
((
filter
)
=>
filter
.
value
===
tag
);
const
isActive
=
memoFilterStore
.
getFiltersByFactor
(
"tagSearch"
).
some
((
filter
)
=>
filter
.
value
===
tag
);
if
(
isActive
)
{
if
(
isActive
)
{
...
@@ -61,7 +46,7 @@ const TagsSection = (props: Props) => {
...
@@ -61,7 +46,7 @@ const TagsSection = (props: Props) => {
parent
:
"memos/-"
,
parent
:
"memos/-"
,
tag
:
tag
,
tag
:
tag
,
});
});
await
tagStore
.
fetchTags
({
location
,
user
},
{
skipCache
:
true
});
await
memoMetadataStore
.
fetchMemoMetadata
({
user
,
location
});
toast
.
success
(
t
(
"message.deleted-successfully"
));
toast
.
success
(
t
(
"message.deleted-successfully"
));
}
}
};
};
...
@@ -70,7 +55,7 @@ const TagsSection = (props: Props) => {
...
@@ -70,7 +55,7 @@ const TagsSection = (props: Props) => {
<
div
className=
"flex flex-col justify-start items-start w-full mt-3 px-1 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
<
div
className=
"flex flex-col justify-start items-start w-full mt-3 px-1 h-auto shrink-0 flex-nowrap hide-scrollbar"
>
<
div
className=
"flex flex-row justify-between items-center w-full gap-1 mb-1 text-sm leading-6 text-gray-400 select-none"
>
<
div
className=
"flex flex-row justify-between items-center w-full gap-1 mb-1 text-sm leading-6 text-gray-400 select-none"
>
<
span
>
{
t
(
"common.tags"
)
}
</
span
>
<
span
>
{
t
(
"common.tags"
)
}
</
span
>
{
tag
Amount
s
.
length
>
0
&&
(
{
tags
.
length
>
0
&&
(
<
Popover
>
<
Popover
>
<
PopoverTrigger
>
<
PopoverTrigger
>
<
MoreVerticalIcon
className=
"w-4 h-auto shrink-0 opacity-60"
/>
<
MoreVerticalIcon
className=
"w-4 h-auto shrink-0 opacity-60"
/>
...
@@ -84,12 +69,12 @@ const TagsSection = (props: Props) => {
...
@@ -84,12 +69,12 @@ const TagsSection = (props: Props) => {
</
Popover
>
</
Popover
>
)
}
)
}
</
div
>
</
div
>
{
tag
Amount
s
.
length
>
0
?
(
{
tags
.
length
>
0
?
(
treeMode
?
(
treeMode
?
(
<
TagTree
tagAmounts=
{
tag
Amount
s
}
/>
<
TagTree
tagAmounts=
{
tags
}
/>
)
:
(
)
:
(
<
div
className=
"w-full flex flex-row justify-start items-center relative flex-wrap gap-x-2 gap-y-1"
>
<
div
className=
"w-full flex flex-row justify-start items-center relative flex-wrap gap-x-2 gap-y-1"
>
{
tag
Amount
s
.
map
(([
tag
,
amount
])
=>
(
{
tags
.
map
(([
tag
,
amount
])
=>
(
<
div
<
div
key=
{
tag
}
key=
{
tag
}
className=
"shrink-0 w-auto max-w-full text-sm rounded-md leading-6 flex flex-row justify-start items-center select-none hover:opacity-80 text-gray-600 dark:text-gray-400 dark:border-zinc-800"
className=
"shrink-0 w-auto max-w-full text-sm rounded-md leading-6 flex flex-row justify-start items-center select-none hover:opacity-80 text-gray-600 dark:text-gray-400 dark:border-zinc-800"
...
...
web/src/components/MemoEditor/ActionButton/TagSelector.tsx
View file @
dc15e8f3
...
@@ -3,9 +3,7 @@ import { HashIcon } from "lucide-react";
...
@@ -3,9 +3,7 @@ import { HashIcon } from "lucide-react";
import
{
useRef
,
useState
}
from
"react"
;
import
{
useRef
,
useState
}
from
"react"
;
import
useClickAway
from
"react-use/lib/useClickAway"
;
import
useClickAway
from
"react-use/lib/useClickAway"
;
import
OverflowTip
from
"@/components/kit/OverflowTip"
;
import
OverflowTip
from
"@/components/kit/OverflowTip"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
{
useMemoTagList
}
from
"@/store/v1"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useTagStore
}
from
"@/store/v1"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
EditorRefActions
}
from
"../Editor"
;
import
{
EditorRefActions
}
from
"../Editor"
;
...
@@ -16,21 +14,12 @@ interface Props {
...
@@ -16,21 +14,12 @@ interface Props {
const
TagSelector
=
(
props
:
Props
)
=>
{
const
TagSelector
=
(
props
:
Props
)
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
{
editorRef
}
=
props
;
const
{
editorRef
}
=
props
;
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
.
sortedTags
();
const
tags
=
Object
.
entries
(
useMemoTagList
())
const
user
=
useCurrentUser
();
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
])
useAsyncEffect
(
async
()
=>
{
.
map
(([
tag
])
=>
tag
);
if
(
!
open
)
return
;
try
{
await
tagStore
.
fetchTags
({
user
});
}
catch
(
error
)
{
// do nothing.
}
},
[
open
]);
useClickAway
(
containerRef
,
()
=>
{
useClickAway
(
containerRef
,
()
=>
{
setOpen
(
false
);
setOpen
(
false
);
...
...
web/src/components/MemoEditor/Editor/TagSuggestions.tsx
View file @
dc15e8f3
...
@@ -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
{
use
TagStore
}
from
"@/store/v1"
;
import
{
use
MemoTagList
}
from
"@/store/v1"
;
import
{
EditorRefActions
}
from
"."
;
import
{
EditorRefActions
}
from
"."
;
type
Props
=
{
type
Props
=
{
...
@@ -15,12 +15,13 @@ type Position = { left: number; top: number; height: number };
...
@@ -15,12 +15,13 @@ 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
tagStore
=
useTagStore
();
const
tags
=
tagStore
.
sortedTags
();
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
tags
=
Object
.
entries
(
useMemoTagList
())
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
])
.
map
(([
tag
])
=>
tag
);
const
hide
=
()
=>
setPosition
(
null
);
const
hide
=
()
=>
setPosition
(
null
);
...
...
web/src/components/RenameTagDialog.tsx
View file @
dc15e8f3
...
@@ -5,7 +5,7 @@ import { toast } from "react-hot-toast";
...
@@ -5,7 +5,7 @@ import { toast } from "react-hot-toast";
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
{
use
Tag
Store
}
from
"@/store/v1"
;
import
{
use
MemoMetadata
Store
}
from
"@/store/v1"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
generateDialog
}
from
"./Dialog"
;
import
{
generateDialog
}
from
"./Dialog"
;
...
@@ -16,7 +16,7 @@ interface Props extends DialogProps {
...
@@ -16,7 +16,7 @@ interface Props extends DialogProps {
const
RenameTagDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
RenameTagDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
tag
,
destroy
}
=
props
;
const
{
tag
,
destroy
}
=
props
;
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
tagStore
=
useTag
Store
();
const
memoMetadataStore
=
useMemoMetadata
Store
();
const
[
newName
,
setNewName
]
=
useState
(
tag
);
const
[
newName
,
setNewName
]
=
useState
(
tag
);
const
requestState
=
useLoading
(
false
);
const
requestState
=
useLoading
(
false
);
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
...
@@ -42,7 +42,7 @@ const RenameTagDialog: React.FC<Props> = (props: Props) => {
...
@@ -42,7 +42,7 @@ const RenameTagDialog: React.FC<Props> = (props: Props) => {
newTag
:
newName
,
newTag
:
newName
,
});
});
toast
.
success
(
"Rename tag successfully"
);
toast
.
success
(
"Rename tag successfully"
);
tagStore
.
fetchTags
({
user
},
{
skipCache
:
true
});
memoMetadataStore
.
fetchMemoMetadata
({
user
});
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
console
.
error
(
error
);
console
.
error
(
error
);
toast
.
error
(
error
.
details
);
toast
.
error
(
error
.
details
);
...
...
web/src/components/UserStatisticsView.tsx
View file @
dc15e8f3
...
@@ -19,15 +19,11 @@ import { memoServiceClient } from "@/grpcweb";
...
@@ -19,15 +19,11 @@ import { memoServiceClient } from "@/grpcweb";
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
i18n
from
"@/i18n"
;
import
i18n
from
"@/i18n"
;
import
{
useMemoFilterStore
,
useMemoList
,
useMemoStore
}
from
"@/store/v1"
;
import
{
useMemoFilterStore
,
useMemoMetadataStore
}
from
"@/store/v1"
;
import
{
MemoView
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
ActivityCalendar
from
"./ActivityCalendar"
;
import
ActivityCalendar
from
"./ActivityCalendar"
;
import
{
Popover
,
PopoverContent
,
PopoverTrigger
}
from
"./ui/Popover"
;
import
{
Popover
,
PopoverContent
,
PopoverTrigger
}
from
"./ui/Popover"
;
// Set the maximum number of memos to fetch.
const
DEFAULT_MEMO_PAGE_SIZE
=
1000000
;
interface
UserMemoStats
{
interface
UserMemoStats
{
link
:
number
;
link
:
number
;
taskList
:
number
;
taskList
:
number
;
...
@@ -38,9 +34,9 @@ interface UserMemoStats {
...
@@ -38,9 +34,9 @@ interface UserMemoStats {
const
UserStatisticsView
=
()
=>
{
const
UserStatisticsView
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
currentUser
=
useCurrentUser
();
const
currentUser
=
useCurrentUser
();
const
memoStore
=
useMemoStore
();
const
memoList
=
useMemoList
();
const
memoFilterStore
=
useMemoFilterStore
();
const
memoFilterStore
=
useMemoFilterStore
();
const
memoMetadataStore
=
useMemoMetadataStore
();
const
metadataList
=
Object
.
values
(
memoMetadataStore
.
getState
().
dataMapByName
);
const
[
memoAmount
,
setMemoAmount
]
=
useState
(
0
);
const
[
memoAmount
,
setMemoAmount
]
=
useState
(
0
);
const
[
memoStats
,
setMemoStats
]
=
useState
<
UserMemoStats
>
({
link
:
0
,
taskList
:
0
,
code
:
0
,
incompleteTasks
:
0
});
const
[
memoStats
,
setMemoStats
]
=
useState
<
UserMemoStats
>
({
link
:
0
,
taskList
:
0
,
code
:
0
,
incompleteTasks
:
0
});
const
[
activityStats
,
setActivityStats
]
=
useState
<
Record
<
string
,
number
>>
({});
const
[
activityStats
,
setActivityStats
]
=
useState
<
Record
<
string
,
number
>>
({});
...
@@ -49,14 +45,8 @@ const UserStatisticsView = () => {
...
@@ -49,14 +45,8 @@ const UserStatisticsView = () => {
const
days
=
Math
.
ceil
((
Date
.
now
()
-
currentUser
.
createTime
!
.
getTime
())
/
86400000
);
const
days
=
Math
.
ceil
((
Date
.
now
()
-
currentUser
.
createTime
!
.
getTime
())
/
86400000
);
useAsyncEffect
(
async
()
=>
{
useAsyncEffect
(
async
()
=>
{
if
(
memoList
.
size
()
===
0
)
return
;
const
{
memos
}
=
await
memoServiceClient
.
listMemos
({
pageSize
:
DEFAULT_MEMO_PAGE_SIZE
,
view
:
MemoView
.
MEMO_VIEW_METADATA_ONLY
,
});
const
memoStats
:
UserMemoStats
=
{
link
:
0
,
taskList
:
0
,
code
:
0
,
incompleteTasks
:
0
};
const
memoStats
:
UserMemoStats
=
{
link
:
0
,
taskList
:
0
,
code
:
0
,
incompleteTasks
:
0
};
me
mos
.
forEach
((
memo
)
=>
{
me
tadataList
.
forEach
((
memo
)
=>
{
const
{
property
}
=
memo
;
const
{
property
}
=
memo
;
if
(
property
?.
hasLink
)
{
if
(
property
?.
hasLink
)
{
memoStats
.
link
+=
1
;
memoStats
.
link
+=
1
;
...
@@ -72,9 +62,9 @@ const UserStatisticsView = () => {
...
@@ -72,9 +62,9 @@ const UserStatisticsView = () => {
}
}
});
});
setMemoStats
(
memoStats
);
setMemoStats
(
memoStats
);
setMemoAmount
(
me
mos
.
length
);
setMemoAmount
(
me
tadataList
.
length
);
setActivityStats
(
countBy
(
me
mos
.
map
((
memo
)
=>
dayjs
(
memo
.
displayTime
).
format
(
"YYYY-MM-DD"
))));
setActivityStats
(
countBy
(
me
tadataList
.
map
((
memo
)
=>
dayjs
(
memo
.
displayTime
).
format
(
"YYYY-MM-DD"
))));
},
[
memoStore
.
stateId
]);
},
[
memo
Metadata
Store
.
stateId
]);
const
rebuildMemoProperty
=
async
()
=>
{
const
rebuildMemoProperty
=
async
()
=>
{
await
memoServiceClient
.
rebuildMemoProperty
({
await
memoServiceClient
.
rebuildMemoProperty
({
...
...
web/src/store/v1/index.ts
View file @
dc15e8f3
...
@@ -4,5 +4,5 @@ export * from "./inbox";
...
@@ -4,5 +4,5 @@ export * from "./inbox";
export
*
from
"./resourceName"
;
export
*
from
"./resourceName"
;
export
*
from
"./resource"
;
export
*
from
"./resource"
;
export
*
from
"./workspaceSetting"
;
export
*
from
"./workspaceSetting"
;
export
*
from
"./tag"
;
export
*
from
"./memoFilter"
;
export
*
from
"./memoFilter"
;
export
*
from
"./memoMetadata"
;
web/src/store/v1/
tag
.ts
→
web/src/store/v1/
memoMetadata
.ts
View file @
dc15e8f3
import
{
uniqueId
}
from
"lodash-es"
;
import
{
Location
}
from
"react-router-dom"
;
import
{
Location
}
from
"react-router-dom"
;
import
{
create
}
from
"zustand"
;
import
{
create
}
from
"zustand"
;
import
{
combine
}
from
"zustand/middleware"
;
import
{
combine
}
from
"zustand/middleware"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
memoServiceClient
}
from
"@/grpcweb"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
import
{
MemoView
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
Memo
,
Memo
View
}
from
"@/types/proto/api/v1/memo_service"
;
import
{
User
}
from
"@/types/proto/api/v1/user_service"
;
import
{
User
}
from
"@/types/proto/api/v1/user_service"
;
// Set the maximum number of memos to fetch.
// Set the maximum number of memos to fetch.
const
DEFAULT_MEMO_PAGE_SIZE
=
1000000
;
const
DEFAULT_MEMO_PAGE_SIZE
=
1000000
;
interface
State
{
interface
State
{
tagAmounts
:
Record
<
string
,
number
>
;
// stateId is used to identify the store instance state.
// It should be update when any state change.
stateId
:
string
;
dataMapByName
:
Record
<
string
,
Memo
>
;
}
}
const
getDefaultState
=
():
State
=>
({
const
getDefaultState
=
():
State
=>
({
tagAmounts
:
{},
stateId
:
uniqueId
(),
dataMapByName
:
{},
});
});
export
const
use
Tag
Store
=
create
(
export
const
use
MemoMetadata
Store
=
create
(
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
combine
(
getDefaultState
(),
(
set
,
get
)
=>
({
setState
:
(
state
:
State
)
=>
set
(
state
),
setState
:
(
state
:
State
)
=>
set
(
state
),
getState
:
()
=>
get
(),
getState
:
()
=>
get
(),
sortedTags
:
()
=>
{
fetchMemoMetadata
:
async
(
params
:
{
user
?:
User
;
location
?:
Location
<
any
>
})
=>
{
return
Object
.
entries
(
get
().
tagAmounts
)
.
sort
((
a
,
b
)
=>
a
[
0
].
localeCompare
(
b
[
0
]))
.
sort
((
a
,
b
)
=>
b
[
1
]
-
a
[
1
])
.
map
(([
tag
])
=>
tag
);
},
fetchTags
:
async
(
params
:
{
user
?:
User
;
location
?:
Location
<
any
>
},
options
?:
{
skipCache
?:
boolean
})
=>
{
const
{
tagAmounts
:
cache
}
=
get
();
if
(
cache
.
length
>
0
&&
!
options
?.
skipCache
)
{
return
cache
;
}
const
filters
=
[
`row_status == "NORMAL"`
];
const
filters
=
[
`row_status == "NORMAL"`
];
if
(
params
.
user
)
{
if
(
params
.
user
)
{
if
(
params
.
location
?.
pathname
===
Routes
.
EXPLORE
)
{
if
(
params
.
location
?.
pathname
===
Routes
.
EXPLORE
)
{
...
@@ -41,13 +36,26 @@ export const useTagStore = create(
...
@@ -41,13 +36,26 @@ export const useTagStore = create(
}
else
{
}
else
{
filters
.
push
(
`visibilities == ["PUBLIC"]`
);
filters
.
push
(
`visibilities == ["PUBLIC"]`
);
}
}
const
{
memos
}
=
await
memoServiceClient
.
listMemos
({
const
{
memos
,
nextPageToken
}
=
await
memoServiceClient
.
listMemos
({
pageSize
:
DEFAULT_MEMO_PAGE_SIZE
,
filter
:
filters
.
join
(
" && "
),
filter
:
filters
.
join
(
" && "
),
view
:
MemoView
.
MEMO_VIEW_METADATA_ONLY
,
view
:
MemoView
.
MEMO_VIEW_METADATA_ONLY
,
pageSize
:
DEFAULT_MEMO_PAGE_SIZE
,
});
});
const
memoMap
=
{
...
get
().
dataMapByName
};
for
(
const
memo
of
memos
)
{
memoMap
[
memo
.
name
]
=
memo
;
}
set
({
stateId
:
uniqueId
(),
dataMapByName
:
memoMap
});
return
{
memos
,
nextPageToken
};
},
})),
);
export
const
useMemoTagList
=
()
=>
{
const
memoStore
=
useMemoMetadataStore
();
const
data
=
Object
.
values
(
memoStore
.
getState
().
dataMapByName
);
const
tagAmounts
:
Record
<
string
,
number
>
=
{};
const
tagAmounts
:
Record
<
string
,
number
>
=
{};
memos
.
forEach
((
memo
)
=>
{
data
.
forEach
((
memo
)
=>
{
memo
.
property
?.
tags
.
forEach
((
tag
)
=>
{
memo
.
property
?.
tags
.
forEach
((
tag
)
=>
{
if
(
tagAmounts
[
tag
])
{
if
(
tagAmounts
[
tag
])
{
tagAmounts
[
tag
]
+=
1
;
tagAmounts
[
tag
]
+=
1
;
...
@@ -56,7 +64,5 @@ export const useTagStore = create(
...
@@ -56,7 +64,5 @@ export const useTagStore = create(
}
}
});
});
});
});
set
({
tagAmounts
});
return
tagAmounts
;
},
};
})),
);
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