From 7868613d276daed6f435be03f8498bbaf460f923 Mon Sep 17 00:00:00 2001 From: Untone Date: Fri, 25 Jul 2025 12:26:31 +0300 Subject: [PATCH] rolespicker-fix --- package-lock.json | 6 +- package.json | 3 +- panel/modals/RolesModal.tsx | 206 ++++++++++++++++++------------ panel/ui/ProtectedRoute.tsx | 65 +++++----- vite.config.ts => vite.config.mts | 3 +- 5 files changed, 162 insertions(+), 121 deletions(-) rename vite.config.ts => vite.config.mts (94%) diff --git a/package-lock.json b/package-lock.json index 7204c36e..ba64890f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3282,9 +3282,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.190", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.190.tgz", - "integrity": "sha512-k4McmnB2091YIsdCgkS0fMVMPOJgxl93ltFzaryXqwip1AaxeDqKCGLxkXODDA5Ab/D+tV5EL5+aTx76RvLRxw==", + "version": "1.5.191", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.191.tgz", + "integrity": "sha512-xcwe9ELcuxYLUFqZZxL19Z6HVKcvNkIwhbHUz7L3us6u12yR+7uY89dSl570f/IqNthx8dAw3tojG7i4Ni4tDA==", "dev": true, "license": "ISC" }, diff --git a/package.json b/package.json index 19e81027..fe60eafe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "publy-panel", "version": "0.7.9", - "private": true, + "type": "module", + "description": "Publy, a modern platform for collaborative text creation, offers a user-friendly interface for authors, editors, and readers, supporting real-time collaboration and structured feedback.", "scripts": { "dev": "vite", "build": "vite build", diff --git a/panel/modals/RolesModal.tsx b/panel/modals/RolesModal.tsx index ef99f2e5..5476cf6d 100644 --- a/panel/modals/RolesModal.tsx +++ b/panel/modals/RolesModal.tsx @@ -20,7 +20,7 @@ export interface UserEditModalProps { }) => Promise } -// Доступные роли в системе +// Список доступных ролей с сохранением идентификаторов const AVAILABLE_ROLES = [ { id: 'admin', @@ -54,13 +54,23 @@ const AVAILABLE_ROLES = [ } ] +// Создаем маппинги для конвертации между ID и названиями +const ROLE_ID_TO_NAME = Object.fromEntries( + AVAILABLE_ROLES.map(role => [role.id, role.name]) +) + +const ROLE_NAME_TO_ID = Object.fromEntries( + AVAILABLE_ROLES.map(role => [role.name, role.id]) +) + const UserEditModal: Component = (props) => { + // Инициализируем форму с использованием ID ролей const [formData, setFormData] = createSignal({ id: props.user.id, email: props.user.email || '', name: props.user.name || '', slug: props.user.slug || '', - roles: props.user.roles || [] + roles: (props.user.roles || []).map(roleName => ROLE_NAME_TO_ID[roleName] || roleName) }) const [errors, setErrors] = createSignal>({}) @@ -89,7 +99,7 @@ const UserEditModal: Component = (props) => { } } - // Обновляем форму при изменении пользователя + // Обновляем эффект для инициализации формы createEffect(() => { if (props.user) { setFormData({ @@ -97,31 +107,50 @@ const UserEditModal: Component = (props) => { email: props.user.email || '', name: props.user.name || '', slug: props.user.slug || '', - roles: props.user.roles || [] + roles: (props.user.roles || []).map(roleName => ROLE_NAME_TO_ID[roleName] || roleName) }) setErrors({}) } }) + // Обновим логику проверки выбранности роли + const isRoleSelected = (roleId: string) => { + const roles = formData().roles || [] + const isSelected = roles.includes(roleId) + console.log(`Checking role ${roleId}:`, isSelected) + return isSelected + } + const handleRoleToggle = (roleId: string) => { + console.log('Attempting to toggle role:', roleId) + console.log('Current roles:', formData().roles) + console.log('Is admin:', isAdmin()) + console.log('Role is admin:', roleId === 'admin') + if (roleId === 'admin') { + console.log('Admin role cannot be changed') return // Системная роль не может быть изменена } - setFormData((prev) => { + // Создаем новый массив ролей с учетом текущего состояния + setFormData(prev => { const currentRoles = prev.roles || [] const isCurrentlySelected = currentRoles.includes(roleId) const newRoles = isCurrentlySelected - ? currentRoles.filter((r: string) => r !== roleId) // Убираем роль + ? currentRoles.filter(r => r !== roleId) // Убираем роль : [...currentRoles, roleId] // Добавляем роль + console.log('Current roles before:', currentRoles) + console.log('Is currently selected:', isCurrentlySelected) + console.log('New roles:', newRoles) + return { ...prev, roles: newRoles } }) // Очищаем ошибки, связанные с ролями if (errors().roles) { - setErrors((prev) => { + setErrors(prev => { const newErrors = { ...prev } delete newErrors.roles return newErrors @@ -162,7 +191,8 @@ const UserEditModal: Component = (props) => { try { await props.onSave({ ...formData(), - roles: (formData().roles || []).join(',') + // Конвертируем ID ролей обратно в названия для сервера + roles: (formData().roles || []).map(roleId => ROLE_ID_TO_NAME[roleId]).join(',') }) props.onClose() } catch (error) { @@ -173,6 +203,84 @@ const UserEditModal: Component = (props) => { } } + // Обновляем компонент выбора роли + const RoleSelector = (props: { + role: typeof AVAILABLE_ROLES[0], + isSelected: boolean, + onToggle: () => void, + isDisabled?: boolean + }) => { + return ( + + ) + } + + // В основном компоненте модального окна обновляем рендеринг ролей return ( = (props) => {
- {(role) => { - const isAdminRole = role.id === 'admin' - const isSelected = (formData().roles || []).includes(role.id) - const isDisabled = isAdminRole - const roleInfo = getRoleInfo(role.id) - - return ( - - ) - }} + {(role) => ( + handleRoleToggle(role.id)} + isDisabled={role.id === 'admin'} + /> + )}
diff --git a/panel/ui/ProtectedRoute.tsx b/panel/ui/ProtectedRoute.tsx index 03f7ca3e..abb43dd2 100644 --- a/panel/ui/ProtectedRoute.tsx +++ b/panel/ui/ProtectedRoute.tsx @@ -2,48 +2,45 @@ import { useAuth } from '../context/auth' import { DataProvider } from '../context/data' import { TableSortProvider } from '../context/sort' import AdminPage from '../routes/admin' +import { Show, createEffect } from 'solid-js' /** * Компонент защищенного маршрута */ export const ProtectedRoute = () => { - console.log('[ProtectedRoute] Checking authentication...') const auth = useAuth() - const isReady = auth.isReady() - const authenticated = auth.isAuthenticated() - console.log(`[ProtectedRoute] Auth state: ready=${isReady}, authenticated=${authenticated}`) + createEffect(() => { + if (auth.isReady() && !auth.isAuthenticated()) { + window.location.href = '/login' + } + }) - // Если авторизация еще не готова, показываем загрузку - if (!isReady) { - console.log('[ProtectedRoute] Auth not ready, showing loading...') - return ( -
-
-
Инициализация авторизации...
-
- ) - } - - // Если авторизация готова, но пользователь не аутентифицирован - if (!authenticated) { - console.log('[ProtectedRoute] Not authenticated, redirecting to login...') - // Используем window.location.href для редиректа - window.location.href = '/login' - return ( -
-
-
Перенаправление на страницу входа...
-
- ) - } - - console.log('[ProtectedRoute] Auth ready and authenticated, rendering admin panel...') return ( - - - - - + +
+
Инициализация авторизации...
+
+ } + > + +
+
Перенаправление на страницу входа...
+
+ } + > + + + + + +
+
) } diff --git a/vite.config.ts b/vite.config.mts similarity index 94% rename from vite.config.ts rename to vite.config.mts index a6575ed6..5e25d7b8 100644 --- a/vite.config.ts +++ b/vite.config.mts @@ -4,7 +4,8 @@ import { defineConfig } from 'vite' import solidPlugin from 'vite-plugin-solid' // Читаем версию из package.json -const packageJsonPath = resolve(__dirname, 'package.json') +const currentDir = process.cwd() +const packageJsonPath = resolve(currentDir, 'package.json') const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')) const version = packageJson.version