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
2f8d3473
Commit
2f8d3473
authored
Nov 07, 2024
by
johnnyjoy
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'main' of
https://github.com/usememos/memos
parents
b4f9c09d
5601daef
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
76 additions
and
86 deletions
+76
-86
semantic.yml
.github/semantic.yml
+13
-0
workspace_setting.go
store/workspace_setting.go
+4
-0
ActivityCalendar.tsx
web/src/components/ActivityCalendar.tsx
+39
-48
UserStatisticsView.tsx
web/src/components/UserStatisticsView.tsx
+20
-38
No files found.
.github/semantic.yml
0 → 100644
View file @
2f8d3473
enabled
:
true
# Only check PR title
titleOnly
:
true
types
:
-
feat
-
fix
-
refactor
-
chore
-
docs
-
style
-
test
store/workspace_setting.go
View file @
2f8d3473
...
@@ -140,6 +140,7 @@ func (s *Store) GetWorkspaceGeneralSetting(ctx context.Context) (*storepb.Worksp
...
@@ -140,6 +140,7 @@ func (s *Store) GetWorkspaceGeneralSetting(ctx context.Context) (*storepb.Worksp
const
(
const
(
// DefaultContentLengthLimit is the default limit of content length in bytes. 8KB.
// DefaultContentLengthLimit is the default limit of content length in bytes. 8KB.
DefaultContentLengthLimit
=
8
*
1024
DefaultContentLengthLimit
=
8
*
1024
DefaultReaction
=
"👍"
)
)
func
(
s
*
Store
)
GetWorkspaceMemoRelatedSetting
(
ctx
context
.
Context
)
(
*
storepb
.
WorkspaceMemoRelatedSetting
,
error
)
{
func
(
s
*
Store
)
GetWorkspaceMemoRelatedSetting
(
ctx
context
.
Context
)
(
*
storepb
.
WorkspaceMemoRelatedSetting
,
error
)
{
...
@@ -157,6 +158,9 @@ func (s *Store) GetWorkspaceMemoRelatedSetting(ctx context.Context) (*storepb.Wo
...
@@ -157,6 +158,9 @@ func (s *Store) GetWorkspaceMemoRelatedSetting(ctx context.Context) (*storepb.Wo
if
workspaceMemoRelatedSetting
.
ContentLengthLimit
<
DefaultContentLengthLimit
{
if
workspaceMemoRelatedSetting
.
ContentLengthLimit
<
DefaultContentLengthLimit
{
workspaceMemoRelatedSetting
.
ContentLengthLimit
=
DefaultContentLengthLimit
workspaceMemoRelatedSetting
.
ContentLengthLimit
=
DefaultContentLengthLimit
}
}
if
len
(
workspaceMemoRelatedSetting
.
Reactions
)
==
0
{
workspaceMemoRelatedSetting
.
Reactions
=
append
(
workspaceMemoRelatedSetting
.
Reactions
,
DefaultReaction
)
}
s
.
workspaceSettingCache
.
Store
(
storepb
.
WorkspaceSettingKey_MEMO_RELATED
.
String
(),
&
storepb
.
WorkspaceSetting
{
s
.
workspaceSettingCache
.
Store
(
storepb
.
WorkspaceSettingKey_MEMO_RELATED
.
String
(),
&
storepb
.
WorkspaceSetting
{
Key
:
storepb
.
WorkspaceSettingKey_MEMO_RELATED
,
Key
:
storepb
.
WorkspaceSettingKey_MEMO_RELATED
,
Value
:
&
storepb
.
WorkspaceSetting_MemoRelatedSetting
{
MemoRelatedSetting
:
workspaceMemoRelatedSetting
},
Value
:
&
storepb
.
WorkspaceSetting_MemoRelatedSetting
{
MemoRelatedSetting
:
workspaceMemoRelatedSetting
},
...
...
web/src/components/ActivityCalendar.tsx
View file @
2f8d3473
...
@@ -5,10 +5,10 @@ import { useWorkspaceSettingStore } from "@/store/v1";
...
@@ -5,10 +5,10 @@ import { useWorkspaceSettingStore } from "@/store/v1";
import
{
WorkspaceGeneralSetting
}
from
"@/types/proto/api/v1/workspace_setting_service"
;
import
{
WorkspaceGeneralSetting
}
from
"@/types/proto/api/v1/workspace_setting_service"
;
import
{
WorkspaceSettingKey
}
from
"@/types/proto/store/workspace_setting"
;
import
{
WorkspaceSettingKey
}
from
"@/types/proto/store/workspace_setting"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
cn
}
from
"@/utils/utils"
;
interface
Props
{
interface
Props
{
// Format: 2021-1
month
:
string
;
// Format: 2021-1
month
:
string
;
selectedDate
:
string
;
selectedDate
:
string
;
data
:
Record
<
string
,
number
>
;
data
:
Record
<
string
,
number
>
;
onClick
?:
(
date
:
string
)
=>
void
;
onClick
?:
(
date
:
string
)
=>
void
;
...
@@ -16,9 +16,8 @@ interface Props {
...
@@ -16,9 +16,8 @@ interface Props {
const
getCellAdditionalStyles
=
(
count
:
number
,
maxCount
:
number
)
=>
{
const
getCellAdditionalStyles
=
(
count
:
number
,
maxCount
:
number
)
=>
{
if
(
count
===
0
)
{
if
(
count
===
0
)
{
return
"
bg-gray-100 text-gray-400 dark:bg-gray-700 dark:text-gray-500
"
;
return
""
;
}
}
const
ratio
=
count
/
maxCount
;
const
ratio
=
count
/
maxCount
;
if
(
ratio
>
0.7
)
{
if
(
ratio
>
0.7
)
{
return
"bg-primary-darker text-gray-100 dark:opacity-80"
;
return
"bg-primary-darker text-gray-100 dark:opacity-80"
;
...
@@ -36,72 +35,64 @@ const ActivityCalendar = (props: Props) => {
...
@@ -36,72 +35,64 @@ const ActivityCalendar = (props: Props) => {
const
weekStartDayOffset
=
(
const
weekStartDayOffset
=
(
workspaceSettingStore
.
getWorkspaceSettingByKey
(
WorkspaceSettingKey
.
GENERAL
).
generalSetting
||
WorkspaceGeneralSetting
.
fromPartial
({})
workspaceSettingStore
.
getWorkspaceSettingByKey
(
WorkspaceSettingKey
.
GENERAL
).
generalSetting
||
WorkspaceGeneralSetting
.
fromPartial
({})
).
weekStartDayOffset
;
).
weekStartDayOffset
;
const
year
=
dayjs
(
monthStr
).
toDate
().
getFullYear
();
const
year
=
dayjs
(
monthStr
).
toDate
().
getFullYear
();
const
month
=
dayjs
(
monthStr
).
toDate
().
getMonth
()
+
1
;
const
month
=
dayjs
(
monthStr
).
toDate
().
getMonth
();
const
dayInMonth
=
new
Date
(
year
,
month
,
0
).
getDate
();
const
dayInMonth
=
new
Date
(
year
,
month
+
1
,
0
).
getDate
();
const
firstDay
=
(((
new
Date
(
year
,
month
-
1
,
1
).
getDay
()
-
weekStartDayOffset
)
%
7
)
+
7
)
%
7
;
const
firstDay
=
(((
new
Date
(
year
,
month
,
1
).
getDay
()
-
weekStartDayOffset
)
%
7
)
+
7
)
%
7
;
const
lastDay
=
new
Date
(
year
,
month
-
1
,
dayInMonth
).
getDay
()
-
weekStartDayOffset
;
const
lastDay
=
new
Date
(
year
,
month
,
dayInMonth
).
getDay
()
-
weekStartDayOffset
;
const
prevMonthDays
=
new
Date
(
year
,
month
,
0
).
getDate
();
const
WEEK_DAYS
=
[
t
(
"days.sun"
),
t
(
"days.mon"
),
t
(
"days.tue"
),
t
(
"days.wed"
),
t
(
"days.thu"
),
t
(
"days.fri"
),
t
(
"days.sat"
)];
const
WEEK_DAYS
=
[
t
(
"days.sun"
),
t
(
"days.mon"
),
t
(
"days.tue"
),
t
(
"days.wed"
),
t
(
"days.thu"
),
t
(
"days.fri"
),
t
(
"days.sat"
)];
const
weekDays
=
WEEK_DAYS
.
slice
(
weekStartDayOffset
).
concat
(
WEEK_DAYS
.
slice
(
0
,
weekStartDayOffset
));
const
weekDays
=
WEEK_DAYS
.
slice
(
weekStartDayOffset
).
concat
(
WEEK_DAYS
.
slice
(
0
,
weekStartDayOffset
));
const
maxCount
=
Math
.
max
(...
Object
.
values
(
data
));
const
maxCount
=
Math
.
max
(...
Object
.
values
(
data
));
const
days
=
[];
const
days
=
[];
for
(
let
i
=
0
;
i
<
firstDay
;
i
++
)
{
// Fill in previous month's days.
days
.
push
(
0
);
for
(
let
i
=
firstDay
-
1
;
i
>=
0
;
i
--
)
{
days
.
push
({
day
:
prevMonthDays
-
i
,
isCurrentMonth
:
false
});
}
}
// Fill in current month's days.
for
(
let
i
=
1
;
i
<=
dayInMonth
;
i
++
)
{
for
(
let
i
=
1
;
i
<=
dayInMonth
;
i
++
)
{
days
.
push
(
i
);
days
.
push
(
{
day
:
i
,
isCurrentMonth
:
true
}
);
}
}
for
(
let
i
=
0
;
i
<
6
-
lastDay
;
i
++
)
{
days
.
push
(
0
);
// Fill in next month's days.
for
(
let
i
=
1
;
i
<
7
-
lastDay
;
i
++
)
{
days
.
push
({
day
:
i
,
isCurrentMonth
:
false
});
}
}
return
(
return
(
<
div
className=
{
clsx
(
"w-full h-auto shrink-0 grid grid-cols-7 grid-flow-row gap-1"
)
}
>
<
div
className=
{
clsx
(
"w-full h-auto shrink-0 grid grid-cols-7 grid-flow-row gap-1"
)
}
>
{
weekDays
.
map
((
day
,
index
)
=>
{
{
weekDays
.
map
((
day
,
index
)
=>
(
return
(
<
div
key=
{
index
}
className=
{
clsx
(
"w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60"
)
}
>
<
div
key=
{
index
}
className=
{
clsx
(
"w-6 h-5 text-xs flex justify-center items-center cursor-default opacity-60"
)
}
>
{
day
}
{
day
}
</
div
>
</
div
>
))
}
);
{
days
.
map
((
item
,
index
)
=>
{
})
}
const
date
=
dayjs
(
`${year}-${month + 1}-${item.day}`
).
format
(
"YYYY-MM-DD"
);
{
days
.
map
((
day
,
index
)
=>
{
const
count
=
item
.
isCurrentMonth
?
data
[
date
]
||
0
:
0
;
const
date
=
dayjs
(
`${year}-${month}-${day}`
).
format
(
"YYYY-MM-DD"
);
const
count
=
data
[
date
]
||
0
;
const
isToday
=
dayjs
().
format
(
"YYYY-MM-DD"
)
===
date
;
const
isToday
=
dayjs
().
format
(
"YYYY-MM-DD"
)
===
date
;
const
tooltipText
=
count
?
t
(
"memo.count-memos-in-date"
,
{
count
:
count
,
date
:
date
})
:
date
;
const
tooltipText
=
count
?
t
(
"memo.count-memos-in-date"
,
{
count
:
count
,
date
:
date
})
:
date
;
const
isSelected
=
dayjs
(
props
.
selectedDate
).
format
(
"YYYY-MM-DD"
)
===
date
;
const
isSelected
=
dayjs
(
props
.
selectedDate
).
format
(
"YYYY-MM-DD"
)
===
date
;
return
day
?
(
count
>
0
?
(
return
(
<
Tooltip
className=
"shrink-0"
key=
{
`${date}-${index}`
}
title=
{
tooltipText
}
placement=
"top"
arrow
>
<
Tooltip
className=
"shrink-0"
key=
{
`${date}-${index}`
}
title=
{
tooltipText
}
placement=
"top"
arrow
>
<
div
className=
{
clsx
(
"w-6 h-6 text-xs rounded-xl flex justify-center items-center border cursor-default"
,
getCellAdditionalStyles
(
count
,
maxCount
),
isToday
&&
"border-zinc-400 dark:border-zinc-300"
,
isSelected
&&
"font-bold border-zinc-400 dark:border-zinc-300"
,
!
isToday
&&
!
isSelected
&&
"border-transparent"
,
)
}
onClick=
{
()
=>
count
&&
onClick
&&
onClick
(
date
)
}
>
{
day
}
</
div
>
</
Tooltip
>
)
:
(
<
div
<
div
key=
{
`${date}-${index}`
}
className=
{
cn
(
className=
{
clsx
(
"w-6 h-6 text-xs rounded-xl flex justify-center items-center border cursor-default"
,
"w-6 h-6 text-xs rounded-xl flex justify-center items-center border cursor-default"
,
"bg-gray-100 text-gray-400 dark:bg-zinc-800 dark:text-gray-500"
,
"text-gray-400"
,
isToday
&&
"border-zinc-400 dark:border-zinc-500"
,
item
.
isCurrentMonth
?
getCellAdditionalStyles
(
count
,
maxCount
)
:
"opacity-60"
,
isToday
&&
"border-zinc-400"
,
isSelected
&&
"font-bold border-zinc-400"
,
!
isToday
&&
!
isSelected
&&
"border-transparent"
,
!
isToday
&&
!
isSelected
&&
"border-transparent"
,
)
}
)
}
onClick=
{
()
=>
count
&&
onClick
&&
onClick
(
date
)
}
>
>
{
day
}
{
item
.
day
}
</
div
>
</
div
>
)
</
Tooltip
>
)
:
(
<
div
key=
{
`${date}-${index}`
}
className=
"shrink-0 w-6 h-6 opacity-0"
></
div
>
);
);
})
}
})
}
</
div
>
</
div
>
...
...
web/src/components/UserStatisticsView.tsx
View file @
2f8d3473
import
{
Divider
,
Tooltip
}
from
"@mui/joy"
;
import
{
Divider
,
Tooltip
}
from
"@mui/joy"
;
import
{
Button
}
from
"@usememos/mui"
;
import
clsx
from
"clsx"
;
import
clsx
from
"clsx"
;
import
dayjs
from
"dayjs"
;
import
dayjs
from
"dayjs"
;
import
{
countBy
}
from
"lodash-es"
;
import
{
countBy
}
from
"lodash-es"
;
import
{
import
{
CalendarDaysIcon
,
CheckCircleIcon
,
ChevronLeftIcon
,
ChevronRightIcon
,
Code2Icon
,
LinkIcon
,
ListTodoIcon
}
from
"lucide-react"
;
CalendarDaysIcon
,
CheckCircleIcon
,
ChevronLeftIcon
,
ChevronRightIcon
,
Code2Icon
,
LinkIcon
,
ListTodoIcon
,
MoreVerticalIcon
,
}
from
"lucide-react"
;
import
{
useState
}
from
"react"
;
import
{
useState
}
from
"react"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
useAsyncEffect
from
"@/hooks/useAsyncEffect"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
...
@@ -20,7 +10,6 @@ import i18n from "@/i18n";
...
@@ -20,7 +10,6 @@ import i18n from "@/i18n";
import
{
useMemoFilterStore
,
useMemoMetadataStore
}
from
"@/store/v1"
;
import
{
useMemoFilterStore
,
useMemoMetadataStore
}
from
"@/store/v1"
;
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"
;
interface
UserMemoStats
{
interface
UserMemoStats
{
link
:
number
;
link
:
number
;
...
@@ -71,33 +60,26 @@ const UserStatisticsView = () => {
...
@@ -71,33 +60,26 @@ const UserStatisticsView = () => {
return
(
return
(
<
div
className=
"group w-full border mt-2 py-2 px-3 rounded-lg space-y-0.5 text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800"
>
<
div
className=
"group w-full border mt-2 py-2 px-3 rounded-lg space-y-0.5 text-gray-500 dark:text-gray-400 bg-zinc-50 dark:bg-zinc-900 dark:border-zinc-800"
>
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center"
>
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center gap-1"
>
<
div
className=
"relative text-base font-medium leading-6 flex flex-row items-center dark:text-gray-400"
>
<
div
className=
"relative text-sm font-medium inline-flex flex-row items-center w-auto dark:text-gray-400 truncate"
>
<
CalendarDaysIcon
className=
"w-5 h-auto mr-1 opacity-60"
strokeWidth=
{
1.5
}
/>
<
CalendarDaysIcon
className=
"w-4 h-auto mr-1 opacity-60 shrink-0"
strokeWidth=
{
1.5
}
/>
<
span
>
{
dayjs
(
visibleMonthString
).
toDate
().
toLocaleString
(
i18n
.
language
,
{
year
:
"numeric"
,
month
:
"long"
})
}
</
span
>
<
span
className=
"truncate"
>
{
dayjs
(
visibleMonthString
).
toDate
().
toLocaleString
(
i18n
.
language
,
{
year
:
"numeric"
,
month
:
"long"
})
}
</
span
>
</
div
>
</
div
>
<
div
className=
"invisible group-hover:visible flex justify-end items-center"
>
<
div
className=
"flex justify-end items-center shrink-0"
>
<
Popover
>
<
span
<
PopoverTrigger
>
className=
"cursor-pointer hover:opacity-80"
<
MoreVerticalIcon
className=
"w-4 h-auto shrink-0 opacity-60"
/>
onClick=
{
()
=>
setVisibleMonthString
(
dayjs
(
visibleMonthString
).
subtract
(
1
,
"month"
).
format
(
"YYYY-MM"
))
}
</
PopoverTrigger
>
>
<
PopoverContent
className=
"flex flex-row justify-end items-center"
align=
"end"
alignOffset=
{
-
12
}
>
<
ChevronLeftIcon
className=
"w-4 h-auto shrink-0 opacity-60"
/>
<
Button
</
span
>
size=
"sm"
<
span
variant=
"plain"
className=
"cursor-pointer hover:opacity-80"
onClick=
{
()
=>
setVisibleMonthString
(
dayjs
(
visibleMonthString
).
subtract
(
1
,
"month"
).
format
(
"YYYY-MM"
))
}
onClick=
{
()
=>
setVisibleMonthString
(
dayjs
(
visibleMonthString
).
add
(
1
,
"month"
).
format
(
"YYYY-MM"
))
}
>
>
<
ChevronLeftIcon
className=
"w-5 h-auto shrink-0 opacity-60"
/>
<
ChevronRightIcon
className=
"w-4 h-auto shrink-0 opacity-60"
/>
</
Button
>
</
span
>
<
Button
size=
"sm"
variant=
"plain"
onClick=
{
()
=>
setVisibleMonthString
(
dayjs
(
visibleMonthString
).
add
(
1
,
"month"
).
format
(
"YYYY-MM"
))
}
>
<
ChevronRightIcon
className=
"w-5 h-auto shrink-0 opacity-60"
/>
</
Button
>
</
PopoverContent
>
</
Popover
>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
"w-full"
>
<
div
className=
"w-full"
>
...
...
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