First version of media manager
This commit is contained in:
67
dashboard/package-lock.json
generated
67
dashboard/package-lock.json
generated
@@ -11,6 +11,7 @@
|
||||
"@syncfusion/ej2-react-buttons": "^30.1.37",
|
||||
"@syncfusion/ej2-react-calendars": "^30.1.37",
|
||||
"@syncfusion/ej2-react-dropdowns": "^30.1.37",
|
||||
"@syncfusion/ej2-react-filemanager": "^30.1.38",
|
||||
"@syncfusion/ej2-react-grids": "^30.1.37",
|
||||
"@syncfusion/ej2-react-inputs": "^30.1.38",
|
||||
"@syncfusion/ej2-react-kanban": "^30.1.37",
|
||||
@@ -1025,12 +1026,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-data": {
|
||||
"version": "30.1.37",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-data/-/ej2-data-30.1.37.tgz",
|
||||
"integrity": "sha512-UGbF1a95BmdRcgkgekMOdJY0kcNSaOrKWLlnZxFkEl9SSvN+mxPa7ktgXHlEWRc+KY/WeNSV2kmyZ8h/htnAXQ==",
|
||||
"version": "30.1.38",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-data/-/ej2-data-30.1.38.tgz",
|
||||
"integrity": "sha512-BdqvjLzzK4OuUR1YlzPSG3SmeGg1mrLz/6ih5oD9dSpRXDoMG24bpO1rwCK7mjy8Dp9IJ8mliyCbPfoDycxM9Q==",
|
||||
"license": "SEE LICENSE IN license",
|
||||
"dependencies": {
|
||||
"@syncfusion/ej2-base": "~30.1.37"
|
||||
"@syncfusion/ej2-base": "~30.1.38"
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-dropdowns": {
|
||||
@@ -1064,6 +1065,47 @@
|
||||
"integrity": "sha512-1r0rWrXEsXsRJhG0yOs8Hp2nGARLsBCD4u602R4IxLDrockIPVJv4gz0rIw4dDtFW7bpAa8J+yWXtr6fW29Bhw==",
|
||||
"license": "SEE LICENSE IN license"
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-filemanager": {
|
||||
"version": "30.1.38",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-filemanager/-/ej2-filemanager-30.1.38.tgz",
|
||||
"integrity": "sha512-QuXnn7V1/Ipit+zl1+3WJsnXytqX0VHVSJ5vzhdpE87nENdDktcOmifzZPpPd19ozh7rif2t2aP41KivUVF14A==",
|
||||
"license": "SEE LICENSE IN license",
|
||||
"dependencies": {
|
||||
"@syncfusion/ej2-base": "~30.1.38",
|
||||
"@syncfusion/ej2-buttons": "~30.1.37",
|
||||
"@syncfusion/ej2-data": "~30.1.38",
|
||||
"@syncfusion/ej2-grids": "~30.1.38",
|
||||
"@syncfusion/ej2-inputs": "~30.1.38",
|
||||
"@syncfusion/ej2-layouts": "~30.1.37",
|
||||
"@syncfusion/ej2-lists": "~30.1.37",
|
||||
"@syncfusion/ej2-navigations": "~30.1.37",
|
||||
"@syncfusion/ej2-popups": "~30.1.37",
|
||||
"@syncfusion/ej2-splitbuttons": "~30.1.37"
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-filemanager/node_modules/@syncfusion/ej2-grids": {
|
||||
"version": "30.1.38",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-grids/-/ej2-grids-30.1.38.tgz",
|
||||
"integrity": "sha512-0ULWC/P8AsYco3fhUfrkppEdU+IMzrIWyoP057/yp0Mktq9UI5mgvQ12ruZbEMQXl0vK5S5DKaWMDJU2vBTDWQ==",
|
||||
"license": "SEE LICENSE IN license",
|
||||
"dependencies": {
|
||||
"@syncfusion/ej2-base": "~30.1.38",
|
||||
"@syncfusion/ej2-buttons": "~30.1.37",
|
||||
"@syncfusion/ej2-calendars": "~30.1.37",
|
||||
"@syncfusion/ej2-compression": "~30.1.37",
|
||||
"@syncfusion/ej2-data": "~30.1.38",
|
||||
"@syncfusion/ej2-dropdowns": "~30.1.37",
|
||||
"@syncfusion/ej2-excel-export": "~30.1.37",
|
||||
"@syncfusion/ej2-file-utils": "~30.1.37",
|
||||
"@syncfusion/ej2-inputs": "~30.1.38",
|
||||
"@syncfusion/ej2-lists": "~30.1.37",
|
||||
"@syncfusion/ej2-navigations": "~30.1.37",
|
||||
"@syncfusion/ej2-notifications": "~30.1.37",
|
||||
"@syncfusion/ej2-pdf-export": "~30.1.38",
|
||||
"@syncfusion/ej2-popups": "~30.1.37",
|
||||
"@syncfusion/ej2-splitbuttons": "~30.1.37"
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-grids": {
|
||||
"version": "30.1.37",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-grids/-/ej2-grids-30.1.37.tgz",
|
||||
@@ -1169,9 +1211,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-pdf-export": {
|
||||
"version": "30.1.37",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-pdf-export/-/ej2-pdf-export-30.1.37.tgz",
|
||||
"integrity": "sha512-4vtuyp+IhB8FUdxnizwytYFYP7Uxdr0thFCEuT3p7T7v4HzwEIk1uingaO32Z4AD72LUNuzznnRTZNyd59VU7w==",
|
||||
"version": "30.1.38",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-pdf-export/-/ej2-pdf-export-30.1.38.tgz",
|
||||
"integrity": "sha512-iWgy/40rgKGweC3CJozn3MxcwKRg4OVoS7bnpkF+aDWFlJu4qV2bjZawacwASCitca+0jSs5aT7KOc24cmqJ4w==",
|
||||
"license": "SEE LICENSE IN license",
|
||||
"dependencies": {
|
||||
"@syncfusion/ej2-compression": "~30.1.37"
|
||||
@@ -1229,6 +1271,17 @@
|
||||
"@syncfusion/ej2-react-base": "~30.1.37"
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-react-filemanager": {
|
||||
"version": "30.1.38",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-react-filemanager/-/ej2-react-filemanager-30.1.38.tgz",
|
||||
"integrity": "sha512-xwq7J24oC7zoiuSQpBe1NWvdK/4zIFSZOXGfTapUdjdczcolC6d+s3AgGmJZLvR1rqdNCJE99m5DO0LiRnJz3A==",
|
||||
"license": "SEE LICENSE IN license",
|
||||
"dependencies": {
|
||||
"@syncfusion/ej2-base": "~30.1.38",
|
||||
"@syncfusion/ej2-filemanager": "30.1.38",
|
||||
"@syncfusion/ej2-react-base": "~30.1.37"
|
||||
}
|
||||
},
|
||||
"node_modules/@syncfusion/ej2-react-grids": {
|
||||
"version": "30.1.37",
|
||||
"resolved": "https://registry.npmjs.org/@syncfusion/ej2-react-grids/-/ej2-react-grids-30.1.37.tgz",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"@syncfusion/ej2-react-buttons": "^30.1.37",
|
||||
"@syncfusion/ej2-react-calendars": "^30.1.37",
|
||||
"@syncfusion/ej2-react-dropdowns": "^30.1.37",
|
||||
"@syncfusion/ej2-react-filemanager": "^30.1.38",
|
||||
"@syncfusion/ej2-react-grids": "^30.1.37",
|
||||
"@syncfusion/ej2-react-inputs": "^30.1.38",
|
||||
"@syncfusion/ej2-react-kanban": "^30.1.37",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "../node_modules/@syncfusion/ej2-react-filemanager/styles/material.css";
|
||||
@import "../node_modules/@syncfusion/ej2-base/styles/material.css";
|
||||
@import "../node_modules/@syncfusion/ej2-buttons/styles/material.css";
|
||||
@import "../node_modules/@syncfusion/ej2-calendars/styles/material.css";
|
||||
|
||||
@@ -129,7 +129,7 @@ const App: React.FC = () => (
|
||||
<Route path="ressourcen" element={<Ressourcen />} />
|
||||
<Route path="Infoscreens" element={<Infoscreens />} />
|
||||
<Route path="infoscr_groups" element={<Infoscreen_groups />} />
|
||||
<Route path="medien" element={<Medien />} />
|
||||
<Route path="medien" element={<Media />} />
|
||||
<Route path="benutzer" element={<Benutzer />} />
|
||||
<Route path="einstellungen" element={<Einstellungen />} />
|
||||
</Route>
|
||||
@@ -146,6 +146,6 @@ import Appointments from './appointments';
|
||||
import Ressourcen from './ressourcen';
|
||||
import Infoscreens from './clients';
|
||||
import Infoscreen_groups from './infoscreen_groups';
|
||||
import Medien from './medien';
|
||||
import Media from './media';
|
||||
import Benutzer from './benutzer';
|
||||
import Einstellungen from './einstellungen';
|
||||
|
||||
27
dashboard/src/components/CustomMediaInfoPanel.tsx
Normal file
27
dashboard/src/components/CustomMediaInfoPanel.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
|
||||
interface CustomMediaInfoPanelProps {
|
||||
mediaId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
eventId?: string;
|
||||
onSave: (data: { title: string; description: string; eventId?: string }) => void;
|
||||
}
|
||||
|
||||
const CustomMediaInfoPanel: React.FC<CustomMediaInfoPanelProps> = ({
|
||||
mediaId,
|
||||
title,
|
||||
description,
|
||||
eventId,
|
||||
onSave,
|
||||
}) => {
|
||||
// Hier kannst du Formularfelder und Logik für die Bearbeitung einbauen
|
||||
return (
|
||||
<div>
|
||||
<h3>Medien-Informationen bearbeiten</h3>
|
||||
{/* Formularfelder für Titel, Beschreibung, Event-Zuordnung */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CustomMediaInfoPanel;
|
||||
100
dashboard/src/media.tsx
Normal file
100
dashboard/src/media.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import CustomMediaInfoPanel from './components/CustomMediaInfoPanel';
|
||||
import {
|
||||
FileManagerComponent,
|
||||
Inject,
|
||||
NavigationPane,
|
||||
DetailsView,
|
||||
Toolbar,
|
||||
} from '@syncfusion/ej2-react-filemanager';
|
||||
|
||||
const hostUrl = '/api/eventmedia/filemanager/'; // Dein Backend-Endpunkt für FileManager
|
||||
|
||||
interface MediaItem {
|
||||
id: string;
|
||||
file_path: string;
|
||||
url: string;
|
||||
description: string;
|
||||
eventId?: string;
|
||||
}
|
||||
|
||||
const Media: React.FC = () => {
|
||||
const [mediaList, setMediaList] = useState<MediaItem[]>([]);
|
||||
const [selectedMedia, setSelectedMedia] = useState<MediaItem | null>(null);
|
||||
|
||||
// Medien vom Server laden
|
||||
useEffect(() => {
|
||||
fetch('/api/eventmedia')
|
||||
.then(res => res.json())
|
||||
.then(setMediaList);
|
||||
}, []);
|
||||
|
||||
// Upload-Handler (vereinfachtes Beispiel)
|
||||
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (!e.target.files?.length) return;
|
||||
const formData = new FormData();
|
||||
formData.append('file', e.target.files[0]);
|
||||
await fetch('/api/eventmedia/upload', { method: 'POST', body: formData });
|
||||
// Nach Upload neu laden
|
||||
const res = await fetch('/api/eventmedia');
|
||||
setMediaList(await res.json());
|
||||
};
|
||||
|
||||
// Speichern von Metadaten/Event-Zuordnung
|
||||
const handleSave = async (data: { title: string; description: string; eventId?: string }) => {
|
||||
if (!selectedMedia) return;
|
||||
await fetch(`/api/eventmedia/${selectedMedia.id}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
// Nach dem Speichern neu laden
|
||||
const res = await fetch('/api/eventmedia');
|
||||
setMediaList(await res.json());
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-4">Medien</h2>
|
||||
<FileManagerComponent
|
||||
ajaxSettings={{
|
||||
url: hostUrl + 'operations',
|
||||
getImageUrl: hostUrl + 'get-image',
|
||||
uploadUrl: hostUrl + 'upload',
|
||||
downloadUrl: hostUrl + 'download',
|
||||
}}
|
||||
toolbarSettings={{
|
||||
items: [
|
||||
'NewFolder',
|
||||
'Upload',
|
||||
'Download',
|
||||
'Rename',
|
||||
'Delete',
|
||||
'SortBy',
|
||||
'Refresh',
|
||||
'Details',
|
||||
],
|
||||
}}
|
||||
contextMenuSettings={{
|
||||
file: ['Open', '|', 'Download', '|', 'Rename', 'Delete', '|', 'Details'],
|
||||
folder: ['Open', '|', 'Rename', 'Delete', '|', 'Details'],
|
||||
layout: ['SortBy', 'Refresh', '|', 'View', 'Details'],
|
||||
}}
|
||||
allowMultiSelection={false}
|
||||
>
|
||||
<Inject services={[NavigationPane, DetailsView, Toolbar]} />
|
||||
</FileManagerComponent>
|
||||
{selectedMedia && (
|
||||
<CustomMediaInfoPanel
|
||||
mediaId={selectedMedia.id}
|
||||
title={selectedMedia.url}
|
||||
description={selectedMedia.description}
|
||||
eventId={selectedMedia.eventId}
|
||||
onSave={handleSave}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Media;
|
||||
@@ -1,8 +0,0 @@
|
||||
import React from 'react';
|
||||
const Medien: React.FC = () => (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold mb-4">Medien</h2>
|
||||
<p>Willkommen im Infoscreen-Management Medien.</p>
|
||||
</div>
|
||||
);
|
||||
export default Medien;
|
||||
Reference in New Issue
Block a user