VORKOUT-15 #12

Merged
vlad.dev merged 3 commits from VORKOUT-15 into master 2025-06-24 12:56:16 +05:00
26 changed files with 2108 additions and 15608 deletions
Showing only changes of commit 5ed8ca9251 - Show all commits

View File

@ -1,5 +1,4 @@
REACT_APP_WEBSOCKET_PROTOCOL=ws VITE_APP_WEBSOCKET_PROTOCOL=ws
REACT_APP_HTTP_PROTOCOL=http VITE_APP_HTTP_PROTOCOL=http
REACT_APP_API_URL=localhost:8000 VITE_APP_API_URL=localhost:8000
REACT_APP_URL=localhost:3000 VITE_APP_URL=localhost:3000
BROWSER=none

17
client/index.html Normal file
View File

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using Vite" />
<link rel="icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="manifest" href="/manifest.json" />
<title>VORKOUT</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

17480
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,6 @@
"@testing-library/react": "^16.2.0", "@testing-library/react": "^16.2.0",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.2", "@types/jest": "^27.5.2",
"@types/node": "^16.18.126",
"@types/react": "^19.0.11", "@types/react": "^19.0.11",
"@types/react-dom": "^19.0.4", "@types/react-dom": "^19.0.4",
"antd": "^5.24.7", "antd": "^5.24.7",
@ -21,16 +20,13 @@
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-i18next": "^15.5.1", "react-i18next": "^15.5.1",
"react-router-dom": "^7.5.0", "react-router-dom": "^7.5.0",
"react-scripts": "5.0.1",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4", "web-vitals": "^2.1.4",
"zustand": "^5.0.5" "zustand": "^5.0.5"
}, },
"scripts": { "scripts": {
"start": "react-scripts start", "dev": "vite",
"build": "react-scripts build", "build": "vite build",
"test": "react-scripts test", "preview": "vite preview"
"eject": "react-scripts eject"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
@ -49,5 +45,13 @@
"last 1 firefox version", "last 1 firefox version",
"last 1 safari version" "last 1 safari version"
] ]
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
"@types/node": "^20.19.1",
"@vitejs/plugin-react": "^4.5.2",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vite-plugin-node-polyfills": "^0.23.0"
} }
} }

BIN
client/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,43 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>VORKOUT</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

View File

@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { Route, Routes } from 'react-router-dom'; import { Route, Routes } from 'react-router-dom';
import MainLayout from './pages/MainLayout';
import ProtectedRoute from './pages/ProtectedRoute';
import LoginPage from './pages/LoginPage';
import { useSetUserSelector } from './store/userStore'; import { useSetUserSelector } from './store/userStore';
import LoginPage from './pages/LoginPage';
import ProtectedRoute from './pages/ProtectedRoute';
import MainLayout from './pages/MainLayout';
function App() { function App() {
const setUser = useSetUserSelector(); const setUser = useSetUserSelector();

View File

@ -1,11 +1,14 @@
import axios from 'axios'; import axios from 'axios';
import { Auth, Tokens } from '../types/auth'; // import { Auth, Tokens } from '../types/auth';
import { User } from '../types/user';
import { AuthService } from '../services/authService';
import axiosRetry from 'axios-retry'; import axiosRetry from 'axios-retry';
import { useAuthStore } from '../store/authStore'; import { Auth, Tokens } from '@/types/auth';
import { useAuthStore } from '@/store/authStore';
import { AuthService } from '@/services/authService';
import { User } from '@/types/user';
const baseURL = `${process.env.REACT_APP_HTTP_PROTOCOL}://${process.env.REACT_APP_API_URL}/api/v1`; const baseURL = `${import.meta.env.VITE_APP_HTTP_PROTOCOL}://${
import.meta.env.VITE_APP_API_URL
}/api/v1`;
const base = axios.create({ const base = axios.create({
baseURL, baseURL,
@ -45,6 +48,9 @@ base.interceptors.response.use(
return response; return response;
}, },
async function (error) { async function (error) {
if (!error.response) {
return Promise.reject(error);
}
console.log('error', error); console.log('error', error);
const originalRequest = error.response.config; const originalRequest = error.response.config;
const urlTokens = error?.request?.responseURL.split('/'); const urlTokens = error?.request?.responseURL.split('/');

View File

@ -1,8 +1,9 @@
import './i18n'; import '@/config/i18n';
import { ConfigProvider } from 'antd'; import { ConfigProvider } from 'antd';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { BrowserRouter } from 'react-router-dom';
import { theme } from './customTheme'; import { theme } from '@/config/customTheme';
import en from 'antd/locale/en_US'; import en from 'antd/locale/en_US';
import ru from 'antd/locale/ru_RU'; import ru from 'antd/locale/ru_RU';
@ -18,7 +19,7 @@ export default function AppWrapper({ children }: any) {
return ( return (
<ConfigProvider locale={antdLocales[currentLang]} theme={theme}> <ConfigProvider locale={antdLocales[currentLang]} theme={theme}>
{children} <BrowserRouter>{children}</BrowserRouter>
</ConfigProvider> </ConfigProvider>
); );
} }

12
client/src/env.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
/// <reference types="vite/client" />
interface ImportMetaEnv {
readonly VITE_APP_WEBSOCKET_PROTOCOL: string;
readonly VITE_APP_HTTP_PROTOCOL: string;
readonly VITE_APP_API_URL: string;
readonly VITE_APP_URL: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}

View File

@ -1,9 +1,8 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom/client'; import ReactDOM from 'react-dom/client';
import './index.css'; import '@/index.css';
import App from './App'; import App from '@/App';
import { BrowserRouter } from 'react-router-dom'; import AppWrapper from '@/config/AppWrapper';
import AppWrapper from './config/AppWrapper';
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement document.getElementById('root') as HTMLElement
@ -11,8 +10,6 @@ const root = ReactDOM.createRoot(
root.render( root.render(
<AppWrapper> <AppWrapper>
<BrowserRouter> <App />
<App />
</BrowserRouter>
</AppWrapper> </AppWrapper>
); );

View File

@ -1,12 +1,9 @@
import Header from '../components/Header';
import { useState } from 'react'; import { useState } from 'react';
import ContentDrawer from '../components/ContentDrawer';
import UserCreate from '../components/UserCreate';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Button } from 'antd'; import { User } from '@/types/user';
import { UserService } from '../services/userService'; import Header from '@/components/Header';
import { User } from '../types/user'; import ContentDrawer from '@/components/ContentDrawer';
import { AuthService } from '../services/authService'; import UserCreate from '@/components/UserCreate';
export default function AccountsPage() { export default function AccountsPage() {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -1,5 +1,5 @@
import Header from '@/components/Header';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Header from '../components/Header';
export default function ConfigurationPage() { export default function ConfigurationPage() {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -1,5 +1,5 @@
import Header from '@/components/Header';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Header from '../components/Header';
export default function EventsListPage() { export default function EventsListPage() {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -5,9 +5,9 @@ import {
EyeTwoTone, EyeTwoTone,
UserOutlined, UserOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { AuthService } from '../services/authService';
import { Auth } from '../types/auth';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { AuthService } from '@/services/authService';
import { Auth } from '@/types/auth';
const { Text, Link } = Typography; const { Text, Link } = Typography;

View File

@ -2,8 +2,8 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Layout } from 'antd'; import { Layout } from 'antd';
import Sider from 'antd/es/layout/Sider'; import Sider from 'antd/es/layout/Sider';
import SiderMenu from '../components/SiderMenu';
import { Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import { Route, Routes, useLocation, useNavigate } from 'react-router-dom';
import SiderMenu from '@/components/SiderMenu';
import ProcessDiagramPage from './ProcessDiagramPage'; import ProcessDiagramPage from './ProcessDiagramPage';
import RunningProcessesPage from './RunningProcessesPage'; import RunningProcessesPage from './RunningProcessesPage';
import AccountsPage from './AccountsPage'; import AccountsPage from './AccountsPage';

View File

@ -1,5 +1,5 @@
import Header from '@/components/Header';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Header from '../components/Header';
export default function ProcessDiagramPage() { export default function ProcessDiagramPage() {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -1,8 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
// ProtectedRoute.js
import { Outlet, useNavigate } from 'react-router-dom'; import { Outlet, useNavigate } from 'react-router-dom';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { useUserSelector } from '../store/userStore'; import { useUserSelector } from '@/store/userStore';
const ProtectedRoute = (): React.JSX.Element => { const ProtectedRoute = (): React.JSX.Element => {
const navigate = useNavigate(); const navigate = useNavigate();

View File

@ -1,5 +1,5 @@
import Header from '@/components/Header';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Header from '../components/Header';
export default function RunningProcessesPage() { export default function RunningProcessesPage() {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -1,8 +1,8 @@
import api from '../api/api'; import api from "@/api/api";
import { useAuthStore } from '../store/authStore'; import { useAuthStore } from "@/store/authStore";
import { useUserStore } from '../store/userStore'; import { Auth } from "@/types/auth";
import { Auth } from '../types/auth'; import { UserService } from "./userService";
import { UserService } from './userService'; import { useUserStore } from "@/store/userStore";
export class AuthService { export class AuthService {
static async login(auth: Auth) { static async login(auth: Auth) {

View File

@ -1,5 +1,5 @@
import api from '../api/api'; import api from '@/api/api';
import { User } from '../types/user'; import { User } from '@/types/user';
export class UserService { export class UserService {
static async getProfile(): Promise<User> { static async getProfile(): Promise<User> {

View File

@ -1,6 +1,6 @@
import { User } from '@/types/user';
import { create } from 'zustand'; import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware'; import { devtools, persist } from 'zustand/middleware';
import { User } from '../types/user';
const userInfo = localStorage.getItem('userInfo'); const userInfo = localStorage.getItem('userInfo');

View File

@ -1,3 +1,3 @@
import { components } from "./openapi-types" import { components } from './openapi-types';
export type User = components["schemas"]["User"]; export type User = components['schemas']['User'];

View File

@ -1,11 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es5", "target": "es5",
"lib": [ "lib": ["dom", "dom.iterable", "esnext"],
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true, "allowJs": true,
"skipLibCheck": true, "skipLibCheck": true,
"esModuleInterop": true, "esModuleInterop": true,
@ -18,9 +14,11 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx" "jsx": "react-jsx",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}, },
"include": [ "include": ["src"]
"src"
]
} }

23
client/vite.config.ts Normal file
View File

@ -0,0 +1,23 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import path from 'path';
export default defineConfig({
plugins: [react()],
server: {
port: 3000,
open: false,
},
build: {
outDir: 'build',
},
preview: {
port: 3000,
open: false,
},
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
});

View File

@ -32,11 +32,11 @@ startretries=5
[program:client] [program:client]
environment= environment=
REACT_APP_WEBSOCKET_PROTOCOL=ws, VITE_APP_WEBSOCKET_PROTOCOL=ws,
REACT_APP_HTTP_PROTOCOL=http, VITE_APP_HTTP_PROTOCOL=http,
REACT_APP_API_URL=localhost:8000, VITE_APP_API_URL=localhost:8000,
REACT_APP_URL=localhost:3000 VITE_APP_URL=localhost:3000
command=bash -c 'cd client; npm run build; serve -s build' command=bash -c 'cd client; npm run build; npm run preview'
numprocs=1 numprocs=1
process_name=node-%(process_num)d process_name=node-%(process_num)d
stdout_logfile=client.out.log stdout_logfile=client.out.log