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
307483e4
Commit
307483e4
authored
Sep 19, 2022
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: use `react-router`
parent
4608894e
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
155 additions
and
149 deletions
+155
-149
App.tsx
web/src/App.tsx
+6
-15
MenuBtnsPopup.tsx
web/src/components/MenuBtnsPopup.tsx
+4
-3
Sidebar.tsx
web/src/components/Sidebar.tsx
+4
-7
utils.ts
web/src/helpers/utils.ts
+5
-1
explore.less
web/src/less/explore.less
+1
-1
main.tsx
web/src/main.tsx
+5
-8
Auth.tsx
web/src/pages/Auth.tsx
+5
-3
Explore.tsx
web/src/pages/Explore.tsx
+26
-28
Home.tsx
web/src/pages/Home.tsx
+52
-52
index.tsx
web/src/router/index.tsx
+47
-0
appRouter.tsx
web/src/routers/appRouter.tsx
+0
-11
index.ts
web/src/routers/index.ts
+0
-20
No files found.
web/src/App.tsx
View file @
307483e4
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useEffect
}
from
"react"
;
import
{
RouterProvider
}
from
"react-router-dom"
;
import
useI18n
from
"./hooks/useI18n"
;
import
{
appRouterSwitch
}
from
"./routers"
;
import
{
globalService
,
locationService
}
from
"./services"
;
import
{
useAppSelector
}
from
"./store"
;
import
router
from
"./router"
;
import
*
as
storage
from
"./helpers/storage"
;
function
App
()
{
const
{
setLocale
}
=
useI18n
();
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
global
=
useAppSelector
((
state
)
=>
state
.
global
);
const
pathname
=
useAppSelector
((
state
)
=>
state
.
location
.
pathname
);
const
[
isLoading
,
setLoading
]
=
useState
(
true
);
useEffect
(()
=>
{
locationService
.
updateStateWithLocation
();
window
.
onpopstate
=
()
=>
{
locationService
.
updateStateWithLocation
();
};
globalService
.
initialState
().
then
(()
=>
{
setLoading
(
false
);
});
},
[]);
useEffect
(()
=>
{
if
(
user
?.
setting
.
locale
)
{
globalService
.
setLocale
(
user
.
setting
.
locale
);
}
},
[
user
?.
setting
.
locale
]);
globalService
.
initialState
();
},
[]);
useEffect
(()
=>
{
setLocale
(
global
.
locale
);
...
...
@@ -35,7 +26,7 @@ function App() {
});
},
[
global
.
locale
]);
return
<
>
{
isLoading
?
null
:
appRouterSwitch
(
pathname
)
}
<
/>;
return
<
RouterProvider
router=
{
router
}
/>;
}
export
default
App
;
web/src/components/MenuBtnsPopup.tsx
View file @
307483e4
import
{
useEffect
,
useRef
}
from
"react"
;
import
{
locationService
,
userService
}
from
"../services"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
userService
}
from
"../services"
;
import
useI18n
from
"../hooks/useI18n"
;
import
Only
from
"./common/OnlyWhen"
;
import
showAboutSiteDialog
from
"./AboutSiteDialog"
;
...
...
@@ -15,6 +16,7 @@ interface Props {
const
MenuBtnsPopup
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
shownStatus
,
setShownStatus
}
=
props
;
const
{
t
}
=
useI18n
();
const
navigate
=
useNavigate
();
const
popupElRef
=
useRef
<
HTMLDivElement
>
(
null
);
useEffect
(()
=>
{
...
...
@@ -48,8 +50,7 @@ const MenuBtnsPopup: React.FC<Props> = (props: Props) => {
userService
.
doSignOut
()
.
then
(()
=>
{
locationService
.
replaceHistory
(
"/auth"
);
window
.
location
.
reload
();
navigate
(
"/auth"
);
})
.
catch
(()
=>
{
// do nth
...
...
web/src/components/Sidebar.tsx
View file @
307483e4
import
{
locationService
,
userService
}
from
"../services"
;
import
{
Link
}
from
"react-router-dom"
;
import
{
userService
}
from
"../services"
;
import
useI18n
from
"../hooks/useI18n"
;
import
Icon
from
"./Icon"
;
import
Only
from
"./common/OnlyWhen"
;
...
...
@@ -17,10 +18,6 @@ const Sidebar = () => {
showSettingDialog
();
};
const
handleExploreBtnClick
=
()
=>
{
locationService
.
pushHistory
(
"/explore"
);
};
return
(
<
aside
className=
"sidebar-wrapper"
>
<
div
className=
"close-container"
>
...
...
@@ -35,9 +32,9 @@ const Sidebar = () => {
<
span
className=
"icon"
>
📅
</
span
>
{
t
(
"sidebar.daily-review"
)
}
</
button
>
<
Only
when=
{
!
userService
.
isVisitorMode
()
}
>
<
button
className=
"btn action-btn"
onClick=
{
()
=>
handleExploreBtnClick
()
}
>
<
Link
to=
"/explore"
className=
"btn action-btn"
>
<
span
className=
"icon"
>
🏂
</
span
>
{
t
(
"common.explore"
)
}
</
button
>
</
Link
>
<
button
className=
"btn action-btn"
onClick=
{
handleSettingBtnClick
}
>
<
span
className=
"icon"
>
⚙️
</
span
>
{
t
(
"sidebar.setting"
)
}
</
button
>
...
...
web/src/helpers/utils.ts
View file @
307483e4
import
{
assign
}
from
"lodash-es"
;
import
{
assign
,
isNull
,
isUndefined
}
from
"lodash-es"
;
export
const
isNullorUndefined
=
(
value
:
any
)
=>
{
return
isNull
(
value
)
||
isUndefined
(
value
);
};
export
function
getNowTimeStamp
():
number
{
return
Date
.
now
();
...
...
web/src/less/explore.less
View file @
307483e4
...
...
@@ -25,7 +25,7 @@
> .action-button-container {
> .btn {
@apply
text-gray-600 font-mono text-base py-1 border px-3
rounded-xl hover:opacity-80 hover:underline;
@apply
block text-gray-600 font-mono text-base py-1 border px-3 leading-8
rounded-xl hover:opacity-80 hover:underline;
> .icon {
@apply text-lg;
...
...
web/src/main.tsx
View file @
307483e4
import
{
createRoot
}
from
"react-dom/client"
;
import
{
Provider
}
from
"react-redux"
;
import
{
BrowserRouter
}
from
"react-router-dom"
;
import
I18nProvider
from
"./labs/i18n/I18nProvider"
;
import
store
from
"./store"
;
import
App
from
"./App"
;
...
...
@@ -11,11 +10,9 @@ import "./css/index.css";
const
container
=
document
.
getElementById
(
"root"
);
const
root
=
createRoot
(
container
as
HTMLElement
);
root
.
render
(
<
BrowserRouter
>
<
I18nProvider
>
<
Provider
store=
{
store
}
>
<
App
/>
</
Provider
>
</
I18nProvider
>
</
BrowserRouter
>
<
I18nProvider
>
<
Provider
store=
{
store
}
>
<
App
/>
</
Provider
>
</
I18nProvider
>
);
web/src/pages/Auth.tsx
View file @
307483e4
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
*
as
api
from
"../helpers/api"
;
import
{
validate
,
ValidatorConfig
}
from
"../helpers/validator"
;
import
useI18n
from
"../hooks/useI18n"
;
import
useLoading
from
"../hooks/useLoading"
;
import
{
globalService
,
locationService
,
userService
}
from
"../services"
;
import
{
globalService
,
userService
}
from
"../services"
;
import
Icon
from
"../components/Icon"
;
import
Only
from
"../components/common/OnlyWhen"
;
import
toastHelper
from
"../components/Toast"
;
...
...
@@ -18,6 +19,7 @@ const validateConfig: ValidatorConfig = {
const
Auth
=
()
=>
{
const
{
t
,
locale
}
=
useI18n
();
const
navigate
=
useNavigate
();
const
pageLoadingState
=
useLoading
(
true
);
const
[
siteHost
,
setSiteHost
]
=
useState
<
User
>
();
const
[
email
,
setEmail
]
=
useState
(
""
);
...
...
@@ -68,7 +70,7 @@ const Auth = () => {
await
api
.
signin
(
email
,
password
);
const
user
=
await
userService
.
doSignIn
();
if
(
user
)
{
locationService
.
replaceHistory
(
"/"
);
navigate
(
"/"
);
}
else
{
toastHelper
.
error
(
t
(
"message.login-failed"
));
}
...
...
@@ -101,7 +103,7 @@ const Auth = () => {
await
api
.
signup
(
email
,
password
,
"HOST"
);
const
user
=
await
userService
.
doSignIn
();
if
(
user
)
{
locationService
.
replaceHistory
(
"/"
);
navigate
(
"/"
);
}
else
{
toastHelper
.
error
(
t
(
"common.singup-failed"
));
}
...
...
web/src/pages/Explore.tsx
View file @
307483e4
import
dayjs
from
"dayjs"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
locationService
,
memoService
,
userService
}
from
"../services"
;
import
{
Link
,
useNavigate
}
from
"react-router-dom"
;
import
{
memoService
,
userService
}
from
"../services"
;
import
{
isNullorUndefined
}
from
"../helpers/utils"
;
import
{
useAppSelector
}
from
"../store"
;
import
useI18n
from
"../hooks/useI18n"
;
import
useQuery
from
"../hooks/useQuery"
;
...
...
@@ -16,6 +18,7 @@ interface State {
const
Explore
=
()
=>
{
const
{
t
,
locale
}
=
useI18n
();
const
navigate
=
useNavigate
();
const
query
=
useQuery
();
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
location
=
useAppSelector
((
state
)
=>
state
.
location
);
...
...
@@ -25,33 +28,28 @@ const Explore = () => {
const
loadingState
=
useLoading
();
useEffect
(()
=>
{
userService
.
initialState
()
.
catch
()
.
finally
(
async
()
=>
{
const
{
host
}
=
userService
.
getState
();
if
(
!
host
)
{
locationService
.
replaceHistory
(
"/auth"
);
return
;
}
const
{
host
}
=
userService
.
getState
();
if
(
isNullorUndefined
(
host
))
{
navigate
(
"/auth"
);
return
;
}
memoService
.
fetchAllMemos
().
then
((
memos
)
=>
{
let
filteredMemos
=
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
({
...
state
,
memos
:
filteredMemos
,
});
const
memoId
=
Number
(
query
.
get
(
"memoId"
));
if
(
memoId
&&
!
isNaN
(
memoId
))
{
filteredMemos
=
filteredMemos
.
filter
((
memo
)
=>
{
return
memo
.
id
===
memoId
;
});
loadingState
.
setFinish
();
}
setState
({
...
state
,
memos
:
filteredMemos
,
});
loadingState
.
setFinish
();
});
},
[
location
]);
return
(
...
...
@@ -65,13 +63,13 @@ const Explore = () => {
<
div
className=
"action-button-container"
>
<
Only
when=
{
!
loadingState
.
isLoading
}
>
{
user
?
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/"
)
}
>
<
Link
to=
"/"
className=
"btn"
>
<
span
className=
"icon"
>
🏠
</
span
>
{
t
(
"common.back-to-home"
)
}
</
button
>
</
Link
>
)
:
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/auth"
)
}
>
<
Link
to=
"/auth"
className=
"btn"
>
<
span
className=
"icon"
>
👉
</
span
>
{
t
(
"common.sign-in"
)
}
</
button
>
</
Link
>
)
}
</
Only
>
</
div
>
...
...
web/src/pages/Home.tsx
View file @
307483e4
import
{
useEffect
}
from
"react"
;
import
{
locationService
,
userService
}
from
"../services"
;
import
{
useLocation
,
useNavigate
}
from
"react-router-dom"
;
import
{
globalService
,
userService
}
from
"../services"
;
import
{
useAppSelector
}
from
"../store"
;
import
useI18n
from
"../hooks/useI18n"
;
import
useLoading
from
"../hooks/useLoading
"
;
import
{
isNullorUndefined
}
from
"../helpers/utils
"
;
import
Only
from
"../components/common/OnlyWhen"
;
import
toastHelper
from
"../components/Toast"
;
import
Sidebar
from
"../components/Sidebar"
;
import
MemosHeader
from
"../components/MemosHeader"
;
import
MemoEditor
from
"../components/MemoEditor"
;
import
MemoFilter
from
"../components/MemoFilter"
;
import
MemoList
from
"../components/MemoList"
;
import
toastHelper
from
"../components/Toast"
;
import
"../less/home.less"
;
function
Home
()
{
const
{
t
}
=
useI18n
();
const
location
=
useLocation
();
const
navigate
=
useNavigate
();
const
user
=
useAppSelector
((
state
)
=>
state
.
user
.
user
);
const
location
=
useAppSelector
((
state
)
=>
state
.
location
);
const
loadingState
=
useLoading
();
useEffect
(()
=>
{
userService
.
initialState
()
.
catch
()
.
finally
(
async
()
=>
{
const
{
host
,
owner
,
user
}
=
userService
.
getState
();
if
(
!
host
)
{
locationService
.
replaceHistory
(
"/auth"
);
return
;
}
const
{
host
,
owner
,
user
}
=
userService
.
getState
();
if
(
userService
.
isVisitorMode
())
{
if
(
!
owner
)
{
toastHelper
.
error
(
t
(
"message.user-not-found"
));
}
}
else
{
if
(
!
user
)
{
locationService
.
replaceHistory
(
`/explore`
);
}
}
loadingState
.
setFinish
();
});
if
(
isNullorUndefined
(
host
))
{
navigate
(
"/auth"
);
return
;
}
if
(
userService
.
isVisitorMode
())
{
if
(
!
owner
)
{
toastHelper
.
error
(
t
(
"message.user-not-found"
));
}
}
else
{
if
(
isNullorUndefined
(
user
))
{
navigate
(
"/explore"
);
}
}
},
[
location
]);
useEffect
(()
=>
{
if
(
user
?.
setting
.
locale
)
{
globalService
.
setLocale
(
user
.
setting
.
locale
);
}
},
[
user
?.
setting
.
locale
]);
return
(
<
section
className=
"page-wrapper home"
>
{
loadingState
.
isLoading
?
null
:
(
<
div
className=
"page-container"
>
<
Sidebar
/>
<
main
className=
"memos-wrapper"
>
<
div
className=
"memos-editor-wrapper"
>
<
MemosHeader
/>
<
Only
when=
{
!
userService
.
isVisitorMode
()
}
>
<
MemoEditor
/>
</
Only
>
<
MemoFilter
/>
</
div
>
<
MemoList
/>
<
Only
when=
{
userService
.
isVisitorMode
()
}
>
<
div
className=
"addtion-btn-container"
>
{
user
?
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/"
)
}
>
<
span
className=
"icon"
>
🏠
</
span
>
{
t
(
"common.back-to-home"
)
}
</
button
>
)
:
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/auth"
)
}
>
<
span
className=
"icon"
>
👉
</
span
>
{
t
(
"common.sign-in"
)
}
</
button
>
)
}
</
div
>
<
div
className=
"page-container"
>
<
Sidebar
/>
<
main
className=
"memos-wrapper"
>
<
div
className=
"memos-editor-wrapper"
>
<
MemosHeader
/>
<
Only
when=
{
!
userService
.
isVisitorMode
()
}
>
<
MemoEditor
/>
</
Only
>
</
main
>
</
div
>
)
}
<
MemoFilter
/>
</
div
>
<
MemoList
/>
<
Only
when=
{
userService
.
isVisitorMode
()
}
>
<
div
className=
"addtion-btn-container"
>
{
user
?
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/"
)
}
>
<
span
className=
"icon"
>
🏠
</
span
>
{
t
(
"common.back-to-home"
)
}
</
button
>
)
:
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/auth"
)
}
>
<
span
className=
"icon"
>
👉
</
span
>
{
t
(
"common.sign-in"
)
}
</
button
>
)
}
</
div
>
</
Only
>
</
main
>
</
div
>
</
section
>
);
}
...
...
web/src/router/index.tsx
0 → 100644
View file @
307483e4
import
{
createBrowserRouter
}
from
"react-router-dom"
;
import
{
userService
}
from
"../services"
;
import
Auth
from
"../pages/Auth"
;
import
Explore
from
"../pages/Explore"
;
import
Home
from
"../pages/Home"
;
const
router
=
createBrowserRouter
([
{
path
:
"/"
,
element
:
<
Home
/>,
loader
:
async
()
=>
{
try
{
await
userService
.
initialState
();
}
catch
(
error
)
{
// do nth
}
},
},
{
path
:
"/auth"
,
element
:
<
Auth
/>,
},
{
path
:
"/u/:userId"
,
element
:
<
Home
/>,
loader
:
async
()
=>
{
try
{
await
userService
.
initialState
();
}
catch
(
error
)
{
// do nth
}
},
},
{
path
:
"/explore"
,
element
:
<
Explore
/>,
loader
:
async
()
=>
{
try
{
await
userService
.
initialState
();
}
catch
(
error
)
{
// do nth
}
},
},
]);
export
default
router
;
web/src/routers/appRouter.tsx
deleted
100644 → 0
View file @
4608894e
import
Home
from
"../pages/Home"
;
import
Auth
from
"../pages/Auth"
;
import
Explore
from
"../pages/Explore"
;
const
appRouter
=
{
"/auth"
:
<
Auth
/>
,
"/explore"
:
<
Explore
/>
,
"*"
:
<
Home
/>
,
};
export
default
appRouter
;
web/src/routers/index.ts
deleted
100644 → 0
View file @
4608894e
import
appRouter
from
"./appRouter"
;
// just like React-Router
interface
Router
{
[
key
:
string
]:
JSX
.
Element
|
null
;
"*"
:
JSX
.
Element
|
null
;
}
const
routerSwitch
=
(
router
:
Router
)
=>
{
return
(
pathname
:
string
)
=>
{
for
(
const
key
of
Object
.
keys
(
router
))
{
if
(
key
===
pathname
)
{
return
router
[
key
];
}
}
return
router
[
"*"
];
};
};
export
const
appRouterSwitch
=
routerSwitch
(
appRouter
);
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