introduce icons in events
This commit is contained in:
@@ -23,6 +23,12 @@ import { getGroupColor } from './groupColors';
|
||||
import { deleteEvent } from './apiEvents';
|
||||
import CustomEventModal from './components/CustomEventModal';
|
||||
import { fetchMediaById } from './apiClients';
|
||||
import { Presentation, Globe, Video, MessageSquare, School } from 'lucide-react';
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import caGregorian from 'cldr-data/main/de/ca-gregorian.json';
|
||||
import numbers from 'cldr-data/main/de/numbers.json';
|
||||
import timeZoneNames from 'cldr-data/main/de/timeZoneNames.json';
|
||||
import numberingSystems from 'cldr-data/supplemental/numberingSystems.json';
|
||||
|
||||
// Typ für Gruppe ergänzen
|
||||
type Group = {
|
||||
@@ -37,9 +43,11 @@ type Event = {
|
||||
StartTime: Date;
|
||||
EndTime: Date;
|
||||
IsAllDay: boolean;
|
||||
MediaId?: string | number; // Nur die MediaId wird gespeichert!
|
||||
MediaId?: string | number;
|
||||
SlideshowInterval?: number;
|
||||
WebsiteUrl?: string;
|
||||
Icon?: string; // <--- Icon ergänzen!
|
||||
Type?: string; // <--- Typ ergänzen, falls benötigt
|
||||
};
|
||||
|
||||
type RawEvent = {
|
||||
@@ -48,21 +56,13 @@ type RawEvent = {
|
||||
StartTime: string;
|
||||
EndTime: string;
|
||||
IsAllDay: boolean;
|
||||
MediaId?: string | number; // Nur die MediaId wird gespeichert!
|
||||
MediaId?: string | number;
|
||||
Icon?: string; // <--- Icon ergänzen!
|
||||
Type?: string;
|
||||
};
|
||||
|
||||
import * as de from 'cldr-data/main/de/ca-gregorian.json';
|
||||
import * as numbers from 'cldr-data/main/de/numbers.json';
|
||||
import * as timeZoneNames from 'cldr-data/main/de/timeZoneNames.json';
|
||||
import * as numberingSystems from 'cldr-data/supplemental/numberingSystems.json';
|
||||
|
||||
// CLDR-Daten laden
|
||||
loadCldr(
|
||||
(de as unknown as { default: object }).default,
|
||||
(numbers as unknown as { default: object }).default,
|
||||
(timeZoneNames as unknown as { default: object }).default,
|
||||
(numberingSystems as unknown as { default: object }).default
|
||||
);
|
||||
// CLDR-Daten laden (direkt die JSON-Objekte übergeben)
|
||||
loadCldr(caGregorian, numbers, timeZoneNames, numberingSystems);
|
||||
|
||||
// Deutsche Lokalisierung für den Scheduler
|
||||
L10n.load({
|
||||
@@ -100,6 +100,37 @@ L10n.load({
|
||||
// Kultur setzen
|
||||
setCulture('de');
|
||||
|
||||
// Mapping für Lucide-Icons
|
||||
const iconMap: Record<string, React.ElementType> = {
|
||||
Presentation,
|
||||
Globe,
|
||||
Video,
|
||||
MessageSquare,
|
||||
School,
|
||||
};
|
||||
|
||||
const eventTemplate = (event: Event) => {
|
||||
const IconComponent = iconMap[event.Icon ?? ''] || null;
|
||||
// Zeitangabe formatieren
|
||||
const start = event.StartTime instanceof Date ? event.StartTime : new Date(event.StartTime);
|
||||
const end = event.EndTime instanceof Date ? event.EndTime : new Date(event.EndTime);
|
||||
const timeString = `${start.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} - ${end.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}`;
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', color: '#fff', marginBottom: 2 }}>
|
||||
{IconComponent && (
|
||||
<span style={{ verticalAlign: 'middle', display: 'inline-block', marginRight: 6 }}>
|
||||
<IconComponent size={18} color="#fff" />
|
||||
</span>
|
||||
)}
|
||||
<span style={{ marginTop: 3 }}>{event.Subject}</span>
|
||||
</div>
|
||||
<div style={{ fontSize: '0.95em', color: '#fff', marginTop: -2 }}>{timeString}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Appointments: React.FC = () => {
|
||||
const [groups, setGroups] = useState<Group[]>([]);
|
||||
const [selectedGroupId, setSelectedGroupId] = useState<string | null>(null);
|
||||
@@ -137,6 +168,8 @@ const Appointments: React.FC = () => {
|
||||
EndTime: new Date(e.EndTime.endsWith('Z') ? e.EndTime : e.EndTime + 'Z'),
|
||||
IsAllDay: e.IsAllDay,
|
||||
MediaId: e.MediaId,
|
||||
Icon: e.Icon, // <--- Icon übernehmen!
|
||||
Type: e.Type, // <--- Typ übernehmen!
|
||||
}));
|
||||
setEvents(mapped);
|
||||
} catch (err) {
|
||||
@@ -247,6 +280,7 @@ const Appointments: React.FC = () => {
|
||||
currentView="Week"
|
||||
eventSettings={{
|
||||
dataSource: events,
|
||||
template: eventTemplate, // <--- Hier das Template setzen!
|
||||
}}
|
||||
cellClick={args => {
|
||||
// args.startTime und args.endTime sind Date-Objekte
|
||||
@@ -317,14 +351,44 @@ const Appointments: React.FC = () => {
|
||||
if (selectedGroupId && args.data && args.data.Id) {
|
||||
const groupColor = getGroupColor(selectedGroupId, groups);
|
||||
const now = new Date();
|
||||
|
||||
let IconComponent: React.ElementType | null = null;
|
||||
switch (args.data.Type) {
|
||||
case 'presentation':
|
||||
IconComponent = Presentation;
|
||||
break;
|
||||
case 'website':
|
||||
IconComponent = Globe;
|
||||
break;
|
||||
case 'video':
|
||||
IconComponent = Video;
|
||||
break;
|
||||
case 'message':
|
||||
IconComponent = MessageSquare;
|
||||
break;
|
||||
case 'webuntis':
|
||||
IconComponent = School;
|
||||
break;
|
||||
default:
|
||||
IconComponent = null;
|
||||
}
|
||||
|
||||
// Nur .e-subject verwenden!
|
||||
const titleElement = args.element.querySelector('.e-subject');
|
||||
if (titleElement && IconComponent) {
|
||||
const svgString = renderToStaticMarkup(<IconComponent size={18} color="#78591c" />);
|
||||
// Immer nur den reinen Text nehmen, kein vorhandenes Icon!
|
||||
const subjectText = (titleElement as HTMLElement).textContent ?? '';
|
||||
(titleElement as HTMLElement).innerHTML =
|
||||
`<span style="vertical-align:middle;display:inline-block;margin-right:6px;">${svgString}</span>` +
|
||||
subjectText;
|
||||
}
|
||||
|
||||
// Vergangene Termine: Raumgruppenfarbe mit Transparenz
|
||||
if (args.data.EndTime && args.data.EndTime < now) {
|
||||
// Vergangene Termine: Raumgruppenfarbe mit Transparenz und grauer Schrift
|
||||
args.element.style.backgroundColor = groupColor
|
||||
? `${groupColor}` // 100 = ~100% Transparenz für hex-Farben
|
||||
: '#f3f3f3';
|
||||
args.element.style.backgroundColor = groupColor ? `${groupColor}` : '#f3f3f3';
|
||||
args.element.style.color = '';
|
||||
} else if (groupColor) {
|
||||
// Aktuelle/future Termine: normale Raumgruppenfarbe
|
||||
args.element.style.backgroundColor = groupColor;
|
||||
args.element.style.color = '';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user