feat: Lauf von Hand anstossen und Spiegelschalter in der Liste
Direkt nach dem Einrichten wuesste man sonst erst beim naechsten Takt, ob die Zugangsdaten stimmen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3befcc19a3
commit
f5eadefdbb
@@ -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 (
|
||||||
|
<Button
|
||||||
|
art="umriss"
|
||||||
|
disabled={laeuft}
|
||||||
|
onClick={() => {
|
||||||
|
starte(async () => {
|
||||||
|
const daten = new FormData()
|
||||||
|
daten.set('quelle', quelle)
|
||||||
|
const antwort = await laufAnstossen(daten)
|
||||||
|
if (antwort.ok) {
|
||||||
|
toast.success(antwort.meldung)
|
||||||
|
router.refresh()
|
||||||
|
} else {
|
||||||
|
toast.error(antwort.fehler)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{laeuft ? (
|
||||||
|
<Loader2 className="animate-spin" aria-hidden />
|
||||||
|
) : (
|
||||||
|
<RefreshCw aria-hidden />
|
||||||
|
)}
|
||||||
|
Jetzt abrufen
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from 'next'
|
import type { Metadata } from 'next'
|
||||||
import { Plug } from 'lucide-react'
|
import { Plug } from 'lucide-react'
|
||||||
|
import { LaufKnopf } from '@/app/(app)/integrationen/lauf-knopf'
|
||||||
import { TelegramChats } from '@/app/(app)/integrationen/telegram-chats'
|
import { TelegramChats } from '@/app/(app)/integrationen/telegram-chats'
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@@ -27,6 +28,8 @@ type Zeile = {
|
|||||||
/** Und auch eingerichtet? */
|
/** Und auch eingerichtet? */
|
||||||
aktiv: boolean
|
aktiv: boolean
|
||||||
hinweis: string
|
hinweis: string
|
||||||
|
/** Laesst sich der Lauf von Hand anstossen? Der Empfaenger wartet nur. */
|
||||||
|
abrufbar?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function IntegrationenSeite() {
|
export default async function IntegrationenSeite() {
|
||||||
@@ -59,6 +62,7 @@ export default async function IntegrationenSeite() {
|
|||||||
vorgesehen: einst.instanz === 'firma',
|
vorgesehen: einst.instanz === 'firma',
|
||||||
aktiv: einst.zammadAktiv,
|
aktiv: einst.zammadAktiv,
|
||||||
hinweis: 'ZAMMAD_URL und ZAMMAD_TOKEN fehlen.',
|
hinweis: 'ZAMMAD_URL und ZAMMAD_TOKEN fehlen.',
|
||||||
|
abrufbar: einst.zammadAktiv,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
quelle: 'WARTUNGSPLANER',
|
quelle: 'WARTUNGSPLANER',
|
||||||
@@ -77,6 +81,7 @@ export default async function IntegrationenSeite() {
|
|||||||
vorgesehen: einst.instanz === 'daheim',
|
vorgesehen: einst.instanz === 'daheim',
|
||||||
aktiv: einst.telegramAktiv,
|
aktiv: einst.telegramAktiv,
|
||||||
hinweis: 'TELEGRAM_TOKEN fehlt.',
|
hinweis: 'TELEGRAM_TOKEN fehlt.',
|
||||||
|
abrufbar: einst.telegramAktiv,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
quelle: 'SPIEGEL',
|
quelle: 'SPIEGEL',
|
||||||
@@ -88,6 +93,8 @@ export default async function IntegrationenSeite() {
|
|||||||
vorgesehen: true,
|
vorgesehen: true,
|
||||||
aktiv: einst.spiegelSendenAktiv || einst.spiegelEmpfangenAktiv,
|
aktiv: einst.spiegelSendenAktiv || einst.spiegelEmpfangenAktiv,
|
||||||
hinweis: 'SPIEGEL_GEHEIMNIS fehlt.',
|
hinweis: 'SPIEGEL_GEHEIMNIS fehlt.',
|
||||||
|
// Die empfangende Seite ruft nichts ab – sie wartet.
|
||||||
|
abrufbar: einst.spiegelSendenAktiv,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -141,6 +148,12 @@ export default async function IntegrationenSeite() {
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{!zustand && zeile.aktiv && <p>Noch kein Lauf.</p>}
|
{!zustand && zeile.aktiv && <p>Noch kein Lauf.</p>}
|
||||||
|
|
||||||
|
{zeile.abrufbar && (
|
||||||
|
<div className="pt-2">
|
||||||
|
<LaufKnopf quelle={zeile.quelle} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</CardInhalt>
|
</CardInhalt>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ type Eigenschaften = {
|
|||||||
leerText: string
|
leerText: string
|
||||||
mitEinsortieren?: boolean
|
mitEinsortieren?: boolean
|
||||||
mitUebernehmen?: boolean
|
mitUebernehmen?: boolean
|
||||||
|
/** Schalter zum Spiegeln zeigen; nur auf der sendenden Instanz sinnvoll. */
|
||||||
|
mitSpiegeln?: boolean
|
||||||
/** Bearbeiten direkt in der Liste erlauben. */
|
/** Bearbeiten direkt in der Liste erlauben. */
|
||||||
mitBearbeiten?: boolean
|
mitBearbeiten?: boolean
|
||||||
}
|
}
|
||||||
@@ -25,6 +27,7 @@ export function AufgabenListe({
|
|||||||
leerText,
|
leerText,
|
||||||
mitEinsortieren = false,
|
mitEinsortieren = false,
|
||||||
mitUebernehmen = false,
|
mitUebernehmen = false,
|
||||||
|
mitSpiegeln = false,
|
||||||
mitBearbeiten = true,
|
mitBearbeiten = true,
|
||||||
}: Eigenschaften) {
|
}: Eigenschaften) {
|
||||||
const [bearbeitet, setBearbeitet] = useState<string | null>(null)
|
const [bearbeitet, setBearbeitet] = useState<string | null>(null)
|
||||||
@@ -60,6 +63,7 @@ export function AufgabenListe({
|
|||||||
bereiche={bereiche}
|
bereiche={bereiche}
|
||||||
mitEinsortieren={mitEinsortieren}
|
mitEinsortieren={mitEinsortieren}
|
||||||
mitUebernehmen={mitUebernehmen}
|
mitUebernehmen={mitUebernehmen}
|
||||||
|
mitSpiegeln={mitSpiegeln}
|
||||||
{...(mitBearbeiten
|
{...(mitBearbeiten
|
||||||
? { onBearbeiten: () => setBearbeitet(aufgabe.id) }
|
? { onBearbeiten: () => setBearbeitet(aufgabe.id) }
|
||||||
: {})}
|
: {})}
|
||||||
|
|||||||
@@ -3,7 +3,15 @@
|
|||||||
import { useState, useTransition } from 'react'
|
import { useState, useTransition } from 'react'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
import Link from 'next/link'
|
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 { toast } from 'sonner'
|
||||||
import { Button } from '@/components/ui/button'
|
import { Button } from '@/components/ui/button'
|
||||||
import { Kennzeichen } from '@/components/ui/kennzeichen'
|
import { Kennzeichen } from '@/components/ui/kennzeichen'
|
||||||
@@ -22,6 +30,7 @@ import {
|
|||||||
aufgabeLoeschen,
|
aufgabeLoeschen,
|
||||||
einsortieren,
|
einsortieren,
|
||||||
ideeUebernehmen,
|
ideeUebernehmen,
|
||||||
|
spiegelnUmschalten,
|
||||||
statusSetzen,
|
statusSetzen,
|
||||||
type Rueckmeldung,
|
type Rueckmeldung,
|
||||||
} from '@/server/aktionen/aufgaben'
|
} from '@/server/aktionen/aufgaben'
|
||||||
@@ -36,6 +45,8 @@ type Eigenschaften = {
|
|||||||
mitEinsortieren?: boolean
|
mitEinsortieren?: boolean
|
||||||
/** Zeigt den Knopf "Zur Aufgabe machen" (Ideen). */
|
/** Zeigt den Knopf "Zur Aufgabe machen" (Ideen). */
|
||||||
mitUebernehmen?: boolean
|
mitUebernehmen?: boolean
|
||||||
|
/** Zeigt den Schalter zum Spiegeln; nur auf der sendenden Instanz. */
|
||||||
|
mitSpiegeln?: boolean
|
||||||
onBearbeiten?: (aufgabe: AufgabeAnzeige) => void
|
onBearbeiten?: (aufgabe: AufgabeAnzeige) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,6 +55,7 @@ export function AufgabenZeile({
|
|||||||
bereiche = [],
|
bereiche = [],
|
||||||
mitEinsortieren = false,
|
mitEinsortieren = false,
|
||||||
mitUebernehmen = false,
|
mitUebernehmen = false,
|
||||||
|
mitSpiegeln = false,
|
||||||
onBearbeiten,
|
onBearbeiten,
|
||||||
}: Eigenschaften) {
|
}: Eigenschaften) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -198,6 +210,29 @@ export function AufgabenZeile({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex shrink-0 items-center gap-1">
|
<div className="flex shrink-0 items-center gap-1">
|
||||||
|
{mitSpiegeln && (
|
||||||
|
<Button
|
||||||
|
art="leise"
|
||||||
|
groesse="quadrat"
|
||||||
|
title={
|
||||||
|
aufgabe.spiegeln
|
||||||
|
? 'Geht mit nach Hause – hier abschalten'
|
||||||
|
: 'Mit nach Hause spiegeln'
|
||||||
|
}
|
||||||
|
disabled={laeuft}
|
||||||
|
onClick={() => {
|
||||||
|
const daten = new FormData()
|
||||||
|
daten.set('id', aufgabe.id)
|
||||||
|
mitRueckmeldung(() => spiegelnUmschalten(daten))
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Share2
|
||||||
|
className={aufgabe.spiegeln ? 'text-betont' : undefined}
|
||||||
|
aria-hidden
|
||||||
|
/>
|
||||||
|
<span className="sr-only">Spiegeln</span>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{onBearbeiten && (
|
{onBearbeiten && (
|
||||||
<Button
|
<Button
|
||||||
art="leise"
|
art="leise"
|
||||||
|
|||||||
Reference in New Issue
Block a user