Skip to content

Commit

Permalink
#323 - threadable emails
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysztofrewak committed Aug 18, 2023
1 parent 912ad27 commit e569a6c
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 191 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
APP_NAME="Toby HR application"
APP_ENV=local
APP_KEY=
APP_KEY=base64:GOwYei8d8m8gubf1JaBxjBlQjeVCG+7n4fZwcgq76V8=
APP_DEBUG=true
APP_URL=https://toby.blumilk.localhost

Expand Down
12 changes: 1 addition & 11 deletions app/Domain/Notifications/VacationRequestCreatedNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,7 @@ protected function buildMailMessage(string $url): MailMessage

protected function buildSubject(): string
{
$name = $this->vacationRequest->name;

if ($this->vacationRequest->creator()->is($this->vacationRequest->user)) {
return __("Request :title created", [
"title" => $name,
]);
}

return __("Request :title has been created on your behalf", [
"title" => $name,
]);
return VacationRequestEmailTitle::get($this->vacationRequest->name);
}

protected function buildDescription(): string
Expand Down
16 changes: 16 additions & 0 deletions app/Domain/Notifications/VacationRequestEmailTitle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

declare(strict_types=1);

namespace Toby\Domain\Notifications;

class VacationRequestEmailTitle
{
public static function get(string $title): string
{
return __("Request :title in :application", [
"title" => $title,
"application" => config("app.name"),
]);
}
}
94 changes: 94 additions & 0 deletions app/Domain/Notifications/VacationRequestNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

declare(strict_types=1);

namespace Toby\Domain\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use InvalidArgumentException;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Infrastructure\Slack\Elements\SlackMessage;

abstract class VacationRequestNotification extends QueuedNotification
{
use Queueable;

public function __construct(
protected VacationRequest $vacationRequest,
protected User $user,
) {
parent::__construct();
}

public function via(): array
{
return [Channels::MAIL, Channels::SLACK];
}

public function toSlack(): SlackMessage
{
$url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]);
$seeDetails = __("See details");

return (new SlackMessage())
->text("{$this->buildDescription()}\n <{$url}|{$seeDetails}>");
}

/**
* @throws InvalidArgumentException
*/
public function toMail(): MailMessage
{
$url = route(
"vacation.requests.show",
[
"vacationRequest" => $this->vacationRequest,
],
);

return $this->buildMailMessage($url);
}

protected function buildMailMessage(string $url): MailMessage
{
$user = $this->user->profile->first_name;
$type = $this->vacationRequest->type->label();
$from = $this->vacationRequest->from;
$to = $this->vacationRequest->to;
$days = $this->vacationRequest->vacations()->count();

$date = $from->equalTo($to)
? "{$from->toDisplayString()}"
: "{$from->toDisplayString()} - {$to->toDisplayString()}";

return (new MailMessage())
->greeting(
__("Hi :user!", [
"user" => $user,
])
)
->subject($this->buildSubject())
->line($this->buildDescription())
->line(
__("Request type: :type", [
"type" => $type,
])
)
->line(
__("Date: :date (number of days: :days)", [
"date" => $date,
"days" => $days,
]),
)
->action(__("Click here for details"), $url);
}

protected function buildSubject(): string
{
return VacationRequestEmailTitle::get($this->vacationRequest->name);
}

abstract protected function buildDescription(): string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,91 +4,8 @@

namespace Toby\Domain\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use InvalidArgumentException;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Infrastructure\Slack\Elements\SlackMessage;

class VacationRequestStatusChangedNotification extends QueuedNotification
class VacationRequestStatusChangedNotification extends VacationRequestNotification
{
use Queueable;

public function __construct(
protected VacationRequest $vacationRequest,
protected User $user,
) {
parent::__construct();
}

public function via(): array
{
return [Channels::MAIL, Channels::SLACK];
}

public function toSlack(): SlackMessage
{
$url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]);
$seeDetails = __("See details");

return (new SlackMessage())
->text("{$this->buildDescription()}\n <{$url}|{$seeDetails}>");
}

/**
* @throws InvalidArgumentException
*/
public function toMail(): MailMessage
{
$url = route(
"vacation.requests.show",
[
"vacationRequest" => $this->vacationRequest,
],
);

return $this->buildMailMessage($url);
}

protected function buildMailMessage(string $url): MailMessage
{
$user = $this->user->profile->first_name;
$type = $this->vacationRequest->type->label();
$from = $this->vacationRequest->from;
$to = $this->vacationRequest->to;
$days = $this->vacationRequest->vacations()->count();

$date = $from->equalTo($to)
? "{$from->toDisplayString()}"
: "{$from->toDisplayString()} - {$to->toDisplayString()}";

return (new MailMessage())
->greeting(__("Hi :user!", [
"user" => $user,
]))
->subject($this->buildSubject())
->line($this->buildDescription())
->line(__("Request type: :type", [
"type" => $type,
]))
->line(
__("Date: :date (number of days: :days)", [
"date" => $date,
"days" => $days,
]),
)
->action(__("Click here for details"), $url);
}

protected function buildSubject(): string
{
return __("Request :title has been :status", [
"title" => $this->vacationRequest->name,
"status" => $this->vacationRequest->state->label(),
]);
}

protected function buildDescription(): string
{
return __("The request :title from user :requester has been :status.", [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,99 +4,10 @@

namespace Toby\Domain\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use InvalidArgumentException;
use Toby\Domain\States\VacationRequest\WaitingForTechnical;
use Toby\Eloquent\Models\User;
use Toby\Eloquent\Models\VacationRequest;
use Toby\Infrastructure\Slack\Elements\SlackMessage;

class VacationRequestWaitsForApprovalNotification extends QueuedNotification
class VacationRequestWaitsForApprovalNotification extends VacationRequestNotification
{
use Queueable;

public function __construct(
protected VacationRequest $vacationRequest,
protected User $user,
) {
parent::__construct();
}

public function via(): array
{
return [Channels::MAIL, Channels::SLACK];
}

public function toSlack(): SlackMessage
{
$url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]);
$seeDetails = __("See details");

return (new SlackMessage())
->text("{$this->buildDescription()}\n <{$url}|{$seeDetails}>");
}

/**
* @throws InvalidArgumentException
*/
public function toMail(): MailMessage
{
$url = route(
"vacation.requests.show",
[
"vacationRequest" => $this->vacationRequest,
],
);

return $this->buildMailMessage($url);
}

protected function buildMailMessage(string $url): MailMessage
{
$user = $this->user->profile->first_name;
$type = $this->vacationRequest->type->label();
$from = $this->vacationRequest->from;
$to = $this->vacationRequest->to;
$days = $this->vacationRequest->vacations()->count();

$date = $from->equalTo($to)
? "{$from->toDisplayString()}"
: "{$from->toDisplayString()} - {$to->toDisplayString()}";

return (new MailMessage())
->greeting(__("Hi :user!", [
"user" => $user,
]))
->subject($this->buildSubject())
->line($this->buildDescription())
->line(__("Request type: :type", [
"type" => $type,
]))
->line(
__("Date: :date (number of days: :days)", [
"date" => $date,
"days" => $days,
]),
)
->action(__("Click here for details"), $url);
}

protected function buildSubject(): string
{
$title = $this->vacationRequest->name;

if ($this->vacationRequest->state->equals(WaitingForTechnical::class)) {
return __("Request :title is waiting for your technical approval", [
"title" => $title,
]);
}

return __("Request :title is waiting for your administrative approval", [
"title" => $title,
]);
}

protected function buildDescription(): string
{
$title = $this->vacationRequest->name;
Expand Down
3 changes: 2 additions & 1 deletion app/Eloquent/Models/Profile.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
/**
* @property string $first_name
* @property string $last_name
* @property-read string $full_name
* @property string $position
* @property EmploymentForm $employment_form
* @property Carbon $employment_date
Expand Down Expand Up @@ -47,7 +48,7 @@ public function getAvatar(): string
->image();
}

public function getfullNameAttribute(): string
public function getFullNameAttribute(): string
{
return "{$this->first_name} {$this->last_name}";
}
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"spatie/laravel-slack-slash-command": "^1.11.4"
},
"require-dev": {
"blumilksoftware/codestyle": "^2.3.0",
"blumilksoftware/codestyle": "^2.4.0",
"laravel/dusk": "^7.7.1",
"mockery/mockery": "^1.5.1",
"nunomaduro/collision": "^7.5.2",
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
declare(strict_types=1);

return [
"name" => env("APP_NAME", "Laravel"),
"name" => env("APP_NAME", "Toby HR application"),
"env" => env("APP_ENV", "production"),
"debug" => (bool)env("APP_DEBUG", false),
"url" => env("APP_URL", "http://localhost"),
Expand Down
3 changes: 2 additions & 1 deletion lang/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"If you're having trouble clicking the \":actionText\" button, copy and paste the URL below\ninto your web browser:": "Jeżeli masz problemy z kliknięciem przycisku \":actionText\", skopiuj i wklej poniższy adres w pasek przeglądarki:",
"All rights reserved.": "Wszelkie prawa zastrzeżone",
"Show request": "Pokaż wniosek",
"Request :title created" : "Wniosek :title został utworzony",
"Request :title created": "Wniosek :title został utworzony",
"The request :title from user :requester created.": "Wniosek :title użytkownika :requester został utworzony pomyślnie.",
"Request type: :type": "Rodzaj wniosku: :type",
"Date: :date (number of days: :days)": "Data: :date (liczba dni: :days)",
Expand All @@ -64,6 +64,7 @@
"The request :title from user :requester is waiting for your technical approval.": "Wniosek :title użytkownika :requester czeka na Twoją akceptację techniczną.",
"The request :title from user :requester is waiting for your administrative approval.": "Wniosek :title użytkownika :requester czeka na Twoją akceptację administracyjną.",
"Request :title has been :status": "Wniosek :title został :status",
"Request :title in :application": "Wniosek :title w aplikacji :application",
"The request :title from user :requester has been :status.": "Wniosek :title użytkownika :requester został :status.",
"Request :title has been created on your behalf": "Wniosek :title został utworzony w Twoim imieniu",
"The request :title has been created by user :creator on your behalf.": "Wniosek :title został utworzony w Twoim imieniu przez użytkownika :creator.",
Expand Down

0 comments on commit e569a6c

Please sign in to comment.