Add related help titles and fix umlauts
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (push) Has been cancelled
tests / ui (push) Has been cancelled

This commit is contained in:
Codex Agent
2026-01-23 10:05:29 +01:00
parent df5e8204fa
commit 0db0ddf3c4
5 changed files with 72 additions and 7 deletions

View File

@@ -4,6 +4,7 @@ namespace App\Services\Help;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str; use Illuminate\Support\Str;
@@ -70,6 +71,8 @@ class HelpSyncService
} }
} }
$articles = $this->hydrateRelatedTitles($articles);
$disk = config('help.disk'); $disk = config('help.disk');
$compiledPath = trim(config('help.compiled_path'), '/'); $compiledPath = trim(config('help.compiled_path'), '/');
$written = []; $written = [];
@@ -87,6 +90,58 @@ class HelpSyncService
return $written; return $written;
} }
private function hydrateRelatedTitles(Collection $articles): Collection
{
$titleIndex = $articles->mapWithKeys(function (array $article) {
$audience = Arr::get($article, 'audience');
$locale = Arr::get($article, 'locale');
$slug = Arr::get($article, 'slug');
if (! $audience || ! $locale || ! $slug) {
return [];
}
return [$this->articleKey((string) $audience, (string) $locale, (string) $slug) => Arr::get($article, 'title')];
});
return $articles->map(function (array $article) use ($titleIndex) {
$related = Arr::get($article, 'related', []);
if (empty($related)) {
return $article;
}
$audience = (string) Arr::get($article, 'audience');
$locale = (string) Arr::get($article, 'locale');
$article['related'] = collect($related)
->map(function ($item) use ($titleIndex, $audience, $locale) {
$slug = is_array($item) ? Arr::get($item, 'slug') : (is_string($item) ? $item : null);
if (! $slug) {
return null;
}
$title = $titleIndex->get($this->articleKey($audience, $locale, $slug));
return array_filter([
'slug' => $slug,
'title' => $title,
], static fn ($value) => $value !== null && $value !== '');
})
->filter()
->values()
->all();
return $article;
});
}
private function articleKey(string $audience, string $locale, string $slug): string
{
return sprintf('%s::%s::%s', $audience, $locale, $slug);
}
private function parseFile(SplFileInfo $file): array private function parseFile(SplFileInfo $file): array
{ {
$contents = $this->files->get($file->getPathname()); $contents = $this->files->get($file->getPathname());

View File

@@ -3,7 +3,7 @@ title: "FAQ: Event-Admin"
locale: de locale: de
slug: faq-admin slug: faq-admin
audience: admin audience: admin
summary: "Kurze Antworten auf die haeufigsten Fragen von Event-Admins." summary: "Kurze Antworten auf die häufigsten Fragen von Event-Admins."
version_introduced: 2025.4 version_introduced: 2025.4
requires_app_version: "^3.2.0" requires_app_version: "^3.2.0"
status: draft status: draft
@@ -19,8 +19,8 @@ related:
**Wo finde ich Join-Link oder QR-Code?** **Wo finde ich Join-Link oder QR-Code?**
Im Event-Dashboard unter den Schnellaktionen. Im Event-Dashboard unter den Schnellaktionen.
**Gaeste koennen nicht beitreten.** **Gäste können nicht beitreten.**
Pruefe, ob das Event **veroeffentlicht** ist, und teile den Join-Link oder QR erneut. Prüfe, ob das Event **veröffentlicht** ist, und teile den Join-Link oder QR erneut.
## Uploads & Moderation ## Uploads & Moderation
**Uploads erscheinen nicht.** **Uploads erscheinen nicht.**
@@ -31,7 +31,7 @@ Im Control Room ausblenden, dann verschwindet es sofort aus der Galerie.
## Live Show ## Live Show
**Die Live Show bleibt leer.** **Die Live Show bleibt leer.**
Pruefe den Show-Link und ob Fotos freigegeben wurden. Prüfe den Show-Link und ob Fotos freigegeben wurden.
### Weitere Hilfe ### Weitere Hilfe
`control-room-moderation` fuer die Queue oder `live-show-setup` fuer die Leinwand. `control-room-moderation` für die Queue oder `live-show-setup` für die Leinwand.

View File

@@ -18,7 +18,7 @@ Dieses Portal sammelt alles, was Event-Admins für Vorbereitung, Kern-Workflows
| --- | --- | --- | | --- | --- | --- |
| Dashboard | Wo sehe ich Status, KPIs und Schnellaktionen? | `tenant-dashboard-overview` | | Dashboard | Wo sehe ich Status, KPIs und Schnellaktionen? | `tenant-dashboard-overview` |
| Event-Vorbereitung | Was muss vor dem Start erledigt sein? | `event-prep-checklist` | | Event-Vorbereitung | Was muss vor dem Start erledigt sein? | `event-prep-checklist` |
| FAQ | Was sind die haeufigsten Fragen? | `faq-admin` | | FAQ | Was sind die häufigsten Fragen? | `faq-admin` |
| Control Room | Wie moderiere ich Uploads und steuere die Queue? | `control-room-moderation` | | Control Room | Wie moderiere ich Uploads und steuere die Queue? | `control-room-moderation` |
| Live Show | Wie richte ich den Live-Show-Player ein? | `live-show-setup` | | Live Show | Wie richte ich den Live-Show-Player ein? | `live-show-setup` |
| Abschluss & Exporte | Was erledige ich nach dem Event? | `post-event-wrapup` | | Abschluss & Exporte | Was erledige ich nach dem Event? | `post-event-wrapup` |

View File

@@ -365,7 +365,7 @@ export type HelpCenterArticleSummary = {
updated_at?: string; updated_at?: string;
status?: string; status?: string;
translation_state?: string; translation_state?: string;
related?: Array<{ slug: string }>; related?: Array<{ slug: string; title?: string | null }>;
}; };
export type HelpCenterArticle = HelpCenterArticleSummary & { export type HelpCenterArticle = HelpCenterArticleSummary & {

View File

@@ -20,5 +20,15 @@ class HelpSyncServiceTest extends TestCase
$this->assertNotEmpty($result); $this->assertNotEmpty($result);
Storage::disk('local')->assertExists('help/guest/en/articles.json'); Storage::disk('local')->assertExists('help/guest/en/articles.json');
Storage::disk('local')->assertExists('help/guest/de/articles.json'); Storage::disk('local')->assertExists('help/guest/de/articles.json');
Storage::disk('local')->assertExists('help/admin/en/articles.json');
$articles = json_decode(Storage::disk('local')->get('help/admin/en/articles.json'), true);
$this->assertIsArray($articles);
$controlRoom = collect($articles)->firstWhere('slug', 'control-room-moderation');
$this->assertNotNull($controlRoom);
$related = collect($controlRoom['related'] ?? [])->firstWhere('slug', 'event-prep-checklist');
$this->assertSame('Event Preparation Checklist', $related['title'] ?? null);
} }
} }