Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"xp-forge/marshalling": "^2.4",
"xp-forge/web": "^4.6",
"xp-forge/web-auth": "^7.0",
"xp-forge/frontend": "^7.0",
"xp-forge/frontend": "^7.4",
"xp-forge/rest-api": "^5.0",
"xp-forge/rest-client": "^6.0",
"xp-forge/handlebars-templates": "^4.0",
Expand Down
9 changes: 9 additions & 0 deletions src/it/php/de/thekid/dialog/unittest/ServeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ public function type_ahead_api_publicly_accessible() {
);
}

#[Test]
public function handles_404() {
$res= $this->serve('GET', '/not-found');
Assert::equals(
[404, 'text/html; charset=utf-8'],
[$res->status(), $res->headers()['Content-Type']]
);
}

#[Test]
public function upload_api_needs_authentication() {
$res= $this->serve('PUT', '/api/entries/test', ['Content-Type' => 'application/json; charset=utf-8'], '{
Expand Down
25 changes: 25 additions & 0 deletions src/main/handlebars/errors/404.handlebars
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{{#> layout}}
{{#*inline "title"}}Nicht gefunden{{/inline}}
{{#*inline "meta"}}
<meta property="og:url" content="{{request.uri}}">
<meta property="og:type" content="website">
<meta property="og:title" content="Nicht gefunden - Dialog">
<meta property="og:description" content="Fotoblog von Timm Friebe">
{{/inline}}
{{#*inline "main"}}

<!-- About me -->
<div class="error">
<h1 title="{{cause.getMessage}}">404: Seite nicht gefunden</h1>

<svg role="graphics-symbol" aria-labelledby="error-message" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><!--!Font Awesome Free v7.2.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2026 Fonticons, Inc.--><path d="M192 32C209.7 32 224 46.3 224 64L224 160L352 160L352 64C352 46.3 366.3 32 384 32C401.7 32 416 46.3 416 64L416 160L480 160C497.7 160 512 174.3 512 192C512 209.7 497.7 224 480 224L480 272.7C381.4 280.8 304 363.4 304 464C304 491.3 309.7 517.3 320 540.9L320 544C320 561.7 305.7 576 288 576C270.3 576 256 561.7 256 544L256 477.3C165.2 462.1 96 383.1 96 288L96 224C78.3 224 64 209.7 64 192C64 174.3 78.3 160 96 160L160 160L160 64C160 46.3 174.3 32 192 32zM496 320C575.5 320 640 384.5 640 464C640 543.5 575.5 608 496 608C416.5 608 352 543.5 352 464C352 384.5 416.5 320 496 320zM555.3 427.3C561.5 421.1 561.5 410.9 555.3 404.7C549.1 398.5 538.9 398.5 532.7 404.7L496 441.4L459.3 404.7C453.1 398.5 442.9 398.5 436.7 404.7C430.5 410.9 430.5 421.1 436.7 427.3L473.4 464L436.7 500.7C430.5 506.9 430.5 517.1 436.7 523.3C442.9 529.5 453.1 529.5 459.3 523.3L496 486.6L532.7 523.3C538.9 529.5 549.1 529.5 555.3 523.3C561.5 517.1 561.5 506.9 555.3 500.7L518.6 464L555.3 427.3z"/></svg>

<p id="error-message">
Unter <kbd>{{cause.path}}</kbd> gibt es nichts zu sehen 🐸
</p>
</div>

&#187; <a href="/">Zurück zur Startseite</a>
{{/inline}}
{{#*inline "scripts"}}{{/inline}}
{{/layout}}
30 changes: 29 additions & 1 deletion src/main/handlebars/layout.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,34 @@
border-bottom-right-radius: .25rem;
}

.error {
margin-bottom: 2rem;

h1 {
font-size: 1.7rem;
color: currentColor;
}

svg {
display: block;
width: 16em;
margin: 3rem auto;
fill: currentColor;
}

p {
font-size: 1.15rem;
}

kbd {
padding: .25rem .25rem;
border-radius: .25rem;
background-color: var(--nav-color);
color: var(--text-color);
word-break: break-all;
}
}

.cover {
margin: -1rem -1rem 1rem -1rem;
background-size: cover;
Expand Down Expand Up @@ -919,7 +947,7 @@
<body class="{{request.cookies.theme}}">
<nav class="navbar" role="navigation" aria-label="main navigation">
<ul>
<li {{#if (equals scope 'home')}}class="active"{{/if}}><a href="/">Home</a></li>
<li {{#if (any (equals scope 'home') cause)}}class="active"{{/if}}><a href="/">Home</a></li>
<li {{#if (any (equals scope 'feed') (equals parent 'feed'))}}class="active"{{/if}}><a href="/feed">Feed</a></li>
<li {{#if (equals scope 'journeys')}}class="active"{{/if}}><a href="/journeys">Reisen</a></li>
{{! Toggle theme }}
Expand Down
23 changes: 12 additions & 11 deletions src/main/php/de/thekid/dialog/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
use web\auth\Basic;
use web\filters\BehindProxy;
use web\frontend\helpers\{Assets, Dates, Numbers};
use web\frontend\{Frontend, AssetsFrom, AssetsManifest, HandlersIn, Handlebars};
use web\frontend\{Frontend, AssetsFrom, AssetsManifest, HandlersIn, Handlebars, Exceptions, CannotRoute};
use web\rest\{RestApi, ResourcesIn};

/** @test de.thekid.dialog.unittest.ServeTest */
Expand Down Expand Up @@ -55,6 +55,16 @@ public function routes() {
$assets= new AssetsFrom($this->environment->path('src/main/webapp'))->with(fn($file) => [
'Cache-Control' => $manifest->immutable($file) ?? 'max-age=604800, must-revalidate'
]);
$frontend= new Frontend(
new HandlersIn('de.thekid.dialog.web', $inject->get(...)),
new Handlebars($this->environment->path('src/main/handlebars'), [
new Dates(new TimeZone('Europe/Berlin')),
new Numbers(),
new Assets($manifest),
$inject->get(Helpers::class),
new Scripts($this->environment->path('src/main/js'), 'dev' === $this->environment->profile()),
]),
);

return [
'/static' => $static,
Expand All @@ -63,16 +73,7 @@ public function routes() {
'/assets' => $assets,
'/image' => $this->storage->with($caching),
'/api' => $auth->optional(new RestApi(new ResourcesIn('de.thekid.dialog.api', $inject->get(...)))),
'/' => new Frontend(
new HandlersIn('de.thekid.dialog.web', $inject->get(...)),
new Handlebars($this->environment->path('src/main/handlebars'), [
new Dates(new TimeZone('Europe/Berlin')),
new Numbers(),
new Assets($manifest),
$inject->get(Helpers::class),
new Scripts($this->environment->path('src/main/js'), 'dev' === $this->environment->profile()),
])
),
'/' => $frontend->handling(new Exceptions()->catch(CannotRoute::class)),
];
}
}
Loading