+3
-2
@@ -1,4 +1,5 @@
|
||||
TSC_COMPILE_ON_ERROR=true
|
||||
ESLINT_NO_DEV_ERRORS=true
|
||||
PUBLIC_URL = /
|
||||
REACT_APP_API_URL = /
|
||||
PUBLIC_URL=/
|
||||
REACT_APP_API_URL=/
|
||||
REACT_APP_BASE_URL=/test
|
||||
|
||||
+2
-1
@@ -5,7 +5,7 @@
|
||||
"homepage": "/",
|
||||
"scripts": {
|
||||
"start": "react-app-rewired start",
|
||||
"build": "react-app-rewired build",
|
||||
"build": "node ./scripts/env.js && react-app-rewired build",
|
||||
"lint": "eslint . --cache --fix --ext .ts,.tsx",
|
||||
"prettier": "prettier --write 'src/**/*.{js,jsx,ts,tsx,json,css,scss,md}' --config ./.prettierrc.json",
|
||||
"pre-install": "node ./scripts/preinstall.js && pnpm install",
|
||||
@@ -76,6 +76,7 @@
|
||||
"eslint-plugin-react-hooks": "^4.6.0",
|
||||
"humps": "^2.0.1",
|
||||
"husky": "^8.0.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"lint-staged": "^13.2.3",
|
||||
"postcss": "^8.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
|
||||
Generated
+98
-33
@@ -1,20 +1,3 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
@@ -200,6 +183,9 @@ importers:
|
||||
husky:
|
||||
specifier: ^8.0.1
|
||||
version: 8.0.1
|
||||
js-yaml:
|
||||
specifier: ^4.1.0
|
||||
version: 4.1.0
|
||||
lint-staged:
|
||||
specifier: ^13.2.3
|
||||
version: 13.3.0
|
||||
@@ -231,6 +217,64 @@ importers:
|
||||
specifier: ^0.8.0
|
||||
version: 0.8.0
|
||||
|
||||
src/plugins/captcha-basic:
|
||||
devDependencies:
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^6.0.0
|
||||
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.3.2)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^6.0.0
|
||||
version: 6.11.0(eslint@8.53.0)(typescript@5.3.2)
|
||||
'@vitejs/plugin-react-swc':
|
||||
specifier: ^3.3.2
|
||||
version: 3.5.0(vite@4.5.0)
|
||||
eslint:
|
||||
specifier: ^8.45.0
|
||||
version: 8.53.0
|
||||
eslint-plugin-react-hooks:
|
||||
specifier: ^4.6.0
|
||||
version: 4.6.0(eslint@8.53.0)
|
||||
eslint-plugin-react-refresh:
|
||||
specifier: ^0.4.3
|
||||
version: 0.4.5(eslint@8.53.0)
|
||||
typescript:
|
||||
specifier: ^5.0.2
|
||||
version: 5.3.2
|
||||
vite:
|
||||
specifier: ^4.4.5
|
||||
version: 4.5.0(@types/node@16.11.59)(sass@1.54.9)
|
||||
|
||||
src/plugins/captcha-google-v2:
|
||||
dependencies:
|
||||
react-google-recaptcha:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0(react@18.2.0)
|
||||
devDependencies:
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^6.0.0
|
||||
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.3.2)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^6.0.0
|
||||
version: 6.11.0(eslint@8.53.0)(typescript@5.3.2)
|
||||
'@vitejs/plugin-react-swc':
|
||||
specifier: ^3.3.2
|
||||
version: 3.5.0(vite@4.5.0)
|
||||
eslint:
|
||||
specifier: ^8.45.0
|
||||
version: 8.53.0
|
||||
eslint-plugin-react-hooks:
|
||||
specifier: ^4.6.0
|
||||
version: 4.6.0(eslint@8.53.0)
|
||||
eslint-plugin-react-refresh:
|
||||
specifier: ^0.4.3
|
||||
version: 0.4.5(eslint@8.53.0)
|
||||
typescript:
|
||||
specifier: ^5.0.2
|
||||
version: 5.3.2
|
||||
vite:
|
||||
specifier: ^4.4.5
|
||||
version: 4.5.0(@types/node@16.11.59)(sass@1.54.9)
|
||||
|
||||
src/plugins/editor-chart:
|
||||
dependencies:
|
||||
mermaid:
|
||||
@@ -3072,7 +3116,7 @@ packages:
|
||||
resolution: {integrity: sha512-/fqTbjxyFUaYNO7VcW5g+4npmqVACz1bB7RTHYuLj+PRjw9hrCwrUXVQFpChUS0JsyEFvMZ7U/PfmvWgxJhI9g==}
|
||||
dependencies:
|
||||
'@types/estree': 1.0.0
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
/@types/eslint@8.56.2:
|
||||
resolution: {integrity: sha512-uQDwm1wFHmbBbCZCqAlq6Do9LYwByNZHWzXppSnay9SuwJ+VRbjkbLABer54kcPnMSlG6Fdiy2yaFXm/z9Z5gw==}
|
||||
@@ -3149,12 +3193,8 @@ packages:
|
||||
pretty-format: 27.5.1
|
||||
dev: true
|
||||
|
||||
/@types/json-schema@7.0.13:
|
||||
resolution: {integrity: sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==}
|
||||
|
||||
/@types/json-schema@7.0.15:
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
dev: true
|
||||
|
||||
/@types/json5@0.0.29:
|
||||
resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==}
|
||||
@@ -3594,7 +3634,7 @@ packages:
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
'@typescript-eslint/scope-manager': 5.38.0
|
||||
'@typescript-eslint/types': 5.38.0
|
||||
'@typescript-eslint/typescript-estree': 5.38.0(typescript@4.9.5)
|
||||
@@ -3612,7 +3652,7 @@ packages:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
'@types/semver': 7.5.5
|
||||
'@typescript-eslint/scope-manager': 6.11.0
|
||||
'@typescript-eslint/types': 6.11.0
|
||||
@@ -3631,7 +3671,7 @@ packages:
|
||||
eslint: ^7.0.0 || ^8.0.0
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
'@types/semver': 7.5.5
|
||||
'@typescript-eslint/scope-manager': 6.11.0
|
||||
'@typescript-eslint/types': 6.11.0
|
||||
@@ -3950,7 +3990,6 @@ packages:
|
||||
resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/acorn@8.8.0:
|
||||
resolution: {integrity: sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==}
|
||||
@@ -6954,7 +6993,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.18.6
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
chalk: 4.1.2
|
||||
chokidar: 3.5.3
|
||||
cosmiconfig: 6.0.0
|
||||
@@ -7262,6 +7301,12 @@ packages:
|
||||
resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==}
|
||||
dev: false
|
||||
|
||||
/hoist-non-react-statics@3.3.2:
|
||||
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||
dependencies:
|
||||
react-is: 16.13.1
|
||||
dev: false
|
||||
|
||||
/hoopy@0.1.4:
|
||||
resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==}
|
||||
engines: {node: '>= 6.0.0'}
|
||||
@@ -8421,7 +8466,7 @@ packages:
|
||||
optional: true
|
||||
dependencies:
|
||||
abab: 2.0.6
|
||||
acorn: 8.10.0
|
||||
acorn: 8.11.3
|
||||
acorn-globals: 6.0.0
|
||||
cssom: 0.4.4
|
||||
cssstyle: 2.3.0
|
||||
@@ -10282,6 +10327,16 @@ packages:
|
||||
semver: 5.7.1
|
||||
dev: true
|
||||
|
||||
/react-async-script@1.2.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-bCpkbm9JiAuMGhkqoAiC0lLkb40DJ0HOEJIku+9JDjxX3Rcs+ztEOG13wbrOskt3n2DTrjshhaQ/iay+SnGg5Q==}
|
||||
peerDependencies:
|
||||
react: '>=16.4.1'
|
||||
dependencies:
|
||||
hoist-non-react-statics: 3.3.2
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-bootstrap@2.10.0(@types/react@18.0.20)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-87gRP69VAfeU2yKgp8RI3HvzhPNrnYIV2QNranYXataz3ef+k7OhvKGGdxQLQfUsQ2RTmlY66tn4pdFrZ94hNg==}
|
||||
peerDependencies:
|
||||
@@ -10366,6 +10421,16 @@ packages:
|
||||
resolution: {integrity: sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==}
|
||||
dev: false
|
||||
|
||||
/react-google-recaptcha@3.1.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-cYW2/DWas8nEKZGD7SCu9BSuVz8iOcOLHChHyi7upUuVhkpkhYG/6N3KDiTQ3XAiZ2UAZkfvYKMfAHOzBOcGEg==}
|
||||
peerDependencies:
|
||||
react: '>=16.4.1'
|
||||
dependencies:
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
react-async-script: 1.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/react-helmet-async@1.3.0(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==}
|
||||
peerDependencies:
|
||||
@@ -10947,7 +11012,7 @@ packages:
|
||||
resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==}
|
||||
engines: {node: '>= 8.9.0'}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
ajv: 6.12.6
|
||||
ajv-keywords: 3.5.2(ajv@6.12.6)
|
||||
|
||||
@@ -10955,7 +11020,7 @@ packages:
|
||||
resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==}
|
||||
engines: {node: '>= 8.9.0'}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
ajv: 6.12.6
|
||||
ajv-keywords: 3.5.2(ajv@6.12.6)
|
||||
|
||||
@@ -10963,7 +11028,7 @@ packages:
|
||||
resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
ajv: 6.12.6
|
||||
ajv-keywords: 3.5.2(ajv@6.12.6)
|
||||
|
||||
@@ -10980,7 +11045,7 @@ packages:
|
||||
resolution: {integrity: sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==}
|
||||
engines: {node: '>= 12.13.0'}
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.13
|
||||
'@types/json-schema': 7.0.15
|
||||
ajv: 8.11.0
|
||||
ajv-formats: 2.1.1(ajv@8.11.0)
|
||||
ajv-keywords: 5.1.0(ajv@8.11.0)
|
||||
@@ -11713,7 +11778,7 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@jridgewell/source-map': 0.3.2
|
||||
acorn: 8.10.0
|
||||
acorn: 8.11.3
|
||||
commander: 2.20.3
|
||||
source-map-support: 0.5.21
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const configFilePath = path.resolve(__dirname, '../../configs/config.yaml');
|
||||
const envFilePath = path.resolve(__dirname, '../.env.production');
|
||||
|
||||
// Read config.yaml file
|
||||
const config = yaml.load(fs.readFileSync(configFilePath, 'utf8'));
|
||||
|
||||
// Generate .env file content
|
||||
let envContent = 'TSC_COMPILE_ON_ERROR=true\nESLINT_NO_DEV_ERRORS=true\n';
|
||||
for (const key in config.ui) {
|
||||
const value = config.ui[key];
|
||||
envContent += `${key.toUpperCase()}=${value}\n`;
|
||||
}
|
||||
|
||||
// Write .env file
|
||||
fs.writeFileSync(envFilePath, envContent);
|
||||
|
||||
console.log(`Generated ${envFilePath}`);
|
||||
+3
-1
@@ -25,7 +25,9 @@ import '@/utils/pluginKit';
|
||||
import routes from '@/router';
|
||||
|
||||
function App() {
|
||||
const router = createBrowserRouter(routes);
|
||||
const router = createBrowserRouter(routes, {
|
||||
basename: process.env.REACT_APP_BASE_URL,
|
||||
});
|
||||
return <RouterProvider router={router} />;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import {
|
||||
Nav,
|
||||
Form,
|
||||
FormControl,
|
||||
Button,
|
||||
Col,
|
||||
} from 'react-bootstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -175,24 +174,26 @@ const Header: FC = () => {
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
variant="link"
|
||||
className={classnames('me-2', {
|
||||
<Link
|
||||
className={classnames('me-2 btn btn-link', {
|
||||
'link-light': navbarStyle === 'theme-colored',
|
||||
'link-primary': navbarStyle !== 'theme-colored',
|
||||
})}
|
||||
onClick={() => floppyNavigation.storageLoginRedirect()}
|
||||
href={userCenter.getLoginUrl()}>
|
||||
to={userCenter.getLoginUrl()}>
|
||||
{t('btns.login')}
|
||||
</Button>
|
||||
</Link>
|
||||
{loginSetting.allow_new_registrations && (
|
||||
<Button
|
||||
variant={
|
||||
navbarStyle === 'theme-colored' ? 'light' : 'primary'
|
||||
}
|
||||
href={userCenter.getSignUpUrl()}>
|
||||
<Link
|
||||
className={classnames(
|
||||
'btn',
|
||||
navbarStyle === 'theme-colored'
|
||||
? 'btn-light'
|
||||
: 'btn-primary',
|
||||
)}
|
||||
to={userCenter.getSignUpUrl()}>
|
||||
{t('btns.signup')}
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
@@ -249,24 +250,26 @@ const Header: FC = () => {
|
||||
</Nav>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
variant="link"
|
||||
className={classnames('me-2', {
|
||||
<Link
|
||||
className={classnames('me-2 btn btn-link', {
|
||||
'link-light': navbarStyle === 'theme-colored',
|
||||
'link-primary': navbarStyle !== 'theme-colored',
|
||||
})}
|
||||
onClick={() => floppyNavigation.storageLoginRedirect()}
|
||||
href={userCenter.getLoginUrl()}>
|
||||
to={userCenter.getLoginUrl()}>
|
||||
{t('btns.login')}
|
||||
</Button>
|
||||
</Link>
|
||||
{loginSetting.allow_new_registrations && (
|
||||
<Button
|
||||
variant={
|
||||
navbarStyle === 'theme-colored' ? 'light' : 'primary'
|
||||
}
|
||||
href={userCenter.getSignUpUrl()}>
|
||||
<Link
|
||||
className={classnames(
|
||||
'btn',
|
||||
navbarStyle === 'theme-colored'
|
||||
? 'btn-light'
|
||||
: 'btn-primary',
|
||||
)}
|
||||
to={userCenter.getSignUpUrl()}>
|
||||
{t('btns.signup')}
|
||||
</Button>
|
||||
</Link>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import { FC, useEffect, useLayoutEffect } from 'react';
|
||||
import { Helmet } from 'react-helmet-async';
|
||||
|
||||
import { REACT_BASE_PATH } from '@/router/alias';
|
||||
import { brandingStore, pageTagStore, siteInfoStore } from '@/stores';
|
||||
import { getCurrentLang } from '@/utils/localize';
|
||||
|
||||
@@ -76,7 +77,7 @@ const Index: FC = () => {
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
href={favicon || square_icon || '/favicon.ico'}
|
||||
href={favicon || square_icon || `${REACT_BASE_PATH}/favicon.ico`}
|
||||
/>
|
||||
<link rel="icon" type="image/png" sizes="192x192" href={square_icon} />
|
||||
<link rel="apple-touch-icon" type="image/png" href={square_icon} />
|
||||
@@ -84,7 +85,10 @@ const Index: FC = () => {
|
||||
{keywords && <meta name="keywords" content={keywords} />}
|
||||
{description && <meta name="description" content={description} />}
|
||||
{doInsertCustomCSS && (
|
||||
<link rel="stylesheet" href={`${process.env.PUBLIC_URL}/custom.css`} />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href={`${process.env.PUBLIC_URL}${REACT_BASE_PATH}/custom.css`}
|
||||
/>
|
||||
)}
|
||||
</Helmet>
|
||||
);
|
||||
|
||||
@@ -24,6 +24,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { FacebookShareButton, TwitterShareButton } from 'next-share';
|
||||
import copy from 'copy-to-clipboard';
|
||||
|
||||
import { BASE_ORIGIN } from '@/router/alias';
|
||||
import { loggedUserInfoStore } from '@/stores';
|
||||
|
||||
interface IProps {
|
||||
@@ -42,8 +43,8 @@ const Index: FC<IProps> = ({ type, qid, aid, title }) => {
|
||||
const { t } = useTranslation();
|
||||
let baseUrl =
|
||||
type === 'question'
|
||||
? `${window.location.origin}/questions/${qid}`
|
||||
: `${window.location.origin}/questions/${qid}/${aid}`;
|
||||
? `${BASE_ORIGIN}/questions/${qid}`
|
||||
: `${BASE_ORIGIN}/questions/${qid}/${aid}`;
|
||||
if (user.id) {
|
||||
baseUrl = `${baseUrl}?shareUserId=${user.username}`;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
import { FC } from 'react';
|
||||
import { Form, Table, Stack } from 'react-bootstrap';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useSearchParams, Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import classNames from 'classnames';
|
||||
@@ -110,8 +110,8 @@ const Answers: FC = () => {
|
||||
return (
|
||||
<tr key={li.id}>
|
||||
<td>
|
||||
<a
|
||||
href={pathFactory.answerLanding({
|
||||
<Link
|
||||
to={pathFactory.answerLanding({
|
||||
questionId: li.question_id,
|
||||
slugTitle: li.question_info.url_title,
|
||||
answerId: li.id,
|
||||
@@ -120,7 +120,7 @@ const Answers: FC = () => {
|
||||
className="text-break text-wrap"
|
||||
rel="noreferrer">
|
||||
{li.question_info.title}
|
||||
</a>
|
||||
</Link>
|
||||
{li.accepted === 2 && (
|
||||
<Icon
|
||||
name="check-circle-fill"
|
||||
|
||||
@@ -109,13 +109,13 @@ const Questions: FC = () => {
|
||||
return (
|
||||
<tr key={li.id}>
|
||||
<td>
|
||||
<a
|
||||
href={pathFactory.questionLanding(li.id, li.url_title)}
|
||||
<Link
|
||||
to={pathFactory.questionLanding(li.id, li.url_title)}
|
||||
target="_blank"
|
||||
className="text-break text-wrap"
|
||||
rel="noreferrer">
|
||||
{li.title}
|
||||
</a>
|
||||
</Link>
|
||||
{li.accepted_answer_id > 0 && (
|
||||
<Icon
|
||||
name="check-circle-fill"
|
||||
|
||||
@@ -21,6 +21,7 @@ import { FC } from 'react';
|
||||
import { Button } from 'react-bootstrap';
|
||||
import { useTranslation, Trans } from 'react-i18next';
|
||||
|
||||
import { REACT_BASE_PATH } from '@/router/alias';
|
||||
import Progress from '../Progress';
|
||||
|
||||
interface Props {
|
||||
@@ -37,15 +38,18 @@ const Index: FC<Props> = ({ visible, siteUrl = '' }) => {
|
||||
<p>
|
||||
<Trans i18nKey="install.ready_description">
|
||||
If you ever feel like changing more settings, visit
|
||||
<a href={`${siteUrl}/users/login`}> admin section</a>; find it in the
|
||||
site menu.
|
||||
<a href={`${siteUrl}${REACT_BASE_PATH}/users/login`}>
|
||||
{' '}
|
||||
admin section
|
||||
</a>
|
||||
; find it in the site menu.
|
||||
</Trans>
|
||||
</p>
|
||||
<p>{t('good_luck')}</p>
|
||||
|
||||
<div className="d-flex align-items-center justify-content-between">
|
||||
<Progress step={5} />
|
||||
<Button href={siteUrl}>{t('done')}</Button>
|
||||
<Button href={`${siteUrl}${REACT_BASE_PATH}`}>{t('done')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
} from '@/services';
|
||||
import { Storage, handleFormError, scrollToDocTop } from '@/utils';
|
||||
import { CURRENT_LANG_STORAGE_KEY } from '@/common/constants';
|
||||
import { BASE_ORIGIN } from '@/router/alias';
|
||||
|
||||
import {
|
||||
FirstStep,
|
||||
@@ -94,7 +95,7 @@ const Index: FC = () => {
|
||||
errorMsg: '',
|
||||
},
|
||||
site_url: {
|
||||
value: window.location.origin,
|
||||
value: BASE_ORIGIN,
|
||||
isInvalid: false,
|
||||
errorMsg: '',
|
||||
},
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import { memo } from 'react';
|
||||
import { Accordion, ListGroup } from 'react-bootstrap';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { Icon } from '@/components';
|
||||
import { pathFactory } from '@/router/pathFactory';
|
||||
@@ -45,10 +46,10 @@ const SearchQuestion = ({ similarQuestions }) => {
|
||||
return (
|
||||
<ListGroup.Item
|
||||
action
|
||||
as="a"
|
||||
as={Link}
|
||||
className="link-dark text-wrap text-break"
|
||||
key={item.id}
|
||||
href={pathFactory.questionLanding(item.id, item.url_title)}
|
||||
to={pathFactory.questionLanding(item.id, item.url_title)}
|
||||
target="_blank">
|
||||
<span
|
||||
className={`${
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
import React, { useState, useRef, useEffect, useLayoutEffect } from 'react';
|
||||
import { Row, Col, Form, Button, Card } from 'react-bootstrap';
|
||||
import { useParams, useNavigate } from 'react-router-dom';
|
||||
import { useParams, useNavigate, Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import dayjs from 'dayjs';
|
||||
@@ -217,12 +217,12 @@ const Index = () => {
|
||||
<h3 className="mb-4">{t('title')}</h3>
|
||||
<Row>
|
||||
<Col className="page-main flex-auto">
|
||||
<a
|
||||
href={pathFactory.questionLanding(qid, data?.question.url_title)}
|
||||
<Link
|
||||
to={pathFactory.questionLanding(qid, data?.question.url_title)}
|
||||
target="_blank"
|
||||
rel="noreferrer">
|
||||
<h5 className="mb-3">{data?.question.title}</h5>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
<div className="question-content-wrap">
|
||||
<div
|
||||
|
||||
@@ -25,7 +25,7 @@ import { usePageTags } from '@/hooks';
|
||||
import { logout } from '@/services';
|
||||
import { loggedUserInfoStore } from '@/stores';
|
||||
import Storage from '@/utils/storage';
|
||||
import { RouteAlias } from '@/router/alias';
|
||||
import { RouteAlias, BASE_ORIGIN } from '@/router/alias';
|
||||
import { REDIRECT_PATH_STORAGE_KEY } from '@/common/constants';
|
||||
|
||||
const Index = () => {
|
||||
@@ -43,7 +43,7 @@ const Index = () => {
|
||||
const redirect =
|
||||
Storage.get(REDIRECT_PATH_STORAGE_KEY) || RouteAlias.home;
|
||||
Storage.remove(REDIRECT_PATH_STORAGE_KEY);
|
||||
window.location.replace(`${window.location.origin}${redirect}`);
|
||||
window.location.replace(`${BASE_ORIGIN}${redirect}`);
|
||||
});
|
||||
}
|
||||
// auto height of container
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
export const REACT_BASE_PATH = process.env.REACT_APP_BASE_URL || '';
|
||||
export const BASE_ORIGIN = `${window.location.origin}${REACT_BASE_PATH}`;
|
||||
|
||||
export const RouteAlias = {
|
||||
home: '/',
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
import type { NavigateFunction } from 'react-router-dom';
|
||||
|
||||
import { RouteAlias } from '@/router/alias';
|
||||
import { RouteAlias, REACT_BASE_PATH } from '@/router/alias';
|
||||
import Storage from '@/utils/storage';
|
||||
import { REDIRECT_PATH_STORAGE_KEY } from '@/common/constants';
|
||||
import { getLoginUrl } from '@/utils/userCenter';
|
||||
@@ -133,10 +133,31 @@ const navigate = (to: string | number, config: NavigateConfig = {}) => {
|
||||
handler = 'replace';
|
||||
}
|
||||
if (handler === 'href') {
|
||||
if (
|
||||
to.startsWith('/') &&
|
||||
!to.startsWith('//') &&
|
||||
!to.startsWith(REACT_BASE_PATH)
|
||||
) {
|
||||
to = `${REACT_BASE_PATH}${to}`;
|
||||
}
|
||||
window.location.href = to;
|
||||
} else if (handler === 'replace') {
|
||||
if (
|
||||
to.startsWith('/') &&
|
||||
!to.startsWith('//') &&
|
||||
!to.startsWith(REACT_BASE_PATH)
|
||||
) {
|
||||
to = `${REACT_BASE_PATH}${to}`;
|
||||
}
|
||||
window.location.replace(to);
|
||||
} else if (typeof handler === 'function') {
|
||||
if (to === '/test') {
|
||||
to = '/';
|
||||
}
|
||||
|
||||
if (to !== '/test' && to.startsWith('/test')) {
|
||||
to = to.replace('/test', '');
|
||||
}
|
||||
handler(to, config.options);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user