diff --git a/src/app/(app)/integrationen/lauf-knopf.tsx b/src/app/(app)/integrationen/lauf-knopf.tsx
new file mode 100644
index 0000000..35198af
--- /dev/null
+++ b/src/app/(app)/integrationen/lauf-knopf.tsx
@@ -0,0 +1,46 @@
+'use client'
+
+import { useTransition } from 'react'
+import { useRouter } from 'next/navigation'
+import { Loader2, RefreshCw } from 'lucide-react'
+import { toast } from 'sonner'
+import { Button } from '@/components/ui/button'
+import { laufAnstossen } from '@/server/aktionen/integrationen'
+
+/**
+ * Stößt einen Lauf von Hand an.
+ *
+ * Vor allem direkt nach dem Einrichten: Sonst wüsste man erst beim nächsten
+ * Takt, ob die Zugangsdaten stimmen.
+ */
+export function LaufKnopf({ quelle }: { quelle: string }) {
+ const router = useRouter()
+ const [laeuft, starte] = useTransition()
+
+ return (
+
+ )
+}
diff --git a/src/app/(app)/integrationen/page.tsx b/src/app/(app)/integrationen/page.tsx
index 079483d..c768703 100644
--- a/src/app/(app)/integrationen/page.tsx
+++ b/src/app/(app)/integrationen/page.tsx
@@ -1,5 +1,6 @@
import type { Metadata } from 'next'
import { Plug } from 'lucide-react'
+import { LaufKnopf } from '@/app/(app)/integrationen/lauf-knopf'
import { TelegramChats } from '@/app/(app)/integrationen/telegram-chats'
import {
Card,
@@ -27,6 +28,8 @@ type Zeile = {
/** Und auch eingerichtet? */
aktiv: boolean
hinweis: string
+ /** Laesst sich der Lauf von Hand anstossen? Der Empfaenger wartet nur. */
+ abrufbar?: boolean
}
export default async function IntegrationenSeite() {
@@ -59,6 +62,7 @@ export default async function IntegrationenSeite() {
vorgesehen: einst.instanz === 'firma',
aktiv: einst.zammadAktiv,
hinweis: 'ZAMMAD_URL und ZAMMAD_TOKEN fehlen.',
+ abrufbar: einst.zammadAktiv,
},
{
quelle: 'WARTUNGSPLANER',
@@ -77,6 +81,7 @@ export default async function IntegrationenSeite() {
vorgesehen: einst.instanz === 'daheim',
aktiv: einst.telegramAktiv,
hinweis: 'TELEGRAM_TOKEN fehlt.',
+ abrufbar: einst.telegramAktiv,
},
{
quelle: 'SPIEGEL',
@@ -88,6 +93,8 @@ export default async function IntegrationenSeite() {
vorgesehen: true,
aktiv: einst.spiegelSendenAktiv || einst.spiegelEmpfangenAktiv,
hinweis: 'SPIEGEL_GEHEIMNIS fehlt.',
+ // Die empfangende Seite ruft nichts ab – sie wartet.
+ abrufbar: einst.spiegelSendenAktiv,
},
]
@@ -141,6 +148,12 @@ export default async function IntegrationenSeite() {
)}
{!zustand && zeile.aktiv && Noch kein Lauf.
}
+
+ {zeile.abrufbar && (
+
+
+
+ )}
)
diff --git a/src/components/aufgaben/aufgaben-liste.tsx b/src/components/aufgaben/aufgaben-liste.tsx
index 4e3dfac..29784d4 100644
--- a/src/components/aufgaben/aufgaben-liste.tsx
+++ b/src/components/aufgaben/aufgaben-liste.tsx
@@ -14,6 +14,8 @@ type Eigenschaften = {
leerText: string
mitEinsortieren?: boolean
mitUebernehmen?: boolean
+ /** Schalter zum Spiegeln zeigen; nur auf der sendenden Instanz sinnvoll. */
+ mitSpiegeln?: boolean
/** Bearbeiten direkt in der Liste erlauben. */
mitBearbeiten?: boolean
}
@@ -25,6 +27,7 @@ export function AufgabenListe({
leerText,
mitEinsortieren = false,
mitUebernehmen = false,
+ mitSpiegeln = false,
mitBearbeiten = true,
}: Eigenschaften) {
const [bearbeitet, setBearbeitet] = useState(null)
@@ -60,6 +63,7 @@ export function AufgabenListe({
bereiche={bereiche}
mitEinsortieren={mitEinsortieren}
mitUebernehmen={mitUebernehmen}
+ mitSpiegeln={mitSpiegeln}
{...(mitBearbeiten
? { onBearbeiten: () => setBearbeitet(aufgabe.id) }
: {})}
diff --git a/src/components/aufgaben/aufgaben-zeile.tsx b/src/components/aufgaben/aufgaben-zeile.tsx
index 73476a1..752adac 100644
--- a/src/components/aufgaben/aufgaben-zeile.tsx
+++ b/src/components/aufgaben/aufgaben-zeile.tsx
@@ -3,7 +3,15 @@
import { useState, useTransition } from 'react'
import { useRouter } from 'next/navigation'
import Link from 'next/link'
-import { Check, ExternalLink, Loader2, Pencil, RotateCcw, Trash2 } from 'lucide-react'
+import {
+ Check,
+ ExternalLink,
+ Loader2,
+ Pencil,
+ RotateCcw,
+ Share2,
+ Trash2,
+} from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import { Kennzeichen } from '@/components/ui/kennzeichen'
@@ -22,6 +30,7 @@ import {
aufgabeLoeschen,
einsortieren,
ideeUebernehmen,
+ spiegelnUmschalten,
statusSetzen,
type Rueckmeldung,
} from '@/server/aktionen/aufgaben'
@@ -36,6 +45,8 @@ type Eigenschaften = {
mitEinsortieren?: boolean
/** Zeigt den Knopf "Zur Aufgabe machen" (Ideen). */
mitUebernehmen?: boolean
+ /** Zeigt den Schalter zum Spiegeln; nur auf der sendenden Instanz. */
+ mitSpiegeln?: boolean
onBearbeiten?: (aufgabe: AufgabeAnzeige) => void
}
@@ -44,6 +55,7 @@ export function AufgabenZeile({
bereiche = [],
mitEinsortieren = false,
mitUebernehmen = false,
+ mitSpiegeln = false,
onBearbeiten,
}: Eigenschaften) {
const router = useRouter()
@@ -198,6 +210,29 @@ export function AufgabenZeile({
+ {mitSpiegeln && (
+
+ )}
{onBearbeiten && (