Skip to content

Commit eb95ddf

Browse files
authored
feat: add error page and router permission handling (#358)
1 parent 7f062e8 commit eb95ddf

6 files changed

Lines changed: 59 additions & 11 deletions

File tree

client/public/locales/en/translation.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@
7777
"error": {
7878
"api_url": "API_URL in Pages environment variables should be the Worker address. Please check if API_URL in Pages environment variables is correct.",
7979
"api_url_slash": "API_URL in Pages environment variables should be the Worker address. Please check if API_URL in Pages environment variables is correct and ensure API_URL does not end with a slash (/).",
80-
"github_callback": "GitHub OAuth callback URL should be `https://<Worker address>/user/github/callback`. Please check if the GitHub OAuth callback URL is correct."
80+
"github_callback": "GitHub OAuth callback URL should be `https://<Worker address>/user/github/callback`. Please check if the GitHub OAuth callback URL is correct.",
81+
"not_found": "Page not found",
82+
"permission_denied": "Permission denied",
83+
"title": "Error"
8184
},
8285
"feed_card": {
8386
"published$time": "Published at {{time}}",

client/public/locales/ja/translation.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@
7777
"error": {
7878
"api_url": "Pages 環境変数のAPI_URLはWorkerアドレスである必要があります。Pages環境変数のAPI_URLが正しいか確認してください。",
7979
"api_url_slash": "Pages 環境変数のAPI_URLはWorkerアドレスである必要があります。Pages環境変数のAPI_URLが正しいか、またAPI_URLの末尾にスラッシュ(/)がないか確認してください。",
80-
"github_callback": "GitHub OAuthコールバックURLは`https://<Workerアドレス>/user/github/callback`である必要があります。GitHub OAuthコールバックURLが正しいか確認してください。"
80+
"github_callback": "GitHub OAuthコールバックURLは`https://<Workerアドレス>/user/github/callback`である必要があります。GitHub OAuthコールバックURLが正しいか確認してください。",
81+
"not_found": "ページが見つかりません",
82+
"permission_denied": "権限がありません",
83+
"title": "エラー"
8184
},
8285
"feed_card": {
8386
"published$time": "{{time}} に公開",

client/public/locales/zh-CN/translation.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@
7777
"error": {
7878
"api_url": "Pages 环境变量中 API_URL 应为 Worker 地址,请检查 Pages 环境变量中 API_URL 是否正确",
7979
"api_url_slash": "Pages 环境变量中 API_URL 应为 Worker 地址,请检查 Pages 环境变量中 API_URL 是否正确,且 API_URL 末尾不能有 /",
80-
"github_callback": "GitHub OAuth 回调地址应为 `https://<Worker 地址>/user/github/callback,请检查 GitHub OAuth 回调地址是否正确"
80+
"github_callback": "GitHub OAuth 回调地址应为 `https://<Worker 地址>/user/github/callback,请检查 GitHub OAuth 回调地址是否正确",
81+
"not_found": "页面未找到",
82+
"permission_denied": "权限不足",
83+
"title": "错误"
8184
},
8285
"feed_card": {
8386
"published$time": "{{time}} 发布",

client/public/locales/zh-TW/translation.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@
7777
"error": {
7878
"api_url": "Pages 環境變數中 API_URL 應為 Worker 地址,請檢查 Pages 環境變數中 API_URL 是否正確",
7979
"api_url_slash": "Pages 環境變數中 API_URL 應為 Worker 地址,請檢查 Pages 環境變數中 API_URL 是否正確,且 API_URL 末尾不能有 /",
80-
"github_callback": "GitHub OAuth 回調地址應為 `https://<Worker 地址>/user/github/callback,請檢查 GitHub OAuth 回調地址是否正確"
80+
"github_callback": "GitHub OAuth 回調地址應為 `https://<Worker 地址>/user/github/callback,請檢查 GitHub OAuth 回調地址是否正確",
81+
"not_found": "頁面未找到",
82+
"permission_denied": "權限不足",
83+
"title": "錯誤"
8184
},
8285
"feed_card": {
8386
"published$time": "{{time}} 發布",

client/src/App.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useRef, useState } from 'react'
1+
import { useEffect, useRef, useState, useContext } from 'react'
22
import { Helmet } from 'react-helmet'
33
import { getCookie } from 'typescript-cookie'
44
import { DefaultParams, PathPattern, Route, Switch } from 'wouter'
@@ -24,6 +24,7 @@ import { SearchPage } from './page/search.tsx'
2424
import { Tips, TipsPage } from './components/tips.tsx'
2525
import { useTranslation } from 'react-i18next'
2626
import { MomentsPage } from './page/moments'
27+
import { ErrorPage } from './page/error.tsx'
2728

2829
function App() {
2930
const ref = useRef(false)
@@ -104,16 +105,16 @@ function App() {
104105
}}
105106
</RouteMe>
106107

107-
<RouteMe path="/settings" paddingClassName='mx-4'>
108+
<RouteMe path="/settings" paddingClassName='mx-4' requirePermission>
108109
<Settings />
109110
</RouteMe>
110111

111112

112-
<RouteMe path="/writing" paddingClassName='mx-4'>
113+
<RouteMe path="/writing" paddingClassName='mx-4' requirePermission>
113114
<WritingPage />
114115
</RouteMe>
115116

116-
<RouteMe path="/writing/:id" paddingClassName='mx-4'>
117+
<RouteMe path="/writing/:id" paddingClassName='mx-4' requirePermission>
117118
{({ id }) => {
118119
const id_num = tryInt(0, id)
119120
return (
@@ -165,16 +166,24 @@ function App() {
165166
</RouteMe>
166167

167168
{/* Default route in a switch */}
168-
<Route>404: No such page!</Route>
169+
<RouteMe>
170+
<ErrorPage error={t('error.not_found')} />
171+
</RouteMe>
169172
</Switch>
170173
</ProfileContext.Provider>
171174
</ClientConfigContext.Provider>
172175
</>
173176
)
174177
}
175178

176-
function RouteMe({ path, children, headerComponent, paddingClassName }:
177-
{ path: PathPattern, children: React.ReactNode | ((params: DefaultParams) => React.ReactNode), headerComponent?: React.ReactNode, paddingClassName?: string }) {
179+
function RouteMe({ path, children, headerComponent, paddingClassName, requirePermission }:
180+
{ path?: PathPattern, children: React.ReactNode | ((params: DefaultParams) => React.ReactNode), headerComponent?: React.ReactNode, paddingClassName?: string, requirePermission?: boolean }) {
181+
if (requirePermission) {
182+
const profile = useContext(ProfileContext);
183+
const { t } = useTranslation();
184+
if (!profile?.permission)
185+
children = <ErrorPage error={t('error.permission_denied')} />;
186+
}
178187
return (
179188
<Route path={path} >
180189
{params => {

client/src/page/error.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { useTranslation } from 'react-i18next'
2+
import { Button } from '../components/button'
3+
import { Helmet } from 'react-helmet'
4+
import { siteName } from '../utils/constants'
5+
6+
export function ErrorPage({error}: {error?: string}) {
7+
const { t } = useTranslation()
8+
return (
9+
<>
10+
<Helmet>
11+
<title>{`${t('error.title')} - ${process.env.NAME}`}</title>
12+
<meta property="og:site_name" content={siteName} />
13+
<meta property="og:title" content={t('error.title')} />
14+
<meta property="og:image" content={process.env.AVATAR} />
15+
</Helmet>
16+
<div className="w-full flex flex-row justify-center ani-show">
17+
<div className="flex flex-col wauto rounded-2xl bg-w m-2 p-6 items-center justify-center space-y-2">
18+
<h1 className="text-xl font-bold t-primary">{error}</h1>
19+
<Button
20+
title={t("index.back")}
21+
onClick={() => (window.location.href = "/")}
22+
/>
23+
</div>
24+
</div>
25+
</>
26+
);
27+
}

0 commit comments

Comments
 (0)