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
4c590357
Commit
4c590357
authored
Jan 06, 2024
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update about page
parent
9459ae82
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
68 additions
and
90 deletions
+68
-90
AboutSiteDialog.tsx
web/src/components/AboutSiteDialog.tsx
+0
-53
Navigation.tsx
web/src/components/Navigation.tsx
+7
-1
UserBanner.tsx
web/src/components/UserBanner.tsx
+2
-12
Dropdown.tsx
web/src/components/kit/Dropdown.tsx
+10
-2
About.tsx
web/src/pages/About.tsx
+36
-0
UserProfile.tsx
web/src/pages/UserProfile.tsx
+8
-22
index.tsx
web/src/router/index.tsx
+5
-0
No files found.
web/src/components/AboutSiteDialog.tsx
deleted
100644 → 0
View file @
9459ae82
import
{
Divider
,
IconButton
}
from
"@mui/joy"
;
import
{
useGlobalStore
}
from
"@/store/module"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
generateDialog
}
from
"./Dialog"
;
import
Icon
from
"./Icon"
;
type
Props
=
DialogProps
;
const
AboutSiteDialog
:
React
.
FC
<
Props
>
=
({
destroy
}:
Props
)
=>
{
const
t
=
useTranslate
();
const
globalStore
=
useGlobalStore
();
const
profile
=
globalStore
.
state
.
systemStatus
.
profile
;
const
customizedProfile
=
globalStore
.
state
.
systemStatus
.
customizedProfile
;
const
handleCloseBtnClick
=
()
=>
{
destroy
();
};
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text flex items-center"
>
{
t
(
"common.about"
)
}
{
customizedProfile
.
name
}
</
p
>
<
IconButton
size=
"sm"
onClick=
{
handleCloseBtnClick
}
>
<
Icon
.
X
className=
"opacity-70"
/>
</
IconButton
>
</
div
>
<
div
className=
"flex flex-col justify-start items-start max-w-full w-96"
>
<
p
className=
"text-xs"
>
{
t
(
"about.memos-description"
)
}
</
p
>
<
p
className=
"text-sm mt-2"
>
{
customizedProfile
.
description
||
t
(
"about.no-server-description"
)
}
</
p
>
<
Divider
className=
"!my-3"
/>
<
div
className=
"w-full flex flex-row justify-start items-center text-sm italic"
>
{
t
(
"about.powered-by"
)
}
<
a
className=
"shrink-0 flex flex-row justify-start items-center mx-1 hover:underline"
href=
"https://usememos.com"
target=
"_blank"
>
<
img
className=
"w-auto h-7"
src=
"https://www.usememos.com/full-logo-landscape.png"
alt=
""
/>
</
a
>
<
span
>
v
{
profile
.
version
}
</
span
>
</
div
>
</
div
>
</>
);
};
export
default
function
showAboutSiteDialog
():
void
{
generateDialog
(
{
className
:
"about-site-dialog"
,
dialogName
:
"about-site-dialog"
,
},
AboutSiteDialog
);
}
web/src/components/Navigation.tsx
View file @
4c590357
...
...
@@ -98,10 +98,16 @@ const Navigation = () => {
title
:
t
(
"common.sign-in"
),
icon
:
<
Icon
.
LogIn
className=
"mr-3 w-6 h-auto opacity-70"
/>,
};
const
aboutNavLink
:
NavLinkItem
=
{
id
:
"header-about"
,
path
:
"/about"
,
title
:
t
(
"common.about"
),
icon
:
<
Icon
.
Smile
className=
"mr-3 w-6 h-auto opacity-70"
/>,
};
const
navLinks
:
NavLinkItem
[]
=
user
?
[
homeNavLink
,
timelineNavLink
,
resourcesNavLink
,
exploreNavLink
,
profileNavLink
,
inboxNavLink
,
archivedNavLink
,
settingNavLink
]
:
[
exploreNavLink
,
signInNavLink
];
:
[
exploreNavLink
,
signInNavLink
,
aboutNavLink
];
return
(
<
header
className=
"w-full h-full overflow-auto flex flex-col justify-start items-start py-4 md:pt-6 z-30"
>
...
...
web/src/components/UserBanner.tsx
View file @
4c590357
...
...
@@ -2,7 +2,6 @@ import * as api from "@/helpers/api";
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useGlobalStore
}
from
"@/store/module"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
showAboutSiteDialog
from
"./AboutSiteDialog"
;
import
Icon
from
"./Icon"
;
import
UserAvatar
from
"./UserAvatar"
;
import
Dropdown
from
"./kit/Dropdown"
;
...
...
@@ -14,10 +13,6 @@ const UserBanner = () => {
const
user
=
useCurrentUser
();
const
title
=
user
?
user
.
nickname
||
user
.
username
:
systemStatus
.
customizedProfile
.
name
||
"memos"
;
const
handleAboutBtnClick
=
()
=>
{
showAboutSiteDialog
();
};
const
handleSignOutBtnClick
=
async
()
=>
{
await
api
.
signout
();
window
.
location
.
href
=
"/auth"
;
...
...
@@ -33,22 +28,17 @@ const UserBanner = () => {
<
span
className=
"text-lg font-medium text-slate-800 dark:text-gray-200 shrink truncate"
>
{
title
}
</
span
>
</
div
>
}
disabled=
{
user
==
undefined
}
actionsClassName=
"min-w-[128px] max-w-full"
positionClassName=
"top-full mt-2"
actions=
{
<>
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleAboutBtnClick
}
>
<
Icon
.
Info
className=
"w-5 h-auto mr-2 opacity-80"
/>
{
t
(
"common.about"
)
}
</
button
>
{
user
!=
undefined
&&
(
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded flex flex-row justify-start items-center dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleSignOutBtnClick
}
>
<
Icon
.
LogOut
className=
"w-5 h-auto mr-
2 opacity-8
0"
/>
{
t
(
"common.sign-out"
)
}
<
Icon
.
LogOut
className=
"w-5 h-auto mr-
1 opacity-6
0"
/>
{
t
(
"common.sign-out"
)
}
</
button
>
)
}
</>
...
...
web/src/components/kit/Dropdown.tsx
View file @
4c590357
...
...
@@ -5,13 +5,14 @@ import Icon from "../Icon";
interface
Props
{
trigger
?:
ReactNode
;
actions
?:
ReactNode
;
disabled
?:
boolean
;
className
?:
string
;
actionsClassName
?:
string
;
positionClassName
?:
string
;
}
const
Dropdown
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
trigger
,
actions
,
className
,
actionsClassName
,
positionClassName
}
=
props
;
const
{
trigger
,
actions
,
disabled
,
className
,
actionsClassName
,
positionClassName
}
=
props
;
const
[
dropdownStatus
,
toggleDropdownStatus
]
=
useToggle
(
false
);
const
dropdownWrapperRef
=
useRef
<
HTMLDivElement
>
(
null
);
...
...
@@ -29,11 +30,18 @@ const Dropdown: React.FC<Props> = (props: Props) => {
}
},
[
dropdownStatus
]);
const
handleDropdownClick
=
()
=>
{
if
(
disabled
)
{
return
;
}
toggleDropdownStatus
();
};
return
(
<
div
ref=
{
dropdownWrapperRef
}
className=
{
`relative flex flex-col justify-start items-start select-none ${className ?? ""}`
}
onClick=
{
()
=>
toggleDropdownStatus
()
}
onClick=
{
handleDropdownClick
}
>
{
trigger
?
(
trigger
...
...
web/src/pages/About.tsx
0 → 100644
View file @
4c590357
import
{
Link
}
from
"@mui/joy"
;
import
Icon
from
"@/components/Icon"
;
import
MobileHeader
from
"@/components/MobileHeader"
;
const
About
=
()
=>
{
return
(
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8"
>
<
MobileHeader
/>
<
div
className=
"w-full px-4 sm:px-6"
>
<
div
className=
"w-full shadow flex flex-col justify-start items-start px-4 py-3 rounded-xl bg-white dark:bg-zinc-800 text-black dark:text-gray-300"
>
<
img
className=
"w-auto h-12"
src=
"https://www.usememos.com/full-logo-landscape.png"
alt=
""
/>
<
p
className=
"text-base"
>
A privacy-first, lightweight note-taking service. Easily capture and share your great thoughts.
</
p
>
<
div
className=
"mt-1 flex flex-row items-center flex-wrap"
>
<
Link
underline=
"always"
href=
"https://github.com/usememos/memos"
>
GitHub Repo
</
Link
>
<
Icon
.
Dot
className=
"w-4 h-auto opacity-60"
/>
<
Link
underline=
"always"
href=
"https://www.usememos.com/"
>
Offical Website
</
Link
>
<
Icon
.
Dot
className=
"w-4 h-auto opacity-60"
/>
<
Link
underline=
"always"
href=
"https://www.usememos.com/blog"
>
Blogs
</
Link
>
<
Icon
.
Dot
className=
"w-4 h-auto opacity-60"
/>
<
Link
underline=
"always"
href=
"https://www.usememos.com/blog"
>
Documents
</
Link
>
</
div
>
</
div
>
</
div
>
</
section
>
);
};
export
default
About
;
web/src/pages/UserProfile.tsx
View file @
4c590357
...
...
@@ -10,7 +10,6 @@ import UserAvatar from "@/components/UserAvatar";
import
{
DEFAULT_MEMO_LIMIT
}
from
"@/helpers/consts"
;
import
{
getTimeStampByDate
}
from
"@/helpers/datetime"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
{
useFilterStore
}
from
"@/store/module"
;
import
{
useMemoList
,
useMemoStore
,
useUserStore
}
from
"@/store/v1"
;
import
{
User
}
from
"@/types/proto/api/v2/user_service"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
...
@@ -21,12 +20,10 @@ const UserProfile = () => {
const
userStore
=
useUserStore
();
const
loadingState
=
useLoading
();
const
[
user
,
setUser
]
=
useState
<
User
>
();
const
filterStore
=
useFilterStore
();
const
memoStore
=
useMemoStore
();
const
memoList
=
useMemoList
();
const
[
isRequesting
,
setIsRequesting
]
=
useState
(
true
);
const
[
isComplete
,
setIsComplete
]
=
useState
(
false
);
const
{
tag
:
tagQuery
,
text
:
textQuery
}
=
filterStore
.
state
;
const
sortedMemos
=
memoList
.
value
.
sort
((
a
,
b
)
=>
getTimeStampByDate
(
b
.
displayTime
)
-
getTimeStampByDate
(
a
.
displayTime
))
.
sort
((
a
,
b
)
=>
Number
(
b
.
pinned
)
-
Number
(
a
.
pinned
));
...
...
@@ -56,7 +53,7 @@ const UserProfile = () => {
memoList
.
reset
();
fetchMemos
();
},
[
user
,
tagQuery
,
textQuery
]);
},
[
user
]);
const
fetchMemos
=
async
()
=>
{
if
(
!
user
)
{
...
...
@@ -64,16 +61,6 @@ const UserProfile = () => {
}
const
filters
=
[
`creator == "
${
user
.
name
}
"`
,
`row_status == "NORMAL"`
,
`order_by_pinned == true`
];
const
contentSearch
:
string
[]
=
[];
if
(
tagQuery
)
{
contentSearch
.
push
(
`"#
${
tagQuery
}
"`
);
}
if
(
textQuery
)
{
contentSearch
.
push
(
`"
${
textQuery
}
"`
);
}
if
(
contentSearch
.
length
>
0
)
{
filters
.
push
(
`content_search == [
${
contentSearch
.
join
(
", "
)}
]`
);
}
setIsRequesting
(
true
);
const
data
=
await
memoStore
.
fetchMemos
({
filter
:
filters
.
join
(
" && "
),
...
...
@@ -91,18 +78,17 @@ const UserProfile = () => {
{
!
loadingState
.
isLoading
&&
(
user
?
(
<>
<
div
className=
"relative -mt-6 top-8 w-full flex justify-end items-center"
>
<
a
className=
""
href=
{
`/u/${user?.id}/rss.xml`
}
target=
"_blank"
rel=
"noopener noreferrer"
>
<
Button
color=
"neutral"
variant=
"outlined"
endDecorator=
{
<
Icon
.
Rss
className=
"w-4 h-auto opacity-60"
/>
}
>
RSS
</
Button
>
</
a
>
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-center py-8"
>
<
UserAvatar
className=
"!w-20 !h-20 mb-2 drop-shadow"
avatarUrl=
{
user
?.
avatarUrl
}
/>
<
div
className=
"w-full flex flex-row justify-center items-center"
>
<
p
className=
"text-3xl text-black leading-none opacity-80 dark:text-gray-200"
>
{
user
?.
nickname
}
</
p
>
<
a
className=
"ml-1 cursor-pointer text-gray-500"
href=
{
`/u/${user?.id}/rss.xml`
}
target=
"_blank"
rel=
"noopener noreferrer"
>
<
Icon
.
Rss
className=
"w-5 h-auto opacity-60 mt-0.5"
/>
</
a
>
</
div
>
</
div
>
{
sortedMemos
.
map
((
memo
)
=>
(
...
...
web/src/router/index.tsx
View file @
4c590357
...
...
@@ -18,6 +18,7 @@ const Timeline = lazy(() => import("@/pages/Timeline"));
const
Resources
=
lazy
(()
=>
import
(
"@/pages/Resources"
));
const
Inboxes
=
lazy
(()
=>
import
(
"@/pages/Inboxes"
));
const
Setting
=
lazy
(()
=>
import
(
"@/pages/Setting"
));
const
About
=
lazy
(()
=>
import
(
"@/pages/About"
));
const
NotFound
=
lazy
(()
=>
import
(
"@/pages/NotFound"
));
const
PermissionDenied
=
lazy
(()
=>
import
(
"@/pages/PermissionDenied"
));
...
...
@@ -118,6 +119,10 @@ const router = createBrowserRouter([
path
:
"u/:username"
,
element
:
<
UserProfile
/>,
},
{
path
:
"about"
,
element
:
<
About
/>,
},
{
path
:
"403"
,
element
:
<
PermissionDenied
/>,
...
...
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