first
This commit is contained in:
108
frontend/src/utils/api.ts
Normal file
108
frontend/src/utils/api.ts
Normal file
@@ -0,0 +1,108 @@
|
||||
import { MQTTMessage, TopicNode } from '../types';
|
||||
|
||||
export async function getTopics(): Promise<TopicNode> {
|
||||
const res = await fetch('/api/topics');
|
||||
if (!res.ok) throw new Error('Impossible de charger les topics');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function getHistory(topic: string, limit = 50): Promise<MQTTMessage[]> {
|
||||
const res = await fetch(`/api/topic/${encodeURIComponent(topic)}/history?limit=${limit}`);
|
||||
if (!res.ok) throw new Error('Impossible de charger l\'historique');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function getStats(): Promise<{ count: number; size: string }> {
|
||||
const res = await fetch('/api/stats');
|
||||
if (!res.ok) throw new Error('Impossible de charger les stats');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function getMetrics(): Promise<{
|
||||
cpuPercent: number;
|
||||
memBytes: number;
|
||||
memLimit: number;
|
||||
dbBytes: number;
|
||||
dbSize: string;
|
||||
}> {
|
||||
const res = await fetch('/api/metrics');
|
||||
if (!res.ok) throw new Error('Impossible de charger les métriques');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function getSysinfo(): Promise<{
|
||||
version: string;
|
||||
clients: string;
|
||||
msgReceived: string;
|
||||
msgSent: string;
|
||||
msgStored: string;
|
||||
subscriptions: string;
|
||||
}> {
|
||||
const res = await fetch('/api/sysinfo');
|
||||
if (!res.ok) throw new Error('Impossible de charger SYS');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function setFilters(rules: { topic: string; save: boolean; view: boolean }[]): Promise<void> {
|
||||
const res = await fetch('/api/filters', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(rules)
|
||||
});
|
||||
if (!res.ok) throw new Error('Impossible de mettre à jour les filtres');
|
||||
}
|
||||
|
||||
export async function getSettings(): Promise<any> {
|
||||
const res = await fetch('/api/settings');
|
||||
if (!res.ok) throw new Error('Impossible de charger les paramètres');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function saveSettings(payload: any): Promise<void> {
|
||||
const res = await fetch('/api/settings', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
if (!res.ok) throw new Error('Impossible de sauvegarder les paramètres');
|
||||
}
|
||||
|
||||
export async function clearHistory(topic: string): Promise<{ deleted: number }> {
|
||||
const res = await fetch(`/api/topic/${encodeURIComponent(topic)}/clear-history`, {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!res.ok) throw new Error('Impossible de supprimer l\'historique');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function clearAllHistory(): Promise<{ deleted: number }> {
|
||||
const res = await fetch('/api/history/clear', {
|
||||
method: 'POST'
|
||||
});
|
||||
if (!res.ok) throw new Error('Impossible de supprimer la base');
|
||||
return res.json();
|
||||
}
|
||||
|
||||
export async function publishMessage(payload: {
|
||||
topic: string;
|
||||
payload: string;
|
||||
qos: number;
|
||||
retained: boolean;
|
||||
}): Promise<void> {
|
||||
const res = await fetch('/api/publish', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
if (!res.ok) throw new Error('Publication impossible');
|
||||
}
|
||||
|
||||
export async function testConnection(broker: string): Promise<{ ok: boolean; latency?: number; error?: string }> {
|
||||
const res = await fetch('/api/test-connection', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ broker })
|
||||
});
|
||||
if (!res.ok) throw new Error('Test impossible');
|
||||
return res.json();
|
||||
}
|
||||
10
frontend/src/utils/format.ts
Normal file
10
frontend/src/utils/format.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export const formatBytes = (bytes: number) => {
|
||||
if (!bytes || bytes < 0) return '0 B';
|
||||
if (bytes < 1024) return `${bytes} B`;
|
||||
const kb = bytes / 1024;
|
||||
if (kb < 1024) return `${kb.toFixed(1)} KB`;
|
||||
const mb = kb / 1024;
|
||||
if (mb < 1024) return `${mb.toFixed(1)} MB`;
|
||||
const gb = mb / 1024;
|
||||
return `${gb.toFixed(2)} GB`;
|
||||
};
|
||||
16
frontend/src/utils/theme.ts
Normal file
16
frontend/src/utils/theme.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
export type ThemeName = 'dark-monokai' | 'light';
|
||||
|
||||
export function setTheme(theme: ThemeName) {
|
||||
const link = document.getElementById('theme-css') as HTMLLinkElement | null;
|
||||
if (link) {
|
||||
link.href = theme === 'dark-monokai' ? '/themes/theme-dark-monokai.css' : '/themes/theme-light.css';
|
||||
}
|
||||
document.documentElement.dataset.theme = theme;
|
||||
}
|
||||
|
||||
export function initTheme() {
|
||||
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const fallback: ThemeName = prefersDark ? 'dark-monokai' : 'light';
|
||||
setTheme(fallback);
|
||||
return fallback;
|
||||
}
|
||||
Reference in New Issue
Block a user