mirror of
https://github.com/ONLYOFFICE/server.git
synced 2026-02-10 18:05:07 +08:00
[feature] Refactor env, routing
This commit is contained in:
@ -1 +1,2 @@
|
||||
REACT_APP_BACKEND_URL=http://localhost:9000
|
||||
REACT_APP_BACKEND_URL=http://localhost:9000
|
||||
REACT_APP_BASE_PATH=/admin
|
||||
|
||||
@ -1 +1,12 @@
|
||||
REACT_APP_BACKEND_URL=http://localhost:9000
|
||||
# Admin Panel Environment Variables
|
||||
# Copy this file to .env for local development
|
||||
|
||||
# Backend URL for API calls
|
||||
REACT_APP_BACKEND_URL=http://localhost:9000
|
||||
|
||||
# Base path for the admin panel (empty for root deployment)
|
||||
# Examples:
|
||||
# REACT_APP_BASE_PATH= # Root deployment: http://localhost:3000/
|
||||
# REACT_APP_BASE_PATH=/admin # Under /admin: http://localhost:3000/admin/
|
||||
# REACT_APP_BASE_PATH=/docserver-admin # Under /docserver-admin: http://localhost:3000/docserver-admin/
|
||||
REACT_APP_BASE_PATH=/admin
|
||||
|
||||
6
AdminPanel/client/package-lock.json
generated
6
AdminPanel/client/package-lock.json
generated
@ -2768,6 +2768,12 @@
|
||||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "17.2.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz",
|
||||
"integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==",
|
||||
"dev": true
|
||||
},
|
||||
"dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
"version": "1.3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "set \"REACT_APP_BACKEND_URL=http://localhost:9000\" && webpack serve --mode=development",
|
||||
"start": "webpack serve --mode=development",
|
||||
"build": "webpack --mode=production"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -29,6 +29,7 @@
|
||||
"babel-loader": "8.2.0",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"css-loader": "^6.2.0",
|
||||
"dotenv": "^17.2.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "5.5.0",
|
||||
"sass": "^1.77.0",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="images/favicon.ico" />
|
||||
<link rel="icon" href="./images/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Document Server Admin Panel" />
|
||||
|
||||
@ -1,32 +1,37 @@
|
||||
import {Provider} from 'react-redux';
|
||||
import {Routes, Route, Navigate} from 'react-router-dom';
|
||||
import {Routes, Route, Navigate, BrowserRouter} from 'react-router-dom';
|
||||
import './App.css';
|
||||
import {store} from './store';
|
||||
import AuthWrapper from './components/AuthWrapper/AuthWrapper';
|
||||
import ConfigLoader from './components/ConfigLoader/ConfigLoader';
|
||||
import Menu from './components/Menu/Menu';
|
||||
import {menuItems} from './config/menuItems';
|
||||
import {getBasePath} from './utils/basePath';
|
||||
|
||||
function App() {
|
||||
const basePath = getBasePath();
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<div className='app'>
|
||||
<AuthWrapper>
|
||||
<div className='appLayout'>
|
||||
<Menu />
|
||||
<div className='mainContent'>
|
||||
<ConfigLoader>
|
||||
<Routes>
|
||||
<Route path='/' element={<Navigate to='/statistics' replace />} />
|
||||
{menuItems.map(item => (
|
||||
<Route key={item.key} path={item.path} element={<item.component />} />
|
||||
))}
|
||||
</Routes>
|
||||
</ConfigLoader>
|
||||
<BrowserRouter basename={basePath}>
|
||||
<div className='app'>
|
||||
<AuthWrapper>
|
||||
<div className='appLayout'>
|
||||
<Menu />
|
||||
<div className='mainContent'>
|
||||
<ConfigLoader>
|
||||
<Routes>
|
||||
<Route path='/' element={<Navigate to='/statistics' replace />} />
|
||||
{menuItems.map(item => (
|
||||
<Route key={item.key} path={item.path} element={<item.component />} />
|
||||
))}
|
||||
</Routes>
|
||||
</ConfigLoader>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</AuthWrapper>
|
||||
</div>
|
||||
</AuthWrapper>
|
||||
</div>
|
||||
</BrowserRouter>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
const BACKEND_URL = process.env.REACT_APP_BACKEND_URL ?? '';
|
||||
const API_BASE_PATH = '/api/v1/admin';
|
||||
|
||||
export const fetchStatistics = async () => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/stat`);
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/stat`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch statistics');
|
||||
}
|
||||
@ -9,7 +10,7 @@ export const fetchStatistics = async () => {
|
||||
};
|
||||
|
||||
export const fetchConfiguration = async () => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/config`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/config`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!response.ok) {
|
||||
@ -19,7 +20,7 @@ export const fetchConfiguration = async () => {
|
||||
};
|
||||
|
||||
export const fetchConfigurationSchema = async () => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/config/schema`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/config/schema`, {
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!response.ok) {
|
||||
@ -29,7 +30,7 @@ export const fetchConfigurationSchema = async () => {
|
||||
};
|
||||
|
||||
export const updateConfiguration = async configData => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/config`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/config`, {
|
||||
method: 'PATCH',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@ -54,7 +55,7 @@ export const updateConfiguration = async configData => {
|
||||
};
|
||||
|
||||
export const fetchCurrentUser = async () => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/me`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/me`, {
|
||||
method: 'GET',
|
||||
credentials: 'include' // Include cookies in the request
|
||||
});
|
||||
@ -70,7 +71,7 @@ export const fetchCurrentUser = async () => {
|
||||
};
|
||||
|
||||
export const login = async ({tenantName, secret}) => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/login`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@ -90,7 +91,7 @@ export const login = async ({tenantName, secret}) => {
|
||||
};
|
||||
|
||||
export const logout = async () => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/logout`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/logout`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
@ -106,7 +107,7 @@ export const logout = async () => {
|
||||
};
|
||||
|
||||
export const rotateWopiKeys = async () => {
|
||||
const response = await fetch(`${BACKEND_URL}/api/v1/admin/wopi/rotate-keys`, {
|
||||
const response = await fetch(`${BACKEND_URL}${API_BASE_PATH}/wopi/rotate-keys`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import {StrictMode} from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import {BrowserRouter} from 'react-router-dom';
|
||||
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
|
||||
import App from './App';
|
||||
|
||||
@ -18,9 +17,7 @@ const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
<App />
|
||||
</QueryClientProvider>
|
||||
</StrictMode>
|
||||
);
|
||||
|
||||
15
AdminPanel/client/src/utils/basePath.js
Normal file
15
AdminPanel/client/src/utils/basePath.js
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Utility functions for handling BASE_PATH environment variable
|
||||
*/
|
||||
|
||||
// Get the base path from environment variable, with fallback to empty string
|
||||
export const getBasePath = () => {
|
||||
return process.env.REACT_APP_BASE_PATH || '';
|
||||
};
|
||||
|
||||
// Create a full path by combining base path with the given path
|
||||
export const createPath = (path) => {
|
||||
const basePath = getBasePath();
|
||||
const cleanPath = path.startsWith('/') ? path : `/${path}`;
|
||||
return `${basePath}${cleanPath}`;
|
||||
};
|
||||
@ -2,6 +2,19 @@ const path = require('path');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
// Load environment variables from .env files
|
||||
// Priority: .env.local > .env.development/.env.production > .env
|
||||
const envFiles = [
|
||||
'.env.local',
|
||||
process.env.NODE_ENV === 'production' ? '.env.production' : '.env.development',
|
||||
'.env'
|
||||
];
|
||||
|
||||
envFiles.forEach(file => {
|
||||
dotenv.config({ path: file });
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
entry: './src/index.js',
|
||||
@ -39,7 +52,8 @@ module.exports = {
|
||||
]
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.REACT_APP_BACKEND_URL': JSON.stringify(process.env.REACT_APP_BACKEND_URL)
|
||||
'process.env.REACT_APP_BACKEND_URL': JSON.stringify(process.env.REACT_APP_BACKEND_URL),
|
||||
'process.env.REACT_APP_BASE_PATH': JSON.stringify(process.env.REACT_APP_BASE_PATH || '')
|
||||
})
|
||||
],
|
||||
|
||||
|
||||
Reference in New Issue
Block a user