Manage the Slack digest in the admin

New settings area: the webhook lives in the database and is only shown
shortened afterwards, the environment variable stays as a fallback. A switch
decides whether internal entries travel, a button sends the digest right
away, and every run is recorded with period, count, projects, result and
who triggered it.
This commit is contained in:
Matthias G
2026-08-03 12:13:57 +02:00
parent 65346d0c09
commit 0fd6da62d1
19 changed files with 2663 additions and 31 deletions
+53 -3
View File
@@ -273,7 +273,8 @@
"clients": "Zugänge",
"manage": "Verwalten",
"postTypes": "Beitragsarten",
"api": "API"
"api": "API",
"settings": "Einstellungen"
},
"messages": {
"created": "Angelegt.",
@@ -283,7 +284,12 @@
"invalid": "Bitte prüfe die markierten Felder.",
"slugTaken": "Diesen Slug gibt es schon. Wähle einen anderen.",
"selfAdmin": "Das eigene Verwaltungsrecht kannst du nicht ändern. Das muss ein anderes Verwaltungskonto tun.",
"typeInUse": "Diese Art wird noch benutzt. Nimm stattdessen den Haken bei Aktiv heraus."
"typeInUse": "Diese Art wird noch benutzt. Nimm stattdessen den Haken bei Aktiv heraus.",
"slackSaved": "Die Slack-Einstellungen sind gespeichert.",
"reportSent": "Der Bericht ist raus.",
"reportEmpty": "In den letzten sieben Tagen wurde nichts veröffentlicht, deshalb ging keine Nachricht raus.",
"reportNoWebhook": "Es ist kein Webhook hinterlegt.",
"reportRejected": "Slack hat die Nachricht abgelehnt."
},
"errors": {
"nameRequired": "Trag einen Namen ein.",
@@ -696,7 +702,51 @@
"publishHint": "Kein Zugang darf veröffentlichen. Das bleibt an Konten gebunden."
},
"recentEntries": "Zuletzt bearbeitet",
"allEntries": "Alle Beiträge"
"allEntries": "Alle Beiträge",
"settings": {
"eyebrow": "Verwaltung",
"title": "Einstellungen",
"intro": "Slack-Bericht und was er enthält. Der Zeitplan liegt in Coolify, nicht hier.",
"slack": "Slack",
"save": "Speichern",
"saving": "Wird gespeichert",
"sendNow": "Bericht jetzt senden",
"sending": "Wird gesendet",
"webhookStored": "Hinterlegt, wird nicht mehr angezeigt.",
"webhookFromEnv": "Kommt aus der Umgebungsvariable SLACK_WEBHOOK_URL.",
"replaceWebhook": "Anderen Webhook eintragen",
"schedule": "Zeitplan",
"scheduleText": "Der Lauf startet montags um 08:00 als Aufgabe in Coolify. Er veröffentlicht erst fällige Termine und schickt danach den Bericht. Nichts veröffentlicht heißt keine Nachricht.",
"history": "Verlauf",
"historyMeta": "{count, plural, =0 {kein Lauf} one {# Lauf} other {# Läufe}}",
"historyEmpty": "Noch kein Lauf vermerkt.",
"columns": {
"when": "Wann",
"period": "Zeitraum",
"total": "Einträge",
"projects": "Projekte",
"result": "Ergebnis",
"trigger": "Ausgelöst von"
},
"results": {
"sent": "Verschickt",
"nothing_published": "Nichts veröffentlicht",
"not_configured": "Kein Webhook",
"rejected": "Von Slack abgelehnt"
},
"fields": {
"webhook": "Incoming Webhook",
"includeInternal": "Interne Beiträge mitschicken"
},
"hints": {
"webhook": "Aus Slack unter Incoming Webhooks. Die Adresse hängt fest an einem Kanal.",
"includeInternal": "Slack ist intern, deshalb standardmäßig an. Aus heißt nur Kunden- und öffentliche Beiträge.",
"sendNow": "Schickt den Stand der letzten sieben Tage sofort in den Kanal."
},
"errors": {
"webhookInvalid": "Das sieht nicht nach einer Slack-Webhook-Adresse aus."
}
}
},
"filter": {
"type": "Art",
+53 -3
View File
@@ -273,7 +273,8 @@
"clients": "Access",
"manage": "Manage",
"postTypes": "Post types",
"api": "API"
"api": "API",
"settings": "Settings"
},
"messages": {
"created": "Created.",
@@ -283,7 +284,12 @@
"invalid": "Please check the marked fields.",
"slugTaken": "That slug already exists. Pick another one.",
"selfAdmin": "You cannot change the administration right on your own account. Another administration account has to do it.",
"typeInUse": "This type is still in use. Clear the active checkbox instead."
"typeInUse": "This type is still in use. Clear the active checkbox instead.",
"slackSaved": "The Slack settings are saved.",
"reportSent": "The digest is out.",
"reportEmpty": "Nothing was published in the last seven days, so no message went out.",
"reportNoWebhook": "No webhook is stored.",
"reportRejected": "Slack rejected the message."
},
"errors": {
"nameRequired": "Enter a name.",
@@ -696,7 +702,51 @@
"publishHint": "No access may publish. That stays bound to accounts."
},
"recentEntries": "Recently edited",
"allEntries": "All entries"
"allEntries": "All entries",
"settings": {
"eyebrow": "Administration",
"title": "Settings",
"intro": "The Slack digest and what it contains. The schedule lives in Coolify, not here.",
"slack": "Slack",
"save": "Save",
"saving": "Saving",
"sendNow": "Send the digest now",
"sending": "Sending",
"webhookStored": "Stored, no longer shown.",
"webhookFromEnv": "Comes from the SLACK_WEBHOOK_URL variable.",
"replaceWebhook": "Enter a different webhook",
"schedule": "Schedule",
"scheduleText": "The run starts Mondays at 08:00 as a Coolify task. It publishes due entries first, then sends the digest. Nothing published means no message.",
"history": "History",
"historyMeta": "{count, plural, =0 {no run} one {# run} other {# runs}}",
"historyEmpty": "No run recorded yet.",
"columns": {
"when": "When",
"period": "Period",
"total": "Entries",
"projects": "Projects",
"result": "Result",
"trigger": "Triggered by"
},
"results": {
"sent": "Sent",
"nothing_published": "Nothing published",
"not_configured": "No webhook",
"rejected": "Rejected by Slack"
},
"fields": {
"webhook": "Incoming webhook",
"includeInternal": "Include internal entries"
},
"hints": {
"webhook": "From Slack under Incoming Webhooks. The address is bound to one channel.",
"includeInternal": "Slack is internal, so this is on by default. Off means customer and public entries only.",
"sendNow": "Sends the last seven days into the channel right away."
},
"errors": {
"webhookInvalid": "That does not look like a Slack webhook address."
}
}
},
"filter": {
"type": "Type",