update
This commit is contained in:
12
Makefile
12
Makefile
@@ -1,8 +1,9 @@
|
||||
.PHONY: install build run dev auth prod stop logs push pull
|
||||
.PHONY: install build run dev auth prod stop logs push pull loeschen
|
||||
|
||||
PY := .venv/bin/python
|
||||
COMPOSE = docker compose
|
||||
SERVER ?= root@178.104.67.87
|
||||
URL ?= https://buchwerk.marha.de
|
||||
REMOTE ?= /var/www/buchwerk
|
||||
# Themen zwischen lokal und Server abgleichen; TOPIC=<Name> beschränkt auf ein Thema.
|
||||
# Ausgeschlossen: Arbeitsdateien der Agenten (arbeit/) und Logs. Ohne --delete: nichts wird entfernt.
|
||||
@@ -47,3 +48,12 @@ push:
|
||||
pull:
|
||||
rsync -az --progress --mkpath $(SYNC_AUS) "$(SERVER):$(REMOTE)/$(SYNC_QUELLE)" "$(SYNC_QUELLE)"
|
||||
@echo "Geholt: $(SERVER):$(REMOTE)/$(SYNC_QUELLE) → $(SYNC_QUELLE)"
|
||||
|
||||
# Fertige Bücher lassen sich in der Oberfläche nicht löschen. Nur hier, mit Rückfrage:
|
||||
# make loeschen TOPIC="Godot 4" – entfernt das Thema auf dem Server (über die API) und lokal.
|
||||
loeschen:
|
||||
@[ -n "$(TOPIC)" ] || { echo "TOPIC=<Name> angeben"; exit 1; }
|
||||
@printf 'Thema „%s“ samt Buch auf dem Server und lokal unwiderruflich löschen? [j/N] ' "$(TOPIC)"; read a; [ "$$a" = "j" ]
|
||||
curl -fsS -X DELETE "$(URL)/api/topics/$$(python3 -c 'import sys,urllib.parse; print(urllib.parse.quote(sys.argv[1]))' "$(TOPIC)")" && echo
|
||||
rm -rf "storage/$(TOPIC)"
|
||||
@echo "Gelöscht: $(TOPIC)"
|
||||
|
||||
@@ -110,7 +110,7 @@ function tokens(n) { return n >= 1e6 ? (n / 1e6).toFixed(1) + 'M' : n >= 1e3 ? M
|
||||
@click="topic = t.name; navAuf = false">
|
||||
<span class="punkt" :class="t.laeuft ? 'laeuft' : t.status"></span>
|
||||
<span style="flex: 1">{{ t.titel }}</span>
|
||||
<button class="klein sekundaer" title="Löschen" @click.stop="loeschen(t.name)">✕</button>
|
||||
<button v-if="t.status !== 'fertig'" class="klein sekundaer" title="Löschen" @click.stop="loeschen(t.name)">✕</button>
|
||||
</div>
|
||||
<div v-if="!topics.length" style="color: var(--dim); padding: 8px">Noch kein Thema.</div>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,15 @@ import Lesemodus from './Lesemodus.vue'
|
||||
const props = defineProps({ topic: String, laeuft: Boolean, fortschritt: Number })
|
||||
const daten = ref(null)
|
||||
const lesemodus = ref(false)
|
||||
// Vollbild nur aus der Klickgeste heraus (Browser-Vorgabe); iOS-Safari kennt die API nicht.
|
||||
function lesemodusStart() {
|
||||
lesemodus.value = true
|
||||
document.documentElement.requestFullscreen?.().catch(() => {})
|
||||
}
|
||||
function lesemodusEnde() {
|
||||
lesemodus.value = false
|
||||
if (document.fullscreenElement) document.exitFullscreen().catch(() => {})
|
||||
}
|
||||
const navAuf = ref(false)
|
||||
// Wischgeste (nur Buchansicht, nicht im Lesemodus): nach rechts öffnet das Inhaltsverzeichnis, nach links schließt es
|
||||
let wisch = null
|
||||
@@ -100,7 +109,7 @@ onUnmounted(() => window.removeEventListener('keydown', taste))
|
||||
<nav class="guide-nav" :class="{ offen: navAuf }">
|
||||
<button class="schliessen sekundaer klein" @click="navAuf = false">✕ Schließen</button>
|
||||
<div class="werkzeuge">
|
||||
<button class="klein" title="Lesemodus: Abschnitt für Abschnitt" @click="lesemodus = true" :disabled="!abschnitte.length">Lesen ▶</button>
|
||||
<button class="klein" title="Lesemodus: Abschnitt für Abschnitt" @click="lesemodusStart" :disabled="!abschnitte.length">Lesen ▶</button>
|
||||
<a class="knopf klein sekundaer" title="Als Markdown-Datei herunterladen" :href="api.guideMdUrl(topic)" download>MD</a>
|
||||
<a v-if="daten?.pdf" class="knopf klein sekundaer" title="Als PDF herunterladen" :href="api.pdfUrl(topic)" download>PDF</a>
|
||||
</div>
|
||||
@@ -126,7 +135,7 @@ onUnmounted(() => window.removeEventListener('keydown', taste))
|
||||
<div ref="lese" class="lese" @touchstart.passive="wischStart" @touchend.passive="wischEnde">
|
||||
<div class="mobil-leiste">
|
||||
<button class="sekundaer klein" @click="navAuf = !navAuf">☰ Inhalt</button>
|
||||
<button class="klein" @click="lesemodus = true" :disabled="!abschnitte.length">Lesen ▶</button>
|
||||
<button class="klein" @click="lesemodusStart" :disabled="!abschnitte.length">Lesen ▶</button>
|
||||
<a class="knopf klein sekundaer" :href="api.guideMdUrl(topic)" download>MD</a>
|
||||
<a v-if="daten?.pdf" class="knopf klein sekundaer" :href="api.pdfUrl(topic)" download>PDF</a>
|
||||
</div>
|
||||
@@ -175,6 +184,6 @@ onUnmounted(() => window.removeEventListener('keydown', taste))
|
||||
</article>
|
||||
</div>
|
||||
|
||||
<Lesemodus v-if="lesemodus && daten" :daten="daten" :topic="topic" @schliessen="lesemodus = false" />
|
||||
<Lesemodus v-if="lesemodus && daten" :daten="daten" :topic="topic" @schliessen="lesemodusEnde" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -43,7 +43,7 @@ function reset() { if (confirm('Lauf zurücksetzen? Alles außer dem Thema wird
|
||||
<div class="aktionen">
|
||||
<button v-if="!laeuft && !fertig" @click="emit('start')">{{ begonnen ? 'Fortsetzen' : 'Buch erzeugen' }}</button>
|
||||
<button v-if="laeuft" class="sekundaer" @click="emit('pause')">Pause</button>
|
||||
<button v-if="!laeuft && begonnen" class="sekundaer" @click="reset">Zurücksetzen</button>
|
||||
<button v-if="!laeuft && begonnen && !fertig" class="sekundaer" @click="reset">Zurücksetzen</button>
|
||||
<span class="spacer"></span>
|
||||
<span class="badge" :class="statusFarbe[state.status]">{{ statusText[state.status] || state.status }}<template v-if="state.stufe && laeuft"> · {{ state.stufe }}</template></span>
|
||||
<span class="badge">{{ usd(state.kosten_usd) }}</span>
|
||||
|
||||
Reference in New Issue
Block a user