feat(org-detail): Verbrauchs-Korrektur direkt an der Kachel, Zahlenfelder ohne Pfeile
Die Korrektur des Verbrauchszählers sitzt jetzt direkt an der Kachel "Verbrauchte Credits", wo man den Zähler sieht, als Eingabefeld mit Korrigieren-Knopf und Sicherheitsrückfrage. Das Feld im Kontingent- Formular entfällt dafür. Außerdem sind die Hochzähl-Pfeile an allen Zahlenfeldern des Portals entfernt. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Dieser Commit ist enthalten in:
@@ -1464,3 +1464,13 @@ details.adv-section .adv-hint { grid-column: 1 / -1; font-size: 12px; color: var
|
||||
background: rgba(239, 68, 68, 0.16);
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
|
||||
/* === Verbrauchs-Korrektur direkt an der Kachel === */
|
||||
.stat-korrektur { display: flex; gap: 6px; margin-top: 10px; }
|
||||
.stat-korrektur input { font-size: 12px; padding: 6px 8px; }
|
||||
|
||||
/* === Zahlenfelder ohne Hochzaehl-Pfeile (portalweit) === */
|
||||
input[type="number"]::-webkit-outer-spin-button,
|
||||
input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
|
||||
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<title>AegisSight Monitor-Verwaltung</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||
<link rel="apple-touch-icon" href="/static/favicon.svg">
|
||||
<link rel="stylesheet" href="/static/css/style.css?v=20260725f">
|
||||
<link rel="stylesheet" href="/static/css/style.css?v=20260725g">
|
||||
<script>(function(){var t=localStorage.getItem('portal_theme');if(t==='light')document.documentElement.setAttribute('data-theme','light');try{var a=JSON.parse(localStorage.getItem('osint_a11y')||'{}');Object.keys(a).forEach(function(k){if(a[k])document.documentElement.setAttribute('data-a11y-'+k,'true');});}catch(e){}})()</script>
|
||||
|
||||
<style>
|
||||
@@ -162,6 +162,10 @@
|
||||
<div class="token-stat-card">
|
||||
<div class="token-stat-label">Verbrauchte Credits (Periode)</div>
|
||||
<div class="token-stat-value" id="tokenCreditsUsed">-</div>
|
||||
<div class="stat-korrektur" title="Überschreibt den Verbrauchszähler direkt, z.B. für Kulanz (Zähler runtersetzen = Credits zurückgeben). Der Kunde sieht die Änderung sofort.">
|
||||
<input type="number" id="korrCreditsUsed" min="0" placeholder="Zähler neu setzen">
|
||||
<button type="button" class="btn btn-secondary btn-small" onclick="korrigiereVerbrauch()">Korrigieren</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="token-stat-card">
|
||||
<div class="token-stat-label">Verbleibend</div>
|
||||
@@ -259,11 +263,6 @@
|
||||
<label for="editWarnPercent">Warnschwelle (%, 0 = aus)</label>
|
||||
<input type="number" id="editWarnPercent" min="0" max="100" placeholder="80">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="editCreditsUsed">Verbrauch korrigieren (Credits, laufende Periode)</label>
|
||||
<input type="number" id="editCreditsUsed" step="0.01" placeholder="Aktueller Verbrauch">
|
||||
<small class="text-secondary">Überschreibt den Verbrauchszähler direkt, z.B. für Kulanz ("Zähler runtersetzen = Credits zurückgeben"). Der Kunde sieht die Änderung sofort.</small>
|
||||
</div>
|
||||
<div style="grid-column:1/-1; display:flex; gap:8px; align-items:center;">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg>
|
||||
@@ -1122,7 +1121,7 @@
|
||||
</div>
|
||||
|
||||
<script src="/static/js/a11y.js?v=20260725a"></script>
|
||||
<script src="/static/js/app.js?v=20260725l"></script>
|
||||
<script src="/static/js/app.js?v=20260725m"></script>
|
||||
<script src="/static/js/sources.js?v=20260522x2"></script>
|
||||
<script src="/static/js/x-scraper.js?v=20260522a"></script>
|
||||
<script src="/static/js/source-health.js?v=20260509l"></script>
|
||||
|
||||
@@ -386,6 +386,37 @@ function setOrgLanguage(wert) {
|
||||
_saveOrgSetting({ output_language: wert }, "Pipeline-Sprache gespeichert");
|
||||
}
|
||||
|
||||
// Verbrauchszähler direkt an der Kachel korrigieren (Kulanz, Fehlbereinigung)
|
||||
async function korrigiereVerbrauch() {
|
||||
const input = document.getElementById("korrCreditsUsed");
|
||||
if (!input || input.value === "") {
|
||||
showToast("Bitte den neuen Zählerstand eintragen", "error");
|
||||
return;
|
||||
}
|
||||
const n = parseFloat(input.value);
|
||||
if (isNaN(n) || n < 0) {
|
||||
showToast("Der Zählerstand muss 0 oder größer sein", "error");
|
||||
return;
|
||||
}
|
||||
showConfirm(
|
||||
"Verbrauch korrigieren",
|
||||
"Verbrauchszähler dieser Organisation auf " + n.toLocaleString("de-DE") + " Credits setzen? Der Kunde sieht die Änderung sofort.",
|
||||
async () => {
|
||||
try {
|
||||
const licenses = await API.get("/api/licenses?org_id=" + currentOrgId);
|
||||
const aktiv = licenses.find(l => l.status === "active");
|
||||
if (!aktiv) { showToast("Keine aktive Lizenz gefunden", "error"); return; }
|
||||
await API.put("/api/token-usage/budget/" + aktiv.id, { credits_used: n });
|
||||
input.value = "";
|
||||
showToast("Verbrauchszähler gesetzt", "success");
|
||||
loadOrgTokenUsage(currentOrgId);
|
||||
} catch (err) {
|
||||
showToast(err.message, "error");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Max Nutzer der aktiven Lizenz direkt in der Tabelle ändern
|
||||
async function setLicenseMaxUsers(licId, wert) {
|
||||
const n = parseInt(wert, 10);
|
||||
@@ -1124,7 +1155,6 @@ async function loadOrgTokenUsage(orgId) {
|
||||
function fillBudgetForm(budget) {
|
||||
const el = (id, val) => { const e = document.getElementById(id); if (e && val != null) e.value = val; };
|
||||
el('editCreditsTotal', budget.credits_total);
|
||||
el('editCreditsUsed', budget.credits_used ? Math.round(budget.credits_used) : 0);
|
||||
el('editWarnPercent', budget.budget_warning_percent);
|
||||
const periodSel = document.getElementById('editCreditsPeriod');
|
||||
if (periodSel) periodSel.value = budget.credits_period || 'monthly';
|
||||
@@ -1282,7 +1312,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
body.unlimited_budget = isUnlimited;
|
||||
|
||||
var creditsTotal = document.getElementById('editCreditsTotal');
|
||||
var creditsUsed = document.getElementById('editCreditsUsed');
|
||||
|
||||
if (!isUnlimited) {
|
||||
if (creditsTotal && creditsTotal.value) body.credits_total = parseInt(creditsTotal.value);
|
||||
@@ -1295,8 +1324,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
var warnPercent = document.getElementById('editWarnPercent');
|
||||
if (warnPercent && warnPercent.value) body.budget_warning_percent = parseInt(warnPercent.value);
|
||||
}
|
||||
// credits_used immer mitsenden (auch im Unlimited-Modus, fuer Korrekturen)
|
||||
if (creditsUsed && creditsUsed.value !== '') body.credits_used = parseFloat(creditsUsed.value);
|
||||
|
||||
var result = await API.put('/api/token-usage/budget/' + activeLic.id, body);
|
||||
if (msgEl) {
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren