Ganze Abfrage-URL einfuegen statt drei Felder tippen
This commit is contained in:
@@ -182,6 +182,7 @@ export default {
|
|||||||
'server.free': 'frei',
|
'server.free': 'frei',
|
||||||
'server.full': 'voll',
|
'server.full': 'voll',
|
||||||
'server.whoIsOn': 'Wer gerade drauf ist',
|
'server.whoIsOn': 'Wer gerade drauf ist',
|
||||||
|
'server.nobody24h': 'In den letzten 24 Stunden war niemand drauf.',
|
||||||
'server.andMore': '+%s weitere',
|
'server.andMore': '+%s weitere',
|
||||||
'server.lastOnline': 'Zuletzt online: %s',
|
'server.lastOnline': 'Zuletzt online: %s',
|
||||||
'server.agoMin': 'vor %s min',
|
'server.agoMin': 'vor %s min',
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ export default {
|
|||||||
'server.free': 'free',
|
'server.free': 'free',
|
||||||
'server.full': 'full',
|
'server.full': 'full',
|
||||||
'server.whoIsOn': 'Who is playing',
|
'server.whoIsOn': 'Who is playing',
|
||||||
|
'server.nobody24h': 'Nobody played in the last 24 hours.',
|
||||||
'server.andMore': '+%s more',
|
'server.andMore': '+%s more',
|
||||||
'server.lastOnline': 'Last online: %s',
|
'server.lastOnline': 'Last online: %s',
|
||||||
'server.agoMin': '%s min ago',
|
'server.agoMin': '%s min ago',
|
||||||
|
|||||||
@@ -75,6 +75,10 @@ function ServerCard({ s }) {
|
|||||||
const [alleSpieler, setAlleSpieler] = useState(false);
|
const [alleSpieler, setAlleSpieler] = useState(false);
|
||||||
const pct = s.online && s.max ? Math.round((s.players / s.max) * 100) : 0;
|
const pct = s.online && s.max ? Math.round((s.players / s.max) * 100) : 0;
|
||||||
const stats = historyStats(s.history);
|
const stats = historyStats(s.history);
|
||||||
|
// War in 24 h überhaupt jemand drauf? Wenn nicht, ist das Diagramm eine
|
||||||
|
// Nulllinie in hundert Pixeln Leere — das sieht nach Fehler aus, obwohl
|
||||||
|
// es keiner ist. Dann lieber ein Satz statt einer leeren Fläche.
|
||||||
|
const hatVerlauf = s.history.length > 1 && s.history.some((h) => (h.players ?? 0) > 0);
|
||||||
// Ab 80 % wird es eng, ab 100 % kommt keiner mehr rein — das soll man
|
// Ab 80 % wird es eng, ab 100 % kommt keiner mehr rein — das soll man
|
||||||
// sehen, ohne den Balken mit der Zahl daneben zu vergleichen.
|
// sehen, ohne den Balken mit der Zahl daneben zu vergleichen.
|
||||||
const fuellung = pct >= 100 ? 'voll' : pct >= 80 ? 'eng' : 'frei';
|
const fuellung = pct >= 100 ? 'voll' : pct >= 80 ? 'eng' : 'frei';
|
||||||
@@ -153,20 +157,22 @@ function ServerCard({ s }) {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{s.history.length > 1 && <HistoryChart history={s.history} max={s.max} />}
|
{hatVerlauf ? (
|
||||||
{stats && (
|
<>
|
||||||
|
<HistoryChart history={s.history} max={s.max} />
|
||||||
<div className="srv-stats">
|
<div className="srv-stats">
|
||||||
<span>{t('server.players24h')}</span>
|
<span>{t('server.players24h')}</span>
|
||||||
{/* Uptime steht jetzt am Balken darunter — zweimal dieselbe
|
{/* Uptime steht jetzt am Balken darunter — zweimal dieselbe
|
||||||
Zahl in verschiedenen Zeiträumen verwirrt nur. */}
|
Zahl in verschiedenen Zeiträumen verwirrt nur. */}
|
||||||
<span>{t('server.peak')} <b>{stats.peak}</b></span>
|
<span>{t('server.peak')} <b>{stats.peak}</b></span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
{s.history.length > 1 && (
|
|
||||||
<div className="srv-achse">
|
<div className="srv-achse">
|
||||||
<span>{t('server.hours24')}</span>
|
<span>{t('server.hours24')}</span>
|
||||||
<span>{t('server.now')}</span>
|
<span>{t('server.now')}</span>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : s.online && (
|
||||||
|
<p className="srv-leer">{t('server.nobody24h')}</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<UptimeTrack buckets={s.uptime} />
|
<UptimeTrack buckets={s.uptime} />
|
||||||
|
|||||||
@@ -171,6 +171,33 @@ const BELIEBTE_SPIELE = [
|
|||||||
];
|
];
|
||||||
const GAMESEL_MAX = 60;
|
const GAMESEL_MAX = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ganze Abfrage-URL eingefügt statt Host getippt? Dann Host, Port und Code
|
||||||
|
* daraus ziehen.
|
||||||
|
*
|
||||||
|
* Bei Farming Simulator ist genau das der Normalfall: der Hoster gibt einem
|
||||||
|
* eine fertige URL wie
|
||||||
|
* `http://1.2.3.4:8200/feed/dedicated-server-stats.xml?code=…`,
|
||||||
|
* und die drei Felder von Hand auseinanderzupflücken ist Arbeit, die niemand
|
||||||
|
* machen muss. Der Port steht mit drin — er ist nicht immer 8080.
|
||||||
|
*
|
||||||
|
* @returns {{host: string, port: string, token?: string} | null}
|
||||||
|
*/
|
||||||
|
function feedUrlZerlegen(text) {
|
||||||
|
const roh = String(text).trim();
|
||||||
|
if (!/^https?:\/\//i.test(roh)) return null;
|
||||||
|
let u;
|
||||||
|
try { u = new URL(roh); } catch { return null; }
|
||||||
|
if (!u.hostname) return null;
|
||||||
|
const code = u.searchParams.get('code') || u.searchParams.get('token') || '';
|
||||||
|
return {
|
||||||
|
host: u.hostname,
|
||||||
|
port: u.port || '',
|
||||||
|
// Ohne Code im Link den vorhandenen stehen lassen, statt ihn zu leeren
|
||||||
|
...(code ? { token: code } : {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/** Combobox für die Spiel-Auswahl — datalist ist nicht stylebar, das hier schon.
|
/** Combobox für die Spiel-Auswahl — datalist ist nicht stylebar, das hier schon.
|
||||||
* Die Liste kommt aus gamedig selbst, damit sie mit jedem Update mitwächst;
|
* Die Liste kommt aus gamedig selbst, damit sie mit jedem Update mitwächst;
|
||||||
* freie IDs bleiben trotzdem erlaubt. */
|
* freie IDs bleiben trotzdem erlaubt. */
|
||||||
@@ -832,6 +859,11 @@ export default function Settings({ me }) {
|
|||||||
|
|
||||||
const serverNeedsUrl = ['fivem', 'http'].includes(serverDraft.type);
|
const serverNeedsUrl = ['fivem', 'http'].includes(serverDraft.type);
|
||||||
const gewaehltesSpiel = games.find((g) => g.id === serverDraft.type) ?? null;
|
const gewaehltesSpiel = games.find((g) => g.id === serverDraft.type) ?? null;
|
||||||
|
/** Ins Host-Feld getippt — oder die ganze Abfrage-URL eingefügt */
|
||||||
|
function hostEingeben(wert) {
|
||||||
|
const teile = feedUrlZerlegen(wert);
|
||||||
|
setServerDraft((d) => (teile ? { ...d, ...teile } : { ...d, host: wert }));
|
||||||
|
}
|
||||||
/** Spiel gewählt: Standard-Port vorschlagen, solange keiner drinsteht */
|
/** Spiel gewählt: Standard-Port vorschlagen, solange keiner drinsteht */
|
||||||
function spielWaehlen(type) {
|
function spielWaehlen(type) {
|
||||||
const spiel = games.find((g) => g.id === type);
|
const spiel = games.find((g) => g.id === type);
|
||||||
@@ -3332,14 +3364,14 @@ export default function Settings({ me }) {
|
|||||||
<input type="text" placeholder={serverDraft.type === 'fivem' ? 'http://ip:30120' : 'https://dienst.example/health'} value={serverDraft.query_url} onChange={(e) => setServerDraft({ ...serverDraft, query_url: e.target.value })} />
|
<input type="text" placeholder={serverDraft.type === 'fivem' ? 'http://ip:30120' : 'https://dienst.example/health'} value={serverDraft.query_url} onChange={(e) => setServerDraft({ ...serverDraft, query_url: e.target.value })} />
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<input type="text" placeholder="Host / IP" value={serverDraft.host} onChange={(e) => setServerDraft({ ...serverDraft, host: e.target.value })} />
|
<input type="text" placeholder="Host / IP — oder ganze Abfrage-URL einfügen" title="Du kannst hier auch die komplette Abfrage-URL einfügen; Host, Port und Code werden herausgezogen." value={serverDraft.host} onChange={(e) => hostEingeben(e.target.value)} />
|
||||||
<input type="text" style={{ flex: 'none', width: '6rem' }} placeholder={gewaehltesSpiel?.port ? `Port ${gewaehltesSpiel.port}` : 'Port'} value={serverDraft.port} onChange={(e) => setServerDraft({ ...serverDraft, port: e.target.value })} />
|
<input type="text" style={{ flex: 'none', width: '6rem' }} placeholder={gewaehltesSpiel?.port ? `Port ${gewaehltesSpiel.port}` : 'Port'} value={serverDraft.port} onChange={(e) => setServerDraft({ ...serverDraft, port: e.target.value })} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<p className="field-hint" style={{ marginTop: '.3rem' }}>
|
<p className="field-hint" style={{ marginTop: '.3rem' }}>
|
||||||
{gewaehltesSpiel
|
{gewaehltesSpiel
|
||||||
? <>Gewählt: <b>{gewaehltesSpiel.name}</b>{!gewaehltesSpiel.eigen && gewaehltesSpiel.port ? ` — Standard-Query-Port ${gewaehltesSpiel.port}` : ''}. Die Liste kommt direkt aus gamedig, {games.length} Einträge.</>
|
? <>Gewählt: <b>{gewaehltesSpiel.name}</b>{!gewaehltesSpiel.eigen && gewaehltesSpiel.port ? ` — Standard-Query-Port ${gewaehltesSpiel.port}, Hoster weichen oft davon ab` : ''}. Die Liste kommt direkt aus gamedig, {games.length} Einträge.</>
|
||||||
: <>Unbekannte ID — sie wird trotzdem versucht. Alle bekannten stehen in der <a href="https://github.com/gamedig/node-gamedig/blob/master/GAMES_LIST.md" target="_blank" rel="noreferrer" style={{ textDecoration: 'underline' }}>gamedig-Liste</a>.</>}
|
: <>Unbekannte ID — sie wird trotzdem versucht. Alle bekannten stehen in der <a href="https://github.com/gamedig/node-gamedig/blob/master/GAMES_LIST.md" target="_blank" rel="noreferrer" style={{ textDecoration: 'underline' }}>gamedig-Liste</a>.</>}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -3358,7 +3390,7 @@ export default function Settings({ me }) {
|
|||||||
/>
|
/>
|
||||||
<p className="field-hint" style={{ marginTop: '.3rem' }}>
|
<p className="field-hint" style={{ marginTop: '.3rem' }}>
|
||||||
{gewaehltesSpiel.id.startsWith('farmingsimulator')
|
{gewaehltesSpiel.id.startsWith('farmingsimulator')
|
||||||
? <>Im Spiel heißt er <b>Code</b>. Steht im Webinterface des Servers unter <code>http://host:{gewaehltesSpiel.port ?? 8080}/settings.html</code> — er gilt nur für den eigenen Server.</>
|
? <>Im Spiel heißt er <b>Code</b> und steckt in der Abfrage-URL, die dein Hoster ausgibt: <code>…/feed/dedicated-server-stats.xml?code=<b>DAS_HIER</b></code>. Am einfachsten die ganze URL oben ins Host-Feld einfügen — Host, Port und Code werden herausgezogen.</>
|
||||||
: <>Steht im Webinterface des Servers. Ohne ihn liefert die Abfrage nichts und der Server stünde dauerhaft auf „offline".</>}
|
: <>Steht im Webinterface des Servers. Ohne ihn liefert die Abfrage nichts und der Server stünde dauerhaft auf „offline".</>}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1835,6 +1835,11 @@ label.toggle {
|
|||||||
color: var(--muted); background: var(--bg3);
|
color: var(--muted); background: var(--bg3);
|
||||||
border: 1px solid var(--border); border-radius: 5px; padding: .22rem .5rem;
|
border: 1px solid var(--border); border-radius: 5px; padding: .22rem .5rem;
|
||||||
}
|
}
|
||||||
|
/* Steht anstelle des Verlaufs, wenn es nichts zu zeigen gibt */
|
||||||
|
.srv-leer {
|
||||||
|
font-family: var(--mono); font-size: .68rem; color: var(--muted2);
|
||||||
|
margin-top: 1rem; letter-spacing: .04em;
|
||||||
|
}
|
||||||
.srv-weg {
|
.srv-weg {
|
||||||
font-family: var(--mono); font-size: .7rem; color: #f23f43;
|
font-family: var(--mono); font-size: .7rem; color: #f23f43;
|
||||||
margin-top: .9rem; letter-spacing: .04em;
|
margin-top: .9rem; letter-spacing: .04em;
|
||||||
|
|||||||
Reference in New Issue
Block a user