feat: die Oberflaeche zu den vier Werkzeugen
Bisher liessen sie sich nur ueber die API benutzen. Jetzt stehen sie dort, wo man sie sucht. SPEICHER bekommt zwei Karten: "Wozu fehlt ein Bild?" -- Muster und Namensliste hinein, beide Richtungen heraus. Das Muster kommt aus den ADRESSVORLAGEN und wird als Knopfreihe angeboten, damit hier nicht dieselbe Zeichenkette ein zweites Mal getippt wird. "Suchen und Ersetzen in Pfaden" -- und dort gibt es KEINEN Knopf, der es sofort tut. Erst zeigen, dann fragen, dann machen. Die Vorschau nennt die Zahl, die die Entscheidung traegt: wie oft die betroffenen Dateien zusammen geholt wurden. Null heisst, es schaut niemand zu; viertausend heisst, es schaut jemand zu. Gibt es auch nur ein Problem, verschwindet der Ausfuehren-Knopf ganz -- nicht ausgegraut, sondern weg, denn ein Problem verhindert ohnehin alles. EINSTELLUNGEN bekommt "Einstellungen mitnehmen". Herunterladen ist der harmlose Knopf; "mit Geheimnissen" ist rot und fragt nach, mit dem Satz, dass die Datei das Discord-Geheimnis und das Nextcloud-Passwort im Klartext traegt und der Download im Verwaltungs-Verlauf steht. TOKEN bekommen das Feld "Bilder verkleinern auf" -- im Anlege-Formular und im Bearbeiten-Dialog, mit dem Hinweis, dass kleinere Bilder NICHT aufgeblasen werden. In der Liste steht es als "max 512 px" neben den anderen Grenzen. Zwei eigene Stolperer beim Bauen, beide vom Uebersetzer gefangen: ein Patch brach vor dem Schreiben ab, sodass die Haelfte der API-Aufrufe fehlte -- und in FehlendeKarte blieb ein `note` stehen, das niemand mehr benutzte. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { DiscordKarte } from '../components/DiscordKarte'
|
||||
import { VorlagenKarte } from '../components/VorlagenKarte'
|
||||
import { FreigabenKarte } from '../components/FreigabenKarte'
|
||||
import { BenutzerKarte } from '../components/BenutzerKarte'
|
||||
import { MitnehmenKarte } from '../components/MitnehmenKarte'
|
||||
import { MeldungenKarte } from '../components/MeldungenKarte'
|
||||
|
||||
/** Alles, was sich einstellen lässt, an einer Stelle.
|
||||
@@ -34,6 +35,8 @@ export function Einstellungen() {
|
||||
<FreigabenKarte />
|
||||
|
||||
<BenutzerKarte />
|
||||
|
||||
<MitnehmenKarte />
|
||||
<SicherungKarte />
|
||||
<MeldungenKarte />
|
||||
<DiscordKarte />
|
||||
|
||||
@@ -14,8 +14,11 @@ import { api, type Stats } from '../api'
|
||||
import { run, useStore } from '../store'
|
||||
import { bytes } from '../format'
|
||||
import { Karte, Knopf, Leer, Nachfrage, useKopieren } from '../components/Bausteine'
|
||||
import { type Verwaiste } from '../api'
|
||||
import { type Folders, type Verwaiste } from '../api'
|
||||
import { SpeicherKarten } from '../components/SpeicherKarten'
|
||||
import { FehlendeKarte } from '../components/FehlendeKarte'
|
||||
import { ErsetzenKarte } from '../components/ErsetzenKarte'
|
||||
import { api as apiFolders } from '../api'
|
||||
|
||||
export function Speicher() {
|
||||
const note = useStore((s) => s.note)
|
||||
@@ -24,6 +27,13 @@ export function Speicher() {
|
||||
const [zieht, setZieht] = useState(false)
|
||||
const [spart, setSpart] = useState(false)
|
||||
const [fortschritt, setFortschritt] = useState({ thumbs: '', webp: '' })
|
||||
// Die Ordnerliste brauchen zwei Karten hier — geholt wird sie einmal.
|
||||
const [ordnerDaten, setOrdnerDaten] = useState<Folders | null>(null)
|
||||
useEffect(() => {
|
||||
apiFolders.folders().then(setOrdnerDaten).catch(() => {
|
||||
/* die Auswahl bleibt dann bei "(überall)" — kein Grund zu lärmen */
|
||||
})
|
||||
}, [])
|
||||
const [verwaiste, setVerwaiste] = useState<Verwaiste | null>(null)
|
||||
const [sucht, setSucht] = useState(false)
|
||||
const [handelt, setHandelt] = useState(false)
|
||||
@@ -136,6 +146,10 @@ export function Speicher() {
|
||||
</p>
|
||||
</Karte>
|
||||
|
||||
<FehlendeKarte />
|
||||
|
||||
<ErsetzenKarte ordnerDaten={ordnerDaten} fertig={() => setOrdnerDaten(null)} />
|
||||
|
||||
<Karte titel="Wartung">
|
||||
<div className="flex flex-wrap items-center gap-3">
|
||||
<Knopf
|
||||
|
||||
@@ -16,6 +16,7 @@ export function Tokens() {
|
||||
const [darfLoeschen, setDarfLoeschen] = useState(false)
|
||||
const [maxMb, setMaxMb] = useState('')
|
||||
const [quotaMb, setQuotaMb] = useState('')
|
||||
const [maxKante, setMaxKante] = useState('')
|
||||
const [gueltigTage, setGueltigTage] = useState('')
|
||||
const [arten, setArten] = useState<string[]>([])
|
||||
const [legtAn, setLegtAn] = useState(false)
|
||||
@@ -56,6 +57,7 @@ export function Tokens() {
|
||||
canDelete: darfLoeschen,
|
||||
maxMb: maxMb.trim(),
|
||||
quotaMb: quotaMb.trim(),
|
||||
maxKante: maxKante.trim(),
|
||||
arten,
|
||||
gueltigTage: gueltigTage.trim(),
|
||||
}),
|
||||
@@ -125,6 +127,16 @@ export function Tokens() {
|
||||
hinweis="Die Grenze links gilt je Datei. Diese hier gilt für alles zusammen — ohne sie kann ein Token die Platte füllen, es braucht nur genug kleine Dateien."
|
||||
onChange={(e) => setQuotaMb(e.target.value)}
|
||||
/>
|
||||
<Feld
|
||||
label="Bilder verkleinern auf (Pixel, optional)"
|
||||
type="number"
|
||||
min={16}
|
||||
step="64"
|
||||
value={maxKante}
|
||||
placeholder="leer = ablegen wie es kommt"
|
||||
hinweis="Größte Kantenlänge. Kleinere Bilder werden NICHT aufgeblasen. Spart Platz und Ladezeit — als Schutz braucht es das nicht."
|
||||
onChange={(e) => setMaxKante(e.target.value)}
|
||||
/>
|
||||
<Feld
|
||||
label="Gültig für (Tage, optional)"
|
||||
type="number"
|
||||
@@ -273,6 +285,7 @@ export function Tokens() {
|
||||
t.quota_bytes
|
||||
? `${bytes(t.bytes)} von ${bytes(t.quota_bytes)}`
|
||||
: null,
|
||||
t.max_kante ? `max ${t.max_kante} px` : null,
|
||||
t.arten ? t.arten.replaceAll(',', ', ') : null,
|
||||
t.expires_at
|
||||
? `bis ${zeit(t.expires_at).slice(0, 10)}`
|
||||
|
||||
Reference in New Issue
Block a user