rename benutzer to users
add role management to media page
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
"version": "2025.1.0-alpha.10",
|
||||
"date": "2025-10-15",
|
||||
"changes": [
|
||||
"🔐 Auth: Login und Benutzerverwaltung implementiert (rollenbasiert, persistente Sitzungen).",
|
||||
"✨ UI: Benutzer-Menü oben rechts – DropDownButton mit Benutzername/Rolle; Einträge: ‘Profil’ und ‘Abmelden’.",
|
||||
"🧩 Frontend: Syncfusion SplitButtons integriert (react-splitbuttons) und Vite-Konfiguration für Pre-Bundling ergänzt.",
|
||||
"🐛 Fix: Import-Fehler ‘@syncfusion/ej2-react-splitbuttons’ – Anleitung in README hinzugefügt (optimizeDeps + Volume-Reset)."
|
||||
|
||||
@@ -44,7 +44,7 @@ import Ressourcen from './ressourcen';
|
||||
import Infoscreens from './clients';
|
||||
import Infoscreen_groups from './infoscreen_groups';
|
||||
import Media from './media';
|
||||
import Benutzer from './benutzer';
|
||||
import Benutzer from './users';
|
||||
import Einstellungen from './settings';
|
||||
import SetupMode from './SetupMode';
|
||||
import Programminfo from './programminfo';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useAuth } from '../useAuth';
|
||||
import { DialogComponent } from '@syncfusion/ej2-react-popups';
|
||||
import {
|
||||
FileManagerComponent,
|
||||
@@ -19,6 +20,8 @@ type CustomSelectUploadEventModalProps = {
|
||||
|
||||
const CustomSelectUploadEventModal: React.FC<CustomSelectUploadEventModalProps> = props => {
|
||||
const { open, onClose, onSelect } = props;
|
||||
const { user } = useAuth();
|
||||
const isSuperadmin = useMemo(() => user?.role === 'superadmin', [user]);
|
||||
|
||||
const [selectedFile, setSelectedFile] = useState<{
|
||||
id: string;
|
||||
@@ -63,6 +66,23 @@ const CustomSelectUploadEventModal: React.FC<CustomSelectUploadEventModalProps>
|
||||
}
|
||||
};
|
||||
|
||||
type FileItem = { name: string; isFile: boolean };
|
||||
type ReadSuccessArgs = { action: string; result?: { files?: FileItem[] } };
|
||||
type FileOpenArgs = { fileDetails?: FileItem; cancel?: boolean };
|
||||
|
||||
const handleSuccess = (args: ReadSuccessArgs) => {
|
||||
if (isSuperadmin) return;
|
||||
if (args && args.action === 'read' && args.result && Array.isArray(args.result.files)) {
|
||||
args.result.files = args.result.files.filter((f: FileItem) => !(f.name === 'converted' && !f.isFile));
|
||||
}
|
||||
};
|
||||
|
||||
const handleFileOpen = (args: FileOpenArgs) => {
|
||||
if (!isSuperadmin && args && args.fileDetails && args.fileDetails.name === 'converted' && !args.fileDetails.isFile) {
|
||||
args.cancel = true;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<DialogComponent
|
||||
target="#root"
|
||||
@@ -84,6 +104,9 @@ const CustomSelectUploadEventModal: React.FC<CustomSelectUploadEventModalProps>
|
||||
)}
|
||||
>
|
||||
<FileManagerComponent
|
||||
cssClass="e-bigger media-icons-xl"
|
||||
success={handleSuccess}
|
||||
fileOpen={handleFileOpen}
|
||||
ajaxSettings={{
|
||||
url: hostUrl + 'operations',
|
||||
getImageUrl: hostUrl + 'get-image',
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
/* Tailwind removed: base/components/utilities directives no longer used. */
|
||||
|
||||
/* Custom overrides moved to theme-overrides.css to load after Syncfusion styles */
|
||||
|
||||
/* :root {
|
||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
line-height: 1.5;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from './useAuth';
|
||||
|
||||
export default function Login() {
|
||||
@@ -7,14 +8,16 @@ export default function Login() {
|
||||
const [password, setPassword] = useState('');
|
||||
const [message, setMessage] = useState<string | null>(null);
|
||||
const isDev = import.meta.env.MODE !== 'production';
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setMessage(null);
|
||||
try {
|
||||
await login(username, password);
|
||||
// Browser will stay on /login; App's route gate will redirect to '/'
|
||||
setMessage('Login erfolgreich');
|
||||
// Redirect to dashboard after successful login
|
||||
navigate('/');
|
||||
} catch (err) {
|
||||
setMessage(err instanceof Error ? err.message : 'Login fehlgeschlagen');
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import '@syncfusion/ej2-lists/styles/material3.css';
|
||||
import '@syncfusion/ej2-calendars/styles/material3.css';
|
||||
import '@syncfusion/ej2-splitbuttons/styles/material3.css';
|
||||
import '@syncfusion/ej2-icons/styles/material3.css';
|
||||
import './theme-overrides.css';
|
||||
|
||||
// Setze hier deinen Lizenzschlüssel ein
|
||||
registerLicense(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import React, { useState, useRef, useMemo } from 'react';
|
||||
import CustomMediaInfoPanel from './components/CustomMediaInfoPanel';
|
||||
import {
|
||||
FileManagerComponent,
|
||||
@@ -7,10 +7,13 @@ import {
|
||||
DetailsView,
|
||||
Toolbar,
|
||||
} from '@syncfusion/ej2-react-filemanager';
|
||||
import { useAuth } from './useAuth';
|
||||
|
||||
const hostUrl = '/api/eventmedia/filemanager/'; // Dein Backend-Endpunkt für FileManager
|
||||
|
||||
const Media: React.FC = () => {
|
||||
const { user } = useAuth();
|
||||
const isSuperadmin = useMemo(() => user?.role === 'superadmin', [user]);
|
||||
// State für die angezeigten Dateidetails
|
||||
const [fileDetails] = useState<null | {
|
||||
name: string;
|
||||
@@ -43,6 +46,25 @@ const Media: React.FC = () => {
|
||||
}
|
||||
}, [viewMode]);
|
||||
|
||||
type FileItem = { name: string; isFile: boolean };
|
||||
type ReadSuccessArgs = { action: string; result?: { files?: FileItem[] } };
|
||||
type FileOpenArgs = { fileDetails?: FileItem; cancel?: boolean };
|
||||
|
||||
// Hide "converted" for non-superadmins after data load
|
||||
const handleSuccess = (args: ReadSuccessArgs) => {
|
||||
if (isSuperadmin) return;
|
||||
if (args && args.action === 'read' && args.result && Array.isArray(args.result.files)) {
|
||||
args.result.files = args.result.files.filter((f: FileItem) => !(f.name === 'converted' && !f.isFile));
|
||||
}
|
||||
};
|
||||
|
||||
// Prevent opening the "converted" folder for non-superadmins
|
||||
const handleFileOpen = (args: FileOpenArgs) => {
|
||||
if (!isSuperadmin && args && args.fileDetails && args.fileDetails.name === 'converted' && !args.fileDetails.isFile) {
|
||||
args.cancel = true;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-4">Medien</h2>
|
||||
@@ -65,6 +87,9 @@ const Media: React.FC = () => {
|
||||
{/* Debug-Ausgabe entfernt, da ReactNode erwartet wird */}
|
||||
<FileManagerComponent
|
||||
ref={fileManagerRef}
|
||||
cssClass="e-bigger media-icons-xl"
|
||||
success={handleSuccess}
|
||||
fileOpen={handleFileOpen}
|
||||
ajaxSettings={{
|
||||
url: hostUrl + 'operations',
|
||||
getImageUrl: hostUrl + 'get-image',
|
||||
|
||||
15
dashboard/src/theme-overrides.css
Normal file
15
dashboard/src/theme-overrides.css
Normal file
@@ -0,0 +1,15 @@
|
||||
/* FileManager icon size overrides (loaded after Syncfusion styles) */
|
||||
.e-filemanager.media-icons-xl .e-large-icons .e-list-icon {
|
||||
font-size: 40px; /* default ~24px */
|
||||
}
|
||||
|
||||
.e-filemanager.media-icons-xl .e-large-icons .e-fe-folder,
|
||||
.e-filemanager.media-icons-xl .e-large-icons .e-fe-file {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
/* Details (grid) view icons */
|
||||
.e-filemanager.media-icons-xl .e-fe-grid-icon .e-fe-folder,
|
||||
.e-filemanager.media-icons-xl .e-fe-grid-icon .e-fe-file {
|
||||
font-size: 24px;
|
||||
}
|
||||
Reference in New Issue
Block a user