Skip to content

Commit 7622c38

Browse files
authored
Merge pull request #3526 from codeeu/dev
Fix Nova training resource save for anchor CTAs and refine roadmap SVG.
2 parents 3e2fff2 + 78ae490 commit 7622c38

4 files changed

Lines changed: 45 additions & 9 deletions

File tree

app/Nova/TrainingResource.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Nova;
44

5+
use App\Rules\FlexibleUrlOrAnchor;
56
use Illuminate\Http\Request;
67
use Illuminate\Support\Facades\URL;
78
use Laravel\Nova\Fields\Boolean;
@@ -156,19 +157,19 @@ public function fields(Request $request): array
156157

157158
Text::make('Button URL', 'button_url')
158159
->nullable()
159-
->rules('nullable', 'url'),
160+
->rules('nullable', new FlexibleUrlOrAnchor),
160161

161162
Text::make('Secondary button text', 'secondary_button_text')->nullable(),
162163

163164
Text::make('Secondary button URL', 'secondary_button_url')
164165
->nullable()
165-
->rules('nullable', 'url'),
166+
->rules('nullable', new FlexibleUrlOrAnchor),
166167

167168
Text::make('Third button text', 'third_button_text')->nullable(),
168169

169170
Text::make('Third button URL', 'third_button_url')
170171
->nullable()
171-
->rules('nullable', 'url'),
172+
->rules('nullable', new FlexibleUrlOrAnchor),
172173

173174
Text::make('Meta title', 'meta_title')
174175
->nullable()

app/Rules/FlexibleUrlOrAnchor.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace App\Rules;
4+
5+
use Closure;
6+
use Illuminate\Contracts\Validation\ValidationRule;
7+
8+
/**
9+
* Accepts absolute URLs, site-relative paths, or hash anchors (e.g. #key-one-pagers).
10+
* Laravel's built-in "url" rule rejects anchors and many relative paths used in CTAs.
11+
*/
12+
class FlexibleUrlOrAnchor implements ValidationRule
13+
{
14+
public function validate(string $attribute, mixed $value, Closure $fail): void
15+
{
16+
if ($value === null || $value === '') {
17+
return;
18+
}
19+
20+
$value = trim((string) $value);
21+
22+
if (preg_match('/^#([a-zA-Z0-9_-]+)$/', $value) === 1) {
23+
return;
24+
}
25+
26+
// Site-relative path (single leading slash, not protocol-relative)
27+
if (str_starts_with($value, '/') && ! str_starts_with($value, '//')) {
28+
return;
29+
}
30+
31+
if (filter_var($value, FILTER_VALIDATE_URL) !== false) {
32+
return;
33+
}
34+
35+
$fail('Must be a valid URL, a path starting with /, or an anchor like #section-id.');
36+
}
37+
}

database/seeders/TrainingResourceDiscoverDigitalProgrammeSeeder.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,10 @@ public function run(): void
3838
<li>Plan evaluation and feedback to measure outcomes.</li>
3939
<li>Use digital outreach and communication to build awareness and follow-up.</li>
4040
</ol>
41-
<div style="margin-top: 2.25rem;">
41+
<div style="margin-top:2.25rem;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;">
4242
<h2>Roadmap</h2>
4343
<p>Use this roadmap if you do not have time to read the full deliverable. The one-pagers mirror the toolkit flow and provide a practical checklist for implementation.</p>
44-
<a href="https://codeweek-resources.s3.eu-west-1.amazonaws.com/+discover-digital-toolkit/DDP_toolkit_roadmap.pdf" target="_blank" rel="noopener noreferrer">
45-
<img src="https://codeweek-resources.s3.eu-west-1.amazonaws.com/+discover-digital-toolkit/DDP_toolkit_roadmap.svg" alt="Discover Digital Programme roadmap" />
46-
</a>
44+
<img src="https://codeweek-resources.s3.eu-west-1.amazonaws.com/+discover-digital-toolkit/DDP_toolkit_roadmap_small.svg" alt="Discover Digital Programme roadmap diagram" style="display:block;max-width:100%;width:auto;height:auto;margin:0 auto;" />
4745
</div>
4846
HTML,
4947
'body_image' => null,

resources/views/training/show.blade.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
$pageDescription = $trainingResource->meta_description ?: $fallbackDescription;
1212
1313
$introClass = "text-[#20262C] font-normal text-lg md:text-xl p-0 mb-6 [&_p]:p-0 [&_p]:mb-6 [&_a]:text-dark-blue [&_a]:hover:underline";
14-
$contentClass = "text-[#333E48] font-normal text-lg md:text-xl p-0 mb-6 [&_p]:p-0 [&_p]:mb-6 [&_h2]:text-dark-blue [&_h2]:text-2xl [&_h2]:md:text-3xl [&_h2]:leading-[44px] [&_h2]:font-medium [&_h2]:font-['Montserrat'] [&_h2]:mb-4 [&_h3]:text-dark-blue [&_h3]:text-xl [&_h3]:md:text-2xl [&_h3]:font-medium [&_h3]:font-['Montserrat'] [&_h3]:mb-4 [&_ul]:pl-8 [&_ul]:m-0 [&_ul]:mb-6 [&_ul]:list-disc [&_ol]:pl-8 [&_ol]:m-0 [&_ol]:mb-6 [&_ol]:list-decimal [&_li]:p-0 [&_li]:text-lg [&_li]:font-normal [&_li]:leading-7 [&_li]:text-default [&_a]:text-dark-blue [&_a]:hover:underline [&_img]:w-full [&_img]:h-auto [&_img]:my-8";
15-
$pdfClass = "text-[#333E48] font-normal text-lg md:text-xl p-0 mb-6 [&_p]:p-0 [&_p]:mb-4 [&_h2]:text-dark-blue [&_h2]:text-2xl [&_h2]:md:text-3xl [&_h2]:leading-[44px] [&_h2]:font-medium [&_h2]:font-['Montserrat'] [&_h2]:mb-4 [&_ul]:m-0 [&_ul]:mb-6 [&_ul]:list-none [&_ol]:m-0 [&_ol]:mb-6 [&_ol]:list-none [&_li]:p-0 [&_li]:mb-2 [&_li]:font-normal [&_li]:leading-7 [&_li]:text-default [&_a]:text-lg [&_a]:text-dark-blue [&_a]:no-underline [&_a:hover]:underline";
14+
$contentClass = "text-[#333E48] font-normal text-lg md:text-xl p-0 mb-6 [&_p]:p-0 [&_p]:mb-6 [&_h2]:text-dark-blue [&_h2]:text-2xl [&_h2]:md:text-3xl [&_h2]:leading-[44px] [&_h2]:font-medium [&_h2]:font-['Montserrat'] [&_h2]:mb-4 [&_h3]:text-dark-blue [&_h3]:text-xl [&_h3]:md:text-2xl [&_h3]:font-medium [&_h3]:font-['Montserrat'] [&_h3]:mb-4 [&_ul]:pl-8 [&_ul]:m-0 [&_ul]:mb-6 [&_ul]:list-disc [&_ol]:pl-8 [&_ol]:m-0 [&_ol]:mb-6 [&_ol]:list-decimal [&_li]:p-0 [&_li]:text-lg [&_li]:font-normal [&_li]:leading-7 [&_li]:text-default [&_a]:text-dark-blue [&_a]:hover:underline [&_img]:max-w-full [&_img]:w-auto [&_img]:h-auto [&_img]:my-8 [&_img]:mx-auto [&_img]:block";
15+
$pdfClass = "text-[#333E48] font-normal text-lg md:text-xl p-0 mb-6 [&_p]:p-0 [&_p]:mb-4 [&_h2]:text-dark-blue [&_h2]:text-2xl [&_h2]:md:text-3xl [&_h2]:leading-[44px] [&_h2]:font-medium [&_h2]:font-['Montserrat'] [&_h2]:mb-4 [&_ul]:m-0 [&_ul]:mb-6 [&_ul]:list-none [&_ol]:m-0 [&_ol]:mb-6 [&_ol]:list-none [&_li]:p-0 [&_li]:mb-2 [&_li]:font-normal [&_li]:leading-7 [&_li]:text-default [&_li]:break-words [&_a]:text-lg [&_a]:text-dark-blue [&_a]:no-underline [&_a:hover]:underline [&_a]:break-words [&_a]:max-w-full";
1616
$contactsClass = "text-[#333E48] font-normal text-lg md:text-xl p-0 mb-8 [&_p]:p-0 [&_p]:mb-4 [&_h2]:text-dark-blue [&_h2]:text-2xl [&_h2]:md:text-3xl [&_h2]:leading-[44px] [&_h2]:font-medium [&_h2]:font-['Montserrat'] [&_h2]:mb-4 [&_a]:text-dark-blue [&_a]:hover:underline";
1717
$registerClass = "text-[#333E48] font-normal text-base md:text-lg [&_p]:p-0 [&_p]:mb-4 [&_p:last-child]:mb-0 [&_a]:font-medium [&_a]:text-dark-blue [&_a]:hover:underline";
1818
$aboutBoxClass = "text-slate-500 text-[16px] leading-[22px] tablet:text-xl tablet:leading-7 [&_h2]:text-dark-blue [&_h2]:text-2xl [&_h2]:md:text-3xl [&_h2]:leading-[44px] [&_h2]:font-medium [&_h2]:font-['Montserrat'] [&_h2]:mb-3 [&_h3]:text-dark-blue [&_h3]:text-xl [&_h3]:md:text-2xl [&_h3]:font-medium [&_h3]:font-['Montserrat'] [&_h3]:mb-3 [&_p]:p-0 [&_p]:mb-3 [&_p:last-child]:mb-0 [&_ul]:pl-8 [&_ul]:m-0 [&_ul]:mb-2 [&_ul]:list-disc [&_li]:mb-2 [&_li:last-child]:mb-0 [&_a]:font-semibold [&_a]:underline [&_a]:text-dark-blue";

0 commit comments

Comments
 (0)