From 793e4bacbda42b45a1ab40519da8a93b28ae5222 Mon Sep 17 00:00:00 2001 From: philipp lang Date: Thu, 4 Jul 2024 23:54:37 +0200 Subject: [PATCH] Add mail view --- app/Form/Actions/PreventionRememberAction.php | 6 +- app/Lib/Editor/EditorData.php | 60 +++++++++++++++++++ app/Prevention/Actions/SettingStoreAction.php | 5 +- .../Mails/PreventionRememberMail.php | 7 ++- app/Prevention/PreventionSettings.php | 3 +- ...7_04_202013_create_prevention_settings.php | 2 +- .../prevention-remember-participant.blade.php | 6 +- tests/Feature/Member/PreventionTest.php | 36 +++++++++-- tests/Feature/Prevention/SettingTest.php | 8 +-- .../RequestFactories/EditorRequestFactory.php | 25 ++++++++ tests/Unit/EditorDataTest.php | 19 ++++++ 11 files changed, 155 insertions(+), 22 deletions(-) create mode 100644 app/Lib/Editor/EditorData.php create mode 100644 tests/Unit/EditorDataTest.php diff --git a/app/Form/Actions/PreventionRememberAction.php b/app/Form/Actions/PreventionRememberAction.php index e1910165..76b3c1ba 100644 --- a/app/Form/Actions/PreventionRememberAction.php +++ b/app/Form/Actions/PreventionRememberAction.php @@ -4,6 +4,7 @@ namespace App\Form\Actions; use App\Form\Models\Participant; use App\Prevention\Mails\PreventionRememberMail; +use App\Prevention\PreventionSettings; use Illuminate\Support\Facades\Mail; use Lorisleiva\Actions\Concerns\AsAction; @@ -26,11 +27,14 @@ class PreventionRememberAction return; } + $body = app(PreventionSettings::class)->formmail + ->placeholder('formname', $participant->form->name); + if ($participant->getFields()->getMailRecipient() === null) { continue; } - Mail::send(new PreventionRememberMail($participant)); + Mail::send(new PreventionRememberMail($participant, $body)); $participant->update(['last_remembered_at' => now()]); } diff --git a/app/Lib/Editor/EditorData.php b/app/Lib/Editor/EditorData.php new file mode 100644 index 00000000..87f7f4a2 --- /dev/null +++ b/app/Lib/Editor/EditorData.php @@ -0,0 +1,60 @@ +blocks))->replace('{' . $search . '}', $replacement); + $this->blocks = json_decode($replacedBlocks); + + return $this; + } + + /** + * @param array $wanted + */ + public function hasAll(array $wanted): bool + { + return collect($wanted)->first(fn ($search) => !str(json_encode($this->blocks))->contains($search)) === null; + } + + public function replaceWithList(string $blockContent, array $replacements): self + { + $this->blocks = collect($this->blocks)->map(function ($block) use ($blockContent, $replacements) { + if (data_get($block, 'type') !== 'paragraph') { + return $block; + } + + if (data_get($block, 'data.text') === '{' . $blockContent . '}') { + return [ + ...((array)$block), + 'type' => 'list', + 'data' => [ + 'style' => 'unordered', + 'items' => collect($replacements)->map(fn ($replacement) => [ + 'content' => $replacement, + 'items' => [], + ]), + ] + ]; + } + + return $block; + })->toArray(); + + + return $this; + } +} diff --git a/app/Prevention/Actions/SettingStoreAction.php b/app/Prevention/Actions/SettingStoreAction.php index a8d12cb2..57263463 100644 --- a/app/Prevention/Actions/SettingStoreAction.php +++ b/app/Prevention/Actions/SettingStoreAction.php @@ -2,6 +2,7 @@ namespace App\Prevention\Actions; +use App\Lib\Editor\EditorData; use App\Lib\Events\Succeeded; use App\Prevention\PreventionSettings; use Lorisleiva\Actions\ActionRequest; @@ -20,7 +21,9 @@ class SettingStoreAction public function handle(ActionRequest $request): void { - app(PreventionSettings::class)->fill($request->validated())->save(); + $settings = app(PreventionSettings::class); + $settings->formmail = EditorData::from($request->formmail); + $settings->save(); Succeeded::message('Einstellungen gespeichert.')->dispatch(); } diff --git a/app/Prevention/Mails/PreventionRememberMail.php b/app/Prevention/Mails/PreventionRememberMail.php index e2833701..d435d1a7 100644 --- a/app/Prevention/Mails/PreventionRememberMail.php +++ b/app/Prevention/Mails/PreventionRememberMail.php @@ -3,6 +3,7 @@ namespace App\Prevention\Mails; use App\Invoice\InvoiceSettings; +use App\Lib\Editor\EditorData; use App\Prevention\Contracts\Preventable; use Illuminate\Bus\Queueable; use Illuminate\Mail\Attachment; @@ -16,15 +17,15 @@ class PreventionRememberMail extends Mailable use Queueable, SerializesModels; public InvoiceSettings $settings; - public string $documents; /** * Create a new message instance. */ - public function __construct(public Preventable $preventable) + public function __construct(public Preventable $preventable, public EditorData $bodyText) { $this->settings = app(InvoiceSettings::class); - $this->documents = collect($preventable->preventions())->map(fn ($prevention) => "* {$prevention->text()}")->implode("\n"); + $this->bodyText = $this->bodyText + ->replaceWithList('wanted', collect($preventable->preventions())->map(fn ($prevention) => $prevention->text())->toArray()); } /** diff --git a/app/Prevention/PreventionSettings.php b/app/Prevention/PreventionSettings.php index 0a24e7f5..90518f44 100644 --- a/app/Prevention/PreventionSettings.php +++ b/app/Prevention/PreventionSettings.php @@ -2,6 +2,7 @@ namespace App\Prevention; +use App\Lib\Editor\EditorData; use App\Prevention\Actions\PreventionIndexAction; use App\Setting\Contracts\Indexable; use App\Setting\LocalSettings; @@ -9,7 +10,7 @@ use App\Setting\LocalSettings; class PreventionSettings extends LocalSettings implements Indexable { - public array $formmail; + public EditorData $formmail; public static function group(): string { diff --git a/database/settings/2024_07_04_202013_create_prevention_settings.php b/database/settings/2024_07_04_202013_create_prevention_settings.php index 5884aaa3..53e4eaf1 100644 --- a/database/settings/2024_07_04_202013_create_prevention_settings.php +++ b/database/settings/2024_07_04_202013_create_prevention_settings.php @@ -6,6 +6,6 @@ return new class extends SettingsMigration { public function up(): void { - $this->migrator->add('prevention.formmail', ['time' => 1, 'blocks' => []]); + $this->migrator->add('prevention.formmail', ['time' => 1, 'blocks' => [], 'version' => '1.0']); } }; diff --git a/resources/views/mail/prevention/prevention-remember-participant.blade.php b/resources/views/mail/prevention/prevention-remember-participant.blade.php index 1e67be9f..ea9e398b 100644 --- a/resources/views/mail/prevention/prevention-remember-participant.blade.php +++ b/resources/views/mail/prevention/prevention-remember-participant.blade.php @@ -1,11 +1,7 @@ @component('mail::message') # Hallo {{ $preventable->member->fullname }}, -Du hast dich für die Veranstaltung __{{$preventable->form->name}}__ angemeldet. - -Damit du an der Veranstaltung als leitende oder helfende Person teilnehmen kannst, ist noch folgendes einzureichen oder zu beachten. - -{!! $documents !!} + @component('mail::subcopy') diff --git a/tests/Feature/Member/PreventionTest.php b/tests/Feature/Member/PreventionTest.php index 678ab1ed..85eb3bbc 100644 --- a/tests/Feature/Member/PreventionTest.php +++ b/tests/Feature/Member/PreventionTest.php @@ -13,10 +13,12 @@ use App\Prevention\Mails\PreventionRememberMail; use App\Member\Member; use App\Member\Membership; use App\Prevention\PreventionSettings; +use BillSettings; use Generator; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Support\Facades\Mail; use Tests\Lib\CreatesFormFields; +use Tests\RequestFactories\EditorRequestFactory; use Tests\TestCase; class PreventionTest extends TestCase @@ -176,12 +178,36 @@ class PreventionTest extends TestCase InvoiceSettings::fake(['from_long' => 'Stamm Beispiel']); $form = $this->createForm(); $participant = $this->createParticipant($form); - (new PreventionRememberMail($participant)) + (new PreventionRememberMail($participant, app(PreventionSettings::class)->formmail)) ->assertSeeInText($participant->member->firstname) - ->assertSeeInText($participant->form->name) - ->assertSeeInText('erweitertes Führungszeugnis') - ->assertSeeInText('Stamm Beispiel') - ->assertSeeInText($participant->member->lastname); + ->assertSeeInText($participant->member->lastname) + ->assertSeeInText('Stamm Beispiel'); + } + + public function testItRendersSetttingMail(): void + { + Mail::fake(); + app(PreventionSettings::class)->fake([ + 'formmail' => EditorRequestFactory::new()->paragraphs(["lorem lala {formname} g", "{wanted}", "bbb"])->toData() + ])->save(); + $form = $this->createForm(); + $this->createParticipant($form); + + PreventionRememberAction::run(); + + Mail::assertSent(PreventionRememberMail::class, fn ($mail) => $mail->bodyText->hasAll([ + 'lorem lala ' . $form->name, + 'erweitertes' + ])); + } + + public function testItDisplaysBodyTextInMail(): void + { + $form = $this->createForm(); + $participant = $this->createParticipant($form); + + $mail = new PreventionRememberMail($participant, EditorRequestFactory::new()->paragraphs(['ggtt'])->toData()); + $mail->assertSeeInText('ggtt'); } protected function createForm(): Form diff --git a/tests/Feature/Prevention/SettingTest.php b/tests/Feature/Prevention/SettingTest.php index 783b5423..b67fd4b4 100644 --- a/tests/Feature/Prevention/SettingTest.php +++ b/tests/Feature/Prevention/SettingTest.php @@ -23,7 +23,7 @@ class SettingTest extends TestCase { $this->login()->loginNami(); - $text = EditorRequestFactory::new()->text(50, 'lorem ipsum')->create(); + $text = EditorRequestFactory::new()->text(50, 'lorem ipsum')->toData(); app(PreventionSettings::class)->fill(['formmail' => $text])->save(); $this->get('/api/prevention') @@ -34,9 +34,7 @@ class SettingTest extends TestCase { $this->login()->loginNami(); - $text = EditorRequestFactory::new()->text(50, 'new lorem')->create(); - - $this->post('/api/prevention', ['formmail' => $text])->assertOk(); - $this->assertEquals($text, app(PreventionSettings::class)->formmail); + $this->post('/api/prevention', ['formmail' => EditorRequestFactory::new()->text(50, 'new lorem')->create()])->assertOk(); + $this->assertTrue(app(PreventionSettings::class)->formmail->hasAll(['new lorem'])); } } diff --git a/tests/RequestFactories/EditorRequestFactory.php b/tests/RequestFactories/EditorRequestFactory.php index 209a4c11..7a9baeb9 100644 --- a/tests/RequestFactories/EditorRequestFactory.php +++ b/tests/RequestFactories/EditorRequestFactory.php @@ -2,6 +2,7 @@ namespace Tests\RequestFactories; +use App\Lib\Editor\EditorData; use Worksome\RequestFactories\RequestFactory; class EditorRequestFactory extends RequestFactory @@ -49,4 +50,28 @@ class EditorRequestFactory extends RequestFactory ], ]; } + + /** + * @param array $paragraphs + */ + public function paragraphs(array $paragraphs): self + { + return $this->state([ + 'time' => 1, + 'version' => '1.0', + 'blocks' => collect($paragraphs)->map(fn ($paragraph) => [ + 'id' => $this->faker->numberBetween([0, 10000]), + 'type' => 'paragraph', + 'data' => ['text' => $paragraph], + 'tunes' => [ + 'condition' => ['mode' => 'all', 'ifs' => []] + ] + ])->toArray(), + ]); + } + + public function toData(): EditorData + { + return EditorData::from($this->create()); + } } diff --git a/tests/Unit/EditorDataTest.php b/tests/Unit/EditorDataTest.php new file mode 100644 index 00000000..0803ac62 --- /dev/null +++ b/tests/Unit/EditorDataTest.php @@ -0,0 +1,19 @@ +paragraphs(['{search}'])->toData(); + + $data->replaceWithList('search', ['A', 'B']); + + $this->assertEquals('A', data_get($data->blocks, '0.data.items.0.content')); + } +}