fix tests
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-14 01:20:27 +03:00
parent 2ce092aa59
commit 2953a97a46
6 changed files with 90 additions and 22 deletions

View File

@ -44,6 +44,8 @@
| 2026-01-14 | E2E тесты переписаны с Selenium на Playwright (tests/e2e/*.spec.ts) | | 2026-01-14 | E2E тесты переписаны с Selenium на Playwright (tests/e2e/*.spec.ts) |
| 2026-01-14 | **Фаза 2:** Улучшен Drag & Drop — добавлен @dnd-kit/modifiers, исправлен race condition с drag handle, restrictToVerticalAxis | | 2026-01-14 | **Фаза 2:** Улучшен Drag & Drop — добавлен @dnd-kit/modifiers, исправлен race condition с drag handle, restrictToVerticalAxis |
| 2026-01-14 | **Production:** Настроен Keycloak для production (team-planner.vigdorov.ru), обновлён Dockerfile с Keycloak переменными | | 2026-01-14 | **Production:** Настроен Keycloak для production (team-planner.vigdorov.ru), обновлён Dockerfile с Keycloak переменными |
| 2026-01-14 | **UI:** Страница логина (LoginPage) — кнопка "Войти", описание приложения, контакт для получения доступа |
| 2026-01-14 | **UI:** Кнопка выхода на главной странице (IconButton с Logout) |
--- ---
@ -92,6 +94,7 @@ team-planner/
├── src/ ├── src/
│ ├── components/ │ ├── components/
│ │ ├── AuthProvider/ # Keycloak авторизация ✅ │ │ ├── AuthProvider/ # Keycloak авторизация ✅
│ │ ├── LoginPage/ # Страница логина ✅
│ │ ├── IdeasTable/ │ │ ├── IdeasTable/
│ │ │ ├── IdeasTable.tsx # Таблица с DndContext │ │ │ ├── IdeasTable.tsx # Таблица с DndContext
│ │ │ ├── DraggableRow.tsx # Сортируемая строка (useSortable) │ │ │ ├── DraggableRow.tsx # Сортируемая строка (useSortable)

View File

@ -1,13 +1,25 @@
import { Container, Typography, Box, Button } from '@mui/material'; import {
import { Add } from '@mui/icons-material'; Container,
Typography,
Box,
Button,
IconButton,
Tooltip,
} from '@mui/material';
import { Add, Logout } from '@mui/icons-material';
import { IdeasTable } from './components/IdeasTable'; import { IdeasTable } from './components/IdeasTable';
import { IdeasFilters } from './components/IdeasFilters'; import { IdeasFilters } from './components/IdeasFilters';
import { CreateIdeaModal } from './components/CreateIdeaModal'; import { CreateIdeaModal } from './components/CreateIdeaModal';
import { useIdeasStore } from './store/ideas'; import { useIdeasStore } from './store/ideas';
import keycloak from './services/keycloak';
function App() { function App() {
const { setCreateModalOpen } = useIdeasStore(); const { setCreateModalOpen } = useIdeasStore();
const handleLogout = () => {
void keycloak.logout();
};
return ( return (
<Container maxWidth="xl" sx={{ py: 4 }}> <Container maxWidth="xl" sx={{ py: 4 }}>
<Box <Box
@ -26,6 +38,7 @@ function App() {
Управление бэклогом идей команды Управление бэклогом идей команды
</Typography> </Typography>
</Box> </Box>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Button <Button
variant="contained" variant="contained"
startIcon={<Add />} startIcon={<Add />}
@ -33,6 +46,12 @@ function App() {
> >
Новая идея Новая идея
</Button> </Button>
<Tooltip title="Выйти">
<IconButton onClick={handleLogout} color="default">
<Logout />
</IconButton>
</Tooltip>
</Box>
</Box> </Box>
<Box sx={{ mb: 3 }}> <Box sx={{ mb: 3 }}>

View File

@ -1,6 +1,7 @@
import { type ReactNode, useEffect, useRef, useState } from 'react'; import { type ReactNode, useEffect, useRef, useState } from 'react';
import { Box, CircularProgress, Typography } from '@mui/material'; import { Box, CircularProgress, Typography } from '@mui/material';
import keycloak from '../../services/keycloak'; import keycloak from '../../services/keycloak';
import { LoginPage } from '../LoginPage';
interface AuthProviderProps { interface AuthProviderProps {
children: ReactNode; children: ReactNode;
@ -23,7 +24,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
const initKeycloak = async () => { const initKeycloak = async () => {
try { try {
const authenticated = await keycloak.init({ const authenticated = await keycloak.init({
onLoad: 'login-required', onLoad: 'check-sso',
checkLoginIframe: false, checkLoginIframe: false,
pkceMethod: 'S256', pkceMethod: 'S256',
}); });
@ -75,18 +76,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
} }
if (!isAuthenticated) { if (!isAuthenticated) {
return ( return <LoginPage />;
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100vh',
}}
>
<Typography>Ошибка авторизации. Перенаправление...</Typography>
</Box>
);
} }
return <>{children}</>; return <>{children}</>;

View File

@ -0,0 +1,54 @@
import { Box, Button, Typography, Paper } from '@mui/material';
import { Login } from '@mui/icons-material';
import keycloak from '../../services/keycloak';
export function LoginPage() {
const handleLogin = () => {
void keycloak.login();
};
return (
<Box
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
minHeight: '100vh',
bgcolor: 'background.default',
}}
>
<Paper
elevation={3}
sx={{
p: 6,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
maxWidth: 400,
textAlign: 'center',
}}
>
<Typography variant="h4" component="h1" gutterBottom fontWeight="bold">
Team Planner
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 4 }}>
Приложение для управления бэклогом идей команды
</Typography>
<Button
variant="contained"
size="large"
startIcon={<Login />}
onClick={handleLogin}
sx={{ mb: 4, px: 4, py: 1.5 }}
>
Войти
</Button>
<Typography variant="body2" color="text.secondary">
Для получения доступа обратитесь к Николаю Вигдорову
</Typography>
</Paper>
</Box>
);
}

View File

@ -0,0 +1 @@
export { LoginPage } from './LoginPage';

View File

@ -10,6 +10,7 @@
"dev": "concurrently -n be,fe -c blue,green \"npm run dev:backend\" \"npm run dev:frontend\"", "dev": "concurrently -n be,fe -c blue,green \"npm run dev:backend\" \"npm run dev:frontend\"",
"dev:backend": "npm run dev -w backend", "dev:backend": "npm run dev -w backend",
"dev:frontend": "npm run dev -w frontend", "dev:frontend": "npm run dev -w frontend",
"lint": "npm run -w backend lint && npm run -w frontend lint",
"build": "npm run build:backend && npm run build:frontend", "build": "npm run build:backend && npm run build:frontend",
"build:backend": "npm run build -w backend", "build:backend": "npm run build -w backend",
"build:frontend": "npm run build -w frontend", "build:frontend": "npm run build -w frontend",