Nightly: Badge-Entfernen ohne Modal neuer Endpoint /badges/clear und UI-Button 'Badges entfernen'
This commit is contained in:
parent
fae25d7578
commit
85a148d45f
3 changed files with 35 additions and 23 deletions
|
|
@ -649,6 +649,19 @@ app.post('/api/badges/assign', requireAdmin, (req: Request, res: Response) => {
|
||||||
res.json({ ok: true, fileBadges: fb });
|
res.json({ ok: true, fileBadges: fb });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Alle Custom-Badges für die angegebenen Dateien entfernen
|
||||||
|
app.post('/api/badges/clear', requireAdmin, (req: Request, res: Response) => {
|
||||||
|
const { files } = req.body as { files?: string[] };
|
||||||
|
if (!Array.isArray(files) || files.length === 0) return res.status(400).json({ error: 'files[] erforderlich' });
|
||||||
|
const fb = persistedState.fileBadges ?? {};
|
||||||
|
for (const rel of files) {
|
||||||
|
delete fb[rel];
|
||||||
|
}
|
||||||
|
persistedState.fileBadges = fb;
|
||||||
|
writePersistedState(persistedState);
|
||||||
|
res.json({ ok: true, fileBadges: fb });
|
||||||
|
});
|
||||||
|
|
||||||
app.get('/api/channels', (_req: Request, res: Response) => {
|
app.get('/api/channels', (_req: Request, res: Response) => {
|
||||||
if (!client.isReady()) return res.status(503).json({ error: 'Bot noch nicht bereit' });
|
if (!client.isReady()) return res.status(503).json({ error: 'Bot noch nicht bereit' });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { fetchChannels, fetchSounds, playSound, setVolumeLive, getVolume, adminStatus, adminLogin, adminLogout, adminDelete, adminRename, playUrl, fetchCategories, createCategory, assignCategories, assignBadges, updateCategory, deleteCategory } from './api';
|
import { fetchChannels, fetchSounds, playSound, setVolumeLive, getVolume, adminStatus, adminLogin, adminLogout, adminDelete, adminRename, playUrl, fetchCategories, createCategory, assignCategories, assignBadges, clearBadges, updateCategory, deleteCategory } from './api';
|
||||||
import type { VoiceChannelInfo, Sound, Category } from './types';
|
import type { VoiceChannelInfo, Sound, Category } from './types';
|
||||||
import { getCookie, setCookie } from './cookies';
|
import { getCookie, setCookie } from './cookies';
|
||||||
|
|
||||||
|
|
@ -475,28 +475,18 @@ export default function App() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ position:'relative' }}>
|
<button
|
||||||
<button
|
className="bg-gray-700 hover:bg-gray-600 text-white font-bold py-3 px-6 rounded-lg transition duration-300"
|
||||||
className="bg-gray-700 hover:bg-gray-600 text-white font-bold py-3 px-6 rounded-lg transition duration-300"
|
onClick={async ()=>{
|
||||||
onClick={()=> setShowEmojiRemovePicker(v=>!v)}
|
try{
|
||||||
>Badge entfernen</button>
|
const files = Object.entries(selectedSet).filter(([,v])=>v).map(([k])=>k);
|
||||||
{showEmojiRemovePicker && (
|
await clearBadges(files);
|
||||||
<div ref={emojiRemovePickerRef as any} className="emoji-picker" style={{ position:'absolute', top:'110%', right:0, zIndex: 99999 }}>
|
setInfo('Alle Custom-Badges entfernt'); setError(null);
|
||||||
{EMOJIS.map((e, i)=> (
|
const resp = await fetchSounds(query, activeFolder === '__favs__' ? '__all__' : activeFolder, activeCategoryId || undefined);
|
||||||
<button key={i} onClick={async ()=>{
|
setSounds(resp.items); setTotal(resp.total); setFolders(resp.folders);
|
||||||
try{
|
}catch(err:any){ setError(err?.message||'Badge-Entfernung fehlgeschlagen'); setInfo(null); }
|
||||||
const files = Object.entries(selectedSet).filter(([,v])=>v).map(([k])=>k);
|
}}
|
||||||
await assignBadges(files, [], [e]);
|
>Badges entfernen</button>
|
||||||
setShowEmojiRemovePicker(false);
|
|
||||||
setInfo('Badge entfernt'); setError(null);
|
|
||||||
const resp = await fetchSounds(query, activeFolder === '__favs__' ? '__all__' : activeFolder, activeCategoryId || undefined);
|
|
||||||
setSounds(resp.items); setTotal(resp.total); setFolders(resp.folders);
|
|
||||||
}catch(err:any){ setError(err?.message||'Badge-Entfernung fehlgeschlagen'); setInfo(null); }
|
|
||||||
}}>{e}</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,15 @@ export async function assignBadges(files: string[], add: string[], remove: strin
|
||||||
return res.json();
|
return res.json();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function clearBadges(files: string[]) {
|
||||||
|
const res = await fetch(`${API_BASE}/badges/clear`, {
|
||||||
|
method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'include',
|
||||||
|
body: JSON.stringify({ files })
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error('Badges löschen fehlgeschlagen');
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
export async function fetchChannels(): Promise<VoiceChannelInfo[]> {
|
export async function fetchChannels(): Promise<VoiceChannelInfo[]> {
|
||||||
const res = await fetch(`${API_BASE}/channels`);
|
const res = await fetch(`${API_BASE}/channels`);
|
||||||
if (!res.ok) throw new Error('Fehler beim Laden der Channels');
|
if (!res.ok) throw new Error('Fehler beim Laden der Channels');
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue