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
15cfc9e1
Commit
15cfc9e1
authored
Sep 20, 2022
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: add memo detail page
parent
004713d4
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
119 additions
and
19 deletions
+119
-19
MemoCardDialog.tsx
web/src/components/MemoCardDialog.tsx
+4
-6
api.ts
web/src/helpers/api.ts
+4
-0
Explore.tsx
web/src/pages/Explore.tsx
+1
-13
MemoDetail.tsx
web/src/pages/MemoDetail.tsx
+91
-0
index.tsx
web/src/router/index.tsx
+12
-0
memoService.ts
web/src/services/memoService.ts
+7
-0
No files found.
web/src/components/MemoCardDialog.tsx
View file @
15cfc9e1
import
copy
from
"copy-to-clipboard"
;
import
{
useState
,
useEffect
,
useCallback
}
from
"react"
;
import
{
useState
,
useEffect
,
useCallback
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
editorStateService
,
memoService
,
userService
}
from
"../services"
;
import
{
editorStateService
,
memoService
,
userService
}
from
"../services"
;
...
@@ -116,14 +115,13 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
...
@@ -116,14 +115,13 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
setMemo
(
memo
);
setMemo
(
memo
);
},
[]);
},
[]);
const
handle
Copy
MemoLinkBtnClick
=
()
=>
{
const
handle
Goto
MemoLinkBtnClick
=
()
=>
{
if
(
memo
.
visibility
===
"PRIVATE"
)
{
if
(
memo
.
visibility
===
"PRIVATE"
)
{
toastHelper
.
error
(
t
(
"message.private-only"
));
toastHelper
.
error
(
t
(
"message.private-only"
));
return
;
return
;
}
}
copy
(
`
${
window
.
location
.
origin
}
/explore?memoId=
${
memo
.
id
}
`
);
window
.
open
(
`/m/
${
memo
.
id
}
`
);
toastHelper
.
success
(
t
(
"message.copied"
));
};
};
const
handleEditMemoBtnClick
=
()
=>
{
const
handleEditMemoBtnClick
=
()
=>
{
...
@@ -169,8 +167,8 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
...
@@ -169,8 +167,8 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
<
div
className=
"btns-container"
>
<
div
className=
"btns-container"
>
<
Only
when=
{
!
userService
.
isVisitorMode
()
}
>
<
Only
when=
{
!
userService
.
isVisitorMode
()
}
>
<>
<>
<
button
className=
"btn edit-btn"
onClick=
{
handle
Copy
MemoLinkBtnClick
}
>
<
button
className=
"btn edit-btn"
onClick=
{
handle
Goto
MemoLinkBtnClick
}
>
<
Icon
.
Link
className=
"icon-img"
/>
<
Icon
.
External
Link
className=
"icon-img"
/>
</
button
>
</
button
>
<
button
className=
"btn edit-btn"
onClick=
{
handleEditMemoBtnClick
}
>
<
button
className=
"btn edit-btn"
onClick=
{
handleEditMemoBtnClick
}
>
<
Icon
.
Edit3
className=
"icon-img"
/>
<
Icon
.
Edit3
className=
"icon-img"
/>
...
...
web/src/helpers/api.ts
View file @
15cfc9e1
...
@@ -73,6 +73,10 @@ export function getMemoList(memoFind?: MemoFind) {
...
@@ -73,6 +73,10 @@ export function getMemoList(memoFind?: MemoFind) {
return
axios
.
get
<
ResponseObject
<
Memo
[]
>>
(
`/api/memo?
${
queryList
.
join
(
"&"
)}
`
);
return
axios
.
get
<
ResponseObject
<
Memo
[]
>>
(
`/api/memo?
${
queryList
.
join
(
"&"
)}
`
);
}
}
export
function
getMemoById
(
id
:
MemoId
)
{
return
axios
.
get
<
ResponseObject
<
Memo
>>
(
`/api/memo/
${
id
}
`
);
}
export
function
createMemo
(
memoCreate
:
MemoCreate
)
{
export
function
createMemo
(
memoCreate
:
MemoCreate
)
{
return
axios
.
post
<
ResponseObject
<
Memo
>>
(
"/api/memo"
,
memoCreate
);
return
axios
.
post
<
ResponseObject
<
Memo
>>
(
"/api/memo"
,
memoCreate
);
}
}
...
...
web/src/pages/Explore.tsx
View file @
15cfc9e1
...
@@ -5,7 +5,6 @@ import { Link, useNavigate } from "react-router-dom";
...
@@ -5,7 +5,6 @@ import { Link, useNavigate } from "react-router-dom";
import
{
memoService
,
userService
}
from
"../services"
;
import
{
memoService
,
userService
}
from
"../services"
;
import
{
isNullorUndefined
}
from
"../helpers/utils"
;
import
{
isNullorUndefined
}
from
"../helpers/utils"
;
import
{
useAppSelector
}
from
"../store"
;
import
{
useAppSelector
}
from
"../store"
;
import
useQuery
from
"../hooks/useQuery"
;
import
useLoading
from
"../hooks/useLoading"
;
import
useLoading
from
"../hooks/useLoading"
;
import
Only
from
"../components/common/OnlyWhen"
;
import
Only
from
"../components/common/OnlyWhen"
;
import
MemoContent
from
"../components/MemoContent"
;
import
MemoContent
from
"../components/MemoContent"
;
...
@@ -19,7 +18,6 @@ interface State {
...
@@ -19,7 +18,6 @@ interface State {
const
Explore
=
()
=>
{
const
Explore
=
()
=>
{
const
{
t
,
i18n
}
=
useTranslation
();
const
{
t
,
i18n
}
=
useTranslation
();
const
navigate
=
useNavigate
();
const
navigate
=
useNavigate
();
const
query
=
useQuery
();
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
location
=
useAppSelector
((
state
)
=>
state
.
location
);
const
location
=
useAppSelector
((
state
)
=>
state
.
location
);
const
[
state
,
setState
]
=
useState
<
State
>
({
const
[
state
,
setState
]
=
useState
<
State
>
({
...
@@ -35,18 +33,8 @@ const Explore = () => {
...
@@ -35,18 +33,8 @@ const Explore = () => {
}
}
memoService
.
fetchAllMemos
().
then
((
memos
)
=>
{
memoService
.
fetchAllMemos
().
then
((
memos
)
=>
{
let
filteredMemos
=
memos
;
const
memoId
=
Number
(
query
.
get
(
"memoId"
));
if
(
memoId
&&
!
isNaN
(
memoId
))
{
filteredMemos
=
filteredMemos
.
filter
((
memo
)
=>
{
return
memo
.
id
===
memoId
;
});
}
setState
({
setState
({
...
state
,
memos
,
memos
:
filteredMemos
,
});
});
loadingState
.
setFinish
();
loadingState
.
setFinish
();
});
});
...
...
web/src/pages/MemoDetail.tsx
0 → 100644
View file @
15cfc9e1
import
dayjs
from
"dayjs"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
Link
,
useNavigate
,
useParams
}
from
"react-router-dom"
;
import
{
memoService
,
userService
}
from
"../services"
;
import
{
UNKNOWN_ID
}
from
"../helpers/consts"
;
import
{
isNullorUndefined
}
from
"../helpers/utils"
;
import
{
useAppSelector
}
from
"../store"
;
import
useLoading
from
"../hooks/useLoading"
;
import
Only
from
"../components/common/OnlyWhen"
;
import
MemoContent
from
"../components/MemoContent"
;
import
MemoResources
from
"../components/MemoResources"
;
import
"../less/explore.less"
;
interface
State
{
memo
:
Memo
;
}
const
MemoDetail
=
()
=>
{
const
{
t
,
i18n
}
=
useTranslation
();
const
navigate
=
useNavigate
();
const
params
=
useParams
();
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
location
=
useAppSelector
((
state
)
=>
state
.
location
);
const
[
state
,
setState
]
=
useState
<
State
>
({
memo
:
{
id
:
UNKNOWN_ID
,
}
as
Memo
,
});
const
loadingState
=
useLoading
();
useEffect
(()
=>
{
const
{
host
}
=
userService
.
getState
();
if
(
isNullorUndefined
(
host
))
{
navigate
(
"/auth"
);
return
;
}
const
memoId
=
Number
(
params
.
memoId
);
if
(
memoId
&&
!
isNaN
(
memoId
))
{
memoService
.
fetchMemoById
(
memoId
).
then
((
memo
)
=>
{
setState
({
memo
,
});
loadingState
.
setFinish
();
});
}
},
[
location
]);
return
(
<
section
className=
"page-wrapper explore"
>
<
div
className=
"page-container"
>
<
div
className=
"page-header"
>
<
div
className=
"title-container"
>
<
img
className=
"logo-img"
src=
"/logo-full.webp"
alt=
""
/>
</
div
>
<
div
className=
"action-button-container"
>
<
Only
when=
{
!
loadingState
.
isLoading
}
>
{
user
?
(
<
Link
to=
"/"
className=
"btn"
>
<
span
className=
"icon"
>
🏠
</
span
>
{
t
(
"common.back-to-home"
)
}
</
Link
>
)
:
(
<
Link
to=
"/auth"
className=
"btn"
>
<
span
className=
"icon"
>
👉
</
span
>
{
t
(
"common.sign-in"
)
}
</
Link
>
)
}
</
Only
>
</
div
>
</
div
>
{
!
loadingState
.
isLoading
&&
(
<
main
className=
"memos-wrapper"
>
<
div
className=
"memo-container"
>
<
div
className=
"memo-header"
>
<
span
className=
"time-text"
>
{
dayjs
(
state
.
memo
.
createdTs
).
locale
(
i18n
.
language
).
format
(
"YYYY/MM/DD HH:mm:ss"
)
}
</
span
>
<
span
className=
"split-text"
>
by
</
span
>
<
a
className=
"name-text"
href=
{
`/u/${state.memo.creator.id}`
}
>
{
state
.
memo
.
creator
.
name
}
</
a
>
</
div
>
<
MemoContent
className=
"memo-content"
content=
{
state
.
memo
.
content
}
onMemoContentClick=
{
()
=>
undefined
}
/>
<
MemoResources
memo=
{
state
.
memo
}
/>
</
div
>
</
main
>
)
}
</
div
>
</
section
>
);
};
export
default
MemoDetail
;
web/src/router/index.tsx
View file @
15cfc9e1
...
@@ -3,6 +3,7 @@ import { userService } from "../services";
...
@@ -3,6 +3,7 @@ import { userService } from "../services";
import
Auth
from
"../pages/Auth"
;
import
Auth
from
"../pages/Auth"
;
import
Explore
from
"../pages/Explore"
;
import
Explore
from
"../pages/Explore"
;
import
Home
from
"../pages/Home"
;
import
Home
from
"../pages/Home"
;
import
MemoDetail
from
"../pages/MemoDetail"
;
const
router
=
createBrowserRouter
([
const
router
=
createBrowserRouter
([
{
{
...
@@ -42,6 +43,17 @@ const router = createBrowserRouter([
...
@@ -42,6 +43,17 @@ const router = createBrowserRouter([
}
}
},
},
},
},
{
path
:
"/m/:memoId"
,
element
:
<
MemoDetail
/>,
loader
:
async
()
=>
{
try
{
await
userService
.
initialState
();
}
catch
(
error
)
{
// do nth
}
},
},
]);
]);
export
default
router
;
export
default
router
;
web/src/services/memoService.ts
View file @
15cfc9e1
...
@@ -57,6 +57,13 @@ const memoService = {
...
@@ -57,6 +57,13 @@ const memoService = {
return
archivedMemos
;
return
archivedMemos
;
},
},
fetchMemoById
:
async
(
memoId
:
MemoId
)
=>
{
const
{
data
}
=
(
await
api
.
getMemoById
(
memoId
)).
data
;
const
memo
=
convertResponseModelMemo
(
data
);
return
memo
;
},
getMemoById
:
(
memoId
:
MemoId
)
=>
{
getMemoById
:
(
memoId
:
MemoId
)
=>
{
for
(
const
m
of
memoService
.
getState
().
memos
)
{
for
(
const
m
of
memoService
.
getState
().
memos
)
{
if
(
m
.
id
===
memoId
)
{
if
(
m
.
id
===
memoId
)
{
...
...
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