wip
This commit is contained in:
parent
851a52fe32
commit
25816cc47a
@ -9,13 +9,13 @@ use Illuminate\Notifications\ChannelManager;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Toby\Domain\Slack\Channels\SlackApiChannel;
|
||||
use Toby\Domain\Slack\SlackApiChannel;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register()
|
||||
public function register(): void
|
||||
{
|
||||
Notification::resolved(function (ChannelManager $service) {
|
||||
Notification::resolved(function (ChannelManager $service): void {
|
||||
$service->extend("slack", fn(Application $app) => $app->make(SlackApiChannel::class));
|
||||
});
|
||||
}
|
||||
|
45
app/Domain/DailySummaryRetriever.php
Normal file
45
app/Domain/DailySummaryRetriever.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Toby\Domain\Enums\VacationType;
|
||||
use Toby\Eloquent\Models\User;
|
||||
use Toby\Eloquent\Models\Vacation;
|
||||
|
||||
class DailySummaryRetriever
|
||||
{
|
||||
public function __construct(
|
||||
protected VacationTypeConfigRetriever $configRetriever,
|
||||
) {}
|
||||
|
||||
public function getAbsences(Carbon $date): Collection
|
||||
{
|
||||
return Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $date)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $this->configRetriever->isVacation($type)))
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getRemoteDays(Carbon $date): Collection
|
||||
{
|
||||
return Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $date)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$this->configRetriever->isVacation($type)))
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getBirthdays(Carbon $date): Collection
|
||||
{
|
||||
return User::query()
|
||||
->whereRelation("profile", "birthday", $date)
|
||||
->get();
|
||||
}
|
||||
}
|
42
app/Domain/Notifications/KeyHasBeenGivenNotification.php
Normal file
42
app/Domain/Notifications/KeyHasBeenGivenNotification.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Toby\Eloquent\Models\User;
|
||||
|
||||
class KeyHasBeenGivenNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function __construct(
|
||||
protected User $sender,
|
||||
protected User $recipient,
|
||||
) {}
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ["slack"];
|
||||
}
|
||||
|
||||
public function toSlack($notifiable): string
|
||||
{
|
||||
return __(":sender gives key no :key to :recipient", [
|
||||
"sender" => $this->getName($this->sender),
|
||||
"recipient" => $this->getName($this->recipient),
|
||||
"key" => $notifiable->id,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getName(User $user): string
|
||||
{
|
||||
if ($user->profile->slack_id !== null) {
|
||||
return "<@{$user->profile->slack_id}>";
|
||||
}
|
||||
|
||||
return $user->profile->full_name;
|
||||
}
|
||||
}
|
42
app/Domain/Notifications/KeyHasBeenTakenNotification.php
Normal file
42
app/Domain/Notifications/KeyHasBeenTakenNotification.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Notifications;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Notifications\Notification;
|
||||
use Toby\Eloquent\Models\User;
|
||||
|
||||
class KeyHasBeenTakenNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
public function __construct(
|
||||
protected User $recipient,
|
||||
protected User $sender,
|
||||
) {}
|
||||
|
||||
public function via(): array
|
||||
{
|
||||
return ["slack"];
|
||||
}
|
||||
|
||||
public function toSlack($notifiable): string
|
||||
{
|
||||
return __(":recipient takes key no :key from :sender", [
|
||||
"recipient" => $this->getName($this->recipient),
|
||||
"sender" => $this->getName($this->sender),
|
||||
"key" => $notifiable->id,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getName(User $user): string
|
||||
{
|
||||
if ($user->profile->slack_id !== null) {
|
||||
return "<@{$user->profile->slack_id}>";
|
||||
}
|
||||
|
||||
return $user->profile->full_name;
|
||||
}
|
||||
}
|
55
app/Domain/Slack/Controller.php
Normal file
55
app/Domain/Slack/Controller.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request as IlluminateRequest;
|
||||
use Illuminate\Http\Response as IlluminateResponse;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\SlashCommand\Attachment;
|
||||
use Spatie\SlashCommand\Controller as SlackController;
|
||||
use Spatie\SlashCommand\Exceptions\RequestCouldNotBeHandled;
|
||||
use Spatie\SlashCommand\Exceptions\SlackSlashCommandException;
|
||||
use Spatie\SlashCommand\Response;
|
||||
|
||||
class Controller extends SlackController
|
||||
{
|
||||
/**
|
||||
* @throws RequestCouldNotBeHandled
|
||||
*/
|
||||
public function getResponse(IlluminateRequest $request): IlluminateResponse
|
||||
{
|
||||
$this->guardAgainstInvalidRequest($request);
|
||||
|
||||
$handler = $this->determineHandler();
|
||||
|
||||
try {
|
||||
$response = $handler->handle($this->request);
|
||||
} catch (SlackSlashCommandException $exception) {
|
||||
$response = $exception->getResponse($this->request);
|
||||
} catch (ValidationException $exception) {
|
||||
$response = $this->prepareValidationResponse($exception);
|
||||
} catch (Exception $exception) {
|
||||
$response = $this->convertToResponse($exception);
|
||||
}
|
||||
|
||||
return $response->getIlluminateResponse();
|
||||
}
|
||||
|
||||
protected function prepareValidationResponse(ValidationException $exception): Response
|
||||
{
|
||||
$errors = (new Collection($exception->errors()))
|
||||
->map(
|
||||
fn(array $message) => Attachment::create()
|
||||
->setColor("danger")
|
||||
->setText($message[0]),
|
||||
);
|
||||
|
||||
return Response::create($this->request)
|
||||
->withText(":x: Komenda `/{$this->request->command} {$this->request->text}` jest niepoprawna:")
|
||||
->withAttachments($errors->all());
|
||||
}
|
||||
}
|
@ -4,48 +4,32 @@ declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Handlers;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\SlashCommand\Attachment;
|
||||
use Spatie\SlashCommand\AttachmentField;
|
||||
use Spatie\SlashCommand\Handlers\CatchAll as BaseCatchAllHandler;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Spatie\SlashCommand\Handlers\BaseHandler;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Toby\Domain\Slack\Traits\ListsHandlers;
|
||||
|
||||
class CatchAll extends BaseCatchAllHandler
|
||||
class CatchAll extends BaseHandler
|
||||
{
|
||||
use ListsHandlers;
|
||||
|
||||
public function canHandle(Request $request): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$response = $this->respondToSlack("Nie rozpoznaję tej komendy: `/{$request->command} {$request->text}`");
|
||||
$handlers = $this->findAvailableHandlers();
|
||||
$attachmentFields = $this->mapHandlersToAttachments($handlers);
|
||||
|
||||
[$command] = explode(' ', $this->request->text ?? "");
|
||||
|
||||
$alternativeHandlers = $this->findAlternativeHandlers($command);
|
||||
|
||||
if ($alternativeHandlers->count()) {
|
||||
$response->withAttachment($this->getCommandListAttachment($alternativeHandlers));
|
||||
}
|
||||
|
||||
if ($this->containsHelpHandler($alternativeHandlers)) {
|
||||
$response->withAttachment(Attachment::create()
|
||||
->setText("Aby wyświetlić wszystkie komendy, napisz: `/toby pomoc`")
|
||||
return $this->respondToSlack(":x: Nie rozpoznaję tej komendy. Lista wszystkich komend:")
|
||||
->withAttachment(
|
||||
Attachment::create()
|
||||
->setColor("danger")
|
||||
->useMarkdown()
|
||||
->setFields($attachmentFields),
|
||||
);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
protected function getCommandListAttachment(Collection $handlers): Attachment
|
||||
{
|
||||
$attachmentFields = $handlers
|
||||
->map(function (SignatureHandler $handler) {
|
||||
return AttachmentField::create($handler->getFullCommand(), $handler->getDescription());
|
||||
})
|
||||
->all();
|
||||
|
||||
return Attachment::create()
|
||||
->setColor('warning')
|
||||
->setTitle('Czy miałeś na myśli:')
|
||||
->setFields($attachmentFields);
|
||||
}
|
||||
}
|
@ -5,70 +5,52 @@ declare(strict_types=1);
|
||||
namespace Toby\Domain\Slack\Handlers;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\SlashCommand\Attachment;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Toby\Domain\Enums\VacationType;
|
||||
use Toby\Domain\VacationTypeConfigRetriever;
|
||||
use Toby\Domain\DailySummaryRetriever;
|
||||
use Toby\Domain\Slack\SignatureHandler;
|
||||
use Toby\Eloquent\Models\User;
|
||||
use Toby\Eloquent\Models\Vacation;
|
||||
|
||||
class DailySummary extends SignatureHandler
|
||||
{
|
||||
protected $signature = "toby dzisiaj";
|
||||
|
||||
protected $description = "Podsumowanie";
|
||||
protected $description = "Codzienne podsumowanie";
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$configRetriever = app(VacationTypeConfigRetriever::class);
|
||||
$dailySummaryRetriever = app()->make(DailySummaryRetriever::class);
|
||||
|
||||
$now = Carbon::today();
|
||||
|
||||
/** @var Collection $absences */
|
||||
$absences = Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $now)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type)))
|
||||
->get()
|
||||
$absences = $dailySummaryRetriever->getAbsences($now)
|
||||
->map(fn(Vacation $vacation) => $vacation->user->profile->full_name);
|
||||
|
||||
/** @var Collection $remoteDays */
|
||||
$remoteDays = Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $now)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type)))
|
||||
->get()
|
||||
$remoteDays = $dailySummaryRetriever->getRemoteDays($now)
|
||||
->map(fn(Vacation $vacation) => $vacation->user->profile->full_name);
|
||||
|
||||
$birthdays = User::query()
|
||||
->whereRelation("profile", "birthday", $now)
|
||||
->get()
|
||||
$birthdays = $dailySummaryRetriever->getBirthdays($now)
|
||||
->map(fn(User $user) => $user->profile->full_name);
|
||||
|
||||
$absencesAttachment = Attachment::create()
|
||||
->setTitle("Nieobecności :palm_tree:")
|
||||
->setColor('#eab308')
|
||||
->setColor("#eab308")
|
||||
->setText($absences->isNotEmpty() ? $absences->implode("\n") : "Wszyscy dzisiaj pracują :muscle:");
|
||||
|
||||
$remoteAttachment = Attachment::create()
|
||||
->setTitle("Praca zdalna :house_with_garden:")
|
||||
->setColor('#d946ef')
|
||||
->setColor("#d946ef")
|
||||
->setText($remoteDays->isNotEmpty() ? $remoteDays->implode("\n") : "Wszyscy dzisiaj są w biurze :boom:");
|
||||
|
||||
$birthdayAttachment = Attachment::create()
|
||||
->setTitle("Urodziny :birthday:")
|
||||
->setColor('#3C5F97')
|
||||
->setColor("#3C5F97")
|
||||
->setText($birthdays->isNotEmpty() ? $birthdays->implode("\n") : "Dzisiaj nikt nie ma urodzin :cry:");
|
||||
|
||||
return $this->respondToSlack("Podsumowanie dla dnia {$now->toDisplayString()}")
|
||||
->withAttachment($absencesAttachment)
|
||||
->withAttachment($remoteAttachment)
|
||||
->withAttachment($birthdayAttachment)
|
||||
->displayResponseToEveryoneOnChannel();
|
||||
->withAttachment($birthdayAttachment);
|
||||
}
|
||||
}
|
@ -4,46 +4,69 @@ declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Handlers;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Toby\Domain\Notifications\KeyHasBeenGivenNotification;
|
||||
use Toby\Domain\Slack\SignatureHandler;
|
||||
use Toby\Domain\Slack\SlackUserExistsRule;
|
||||
use Toby\Domain\Slack\Traits\FindsUserBySlackId;
|
||||
use Toby\Domain\Slack\UserNotFoundException;
|
||||
use Toby\Eloquent\Models\Key;
|
||||
use Toby\Eloquent\Models\User;
|
||||
|
||||
class GiveKeysTo extends SignatureHandler
|
||||
{
|
||||
protected $signature = "toby klucze:dla {użytkownik}";
|
||||
use FindsUserBySlackId;
|
||||
|
||||
protected $description = "Daj klucze wskazanemu użytkownikowi";
|
||||
protected $signature = "toby klucze:dla {user}";
|
||||
protected $description = "Przekaż klucze wskazanemu użytkownikowi";
|
||||
|
||||
/**
|
||||
* @throws UserNotFoundException
|
||||
* @throws ValidationException
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$to = $this->getArgument('użytkownik');
|
||||
["user" => $from] = $this->validate();
|
||||
|
||||
$id = Str::between($to, "@", "|");
|
||||
|
||||
$authUser = $this->findUserBySlackId($request->userId);
|
||||
$user = $this->findUserBySlackId($id);
|
||||
$authUser = $this->findUserBySlackIdOrFail($request->userId);
|
||||
$user = $this->findUserBySlackId($from);
|
||||
|
||||
/** @var Key $key */
|
||||
$key = $authUser->keys()->first();
|
||||
|
||||
if (!$key) {
|
||||
throw ValidationException::withMessages(["key" => "Nie masz żadnego klucza do przekazania"]);
|
||||
}
|
||||
|
||||
if ($user->is($authUser)) {
|
||||
throw ValidationException::withMessages([
|
||||
"key" => "Nie możesz przekazać sobie kluczy :dzban:",
|
||||
]);
|
||||
}
|
||||
|
||||
$key->user()->associate($user);
|
||||
|
||||
$key->save();
|
||||
|
||||
return $this->respondToSlack("<@{$authUser->profile->slack_id}> daje klucz nr {$key->id} użytkownikowi <@{$user->profile->slack_id}>")
|
||||
->displayResponseToEveryoneOnChannel();
|
||||
$key->notify(new KeyHasBeenGivenNotification($authUser, $user));
|
||||
|
||||
return $this->respondToSlack(
|
||||
":white_check_mark: Klucz nr {$key->id} został przekazany użytkownikowi <@{$user->profile->slack_id}>",
|
||||
);
|
||||
}
|
||||
|
||||
protected function findUserBySlackId(string $slackId): User
|
||||
protected function getRules(): array
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = User::query()
|
||||
->whereRelation("profile", "slack_id", $slackId)
|
||||
->first();
|
||||
return [
|
||||
"user" => ["required", new SlackUserExistsRule()],
|
||||
];
|
||||
}
|
||||
|
||||
return $user;
|
||||
protected function getMessages(): array
|
||||
{
|
||||
return [
|
||||
"user.required" => "Musisz podać użytkownika, któremu chcesz przekazać klucze",
|
||||
];
|
||||
}
|
||||
}
|
@ -4,42 +4,31 @@ declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Handlers;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\SlashCommand\Attachment;
|
||||
use Spatie\SlashCommand\AttachmentField;
|
||||
use Spatie\SlashCommand\Handlers\Help as BaseHelpHandler;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Toby\Domain\Slack\SignatureHandler;
|
||||
use Toby\Domain\Slack\Traits\ListsHandlers;
|
||||
|
||||
class Help extends BaseHelpHandler
|
||||
class Help extends SignatureHandler
|
||||
{
|
||||
use ListsHandlers;
|
||||
|
||||
protected $signature = "toby pomoc";
|
||||
protected $description = "Wyświetl wszystkie dostępne komendy tobiego";
|
||||
protected $description = "Wyświetl wszystkie dostępne komendy";
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$handlers = $this->findAvailableHandlers();
|
||||
|
||||
return $this->displayListOfAllCommands($handlers);
|
||||
}
|
||||
$attachmentFields = $this->mapHandlersToAttachments($handlers);
|
||||
|
||||
protected function displayListOfAllCommands(Collection $handlers): Response
|
||||
{
|
||||
$attachmentFields = $handlers
|
||||
->sort(function (SignatureHandler $handlerA, SignatureHandler $handlerB) {
|
||||
return strcmp($handlerA->getFullCommand(), $handlerB->getFullCommand());
|
||||
})
|
||||
->map(function (SignatureHandler $handler) {
|
||||
return AttachmentField::create("/{$handler->getSignature()}", $handler->getDescription());
|
||||
})
|
||||
->all();
|
||||
|
||||
return $this->respondToSlack('Dostępne komendy')
|
||||
return $this->respondToSlack("Dostępne komendy:")
|
||||
->withAttachment(
|
||||
Attachment::create()
|
||||
->setColor('good')
|
||||
->setFields($attachmentFields)
|
||||
->setColor("good")
|
||||
->useMarkdown()
|
||||
->setFields($attachmentFields),
|
||||
);
|
||||
}
|
||||
}
|
@ -7,22 +7,31 @@ namespace Toby\Domain\Slack\Handlers;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Toby\Domain\Actions\VacationRequest\CreateAction;
|
||||
use Toby\Domain\Enums\VacationType;
|
||||
use Toby\Domain\Slack\SignatureHandler;
|
||||
use Toby\Domain\Slack\Traits\FindsUserBySlackId;
|
||||
use Toby\Eloquent\Models\User;
|
||||
use Toby\Eloquent\Models\YearPeriod;
|
||||
|
||||
class HomeOffice extends SignatureHandler
|
||||
{
|
||||
protected $signature = "toby zdalnie {kiedy?}";
|
||||
protected $description = "Pracuj zdalnie wybranego dnia (domyślnie dzisiaj)";
|
||||
use FindsUserBySlackId;
|
||||
|
||||
protected $signature = "toby zdalnie";
|
||||
protected $description = "Pracuj dzisiaj zdalnie";
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$date = $this->getDateFromArgument($this->getArgument('kiedy') ?? "dzisiaj");
|
||||
$user = $this->findUserBySlackId($request->userId);
|
||||
|
||||
$this->createRemoteday($user, Carbon::today());
|
||||
|
||||
return $this->respondToSlack(":white_check_mark: Pracujesz dzisiaj zdalnie");
|
||||
}
|
||||
|
||||
protected function createRemoteday(User $user, Carbon $date): void
|
||||
{
|
||||
$yearPeriod = YearPeriod::findByYear($date->year);
|
||||
|
||||
app(CreateAction::class)->execute([
|
||||
@ -33,27 +42,5 @@ class HomeOffice extends SignatureHandler
|
||||
"year_period_id" => $yearPeriod->id,
|
||||
"flow_skipped" => false,
|
||||
], $user);
|
||||
|
||||
return $this->respondToSlack("Praca zdalna dnia {$date->toDisplayString()} została utworzona pomyślnie.")
|
||||
->displayResponseToEveryoneOnChannel();
|
||||
}
|
||||
|
||||
protected function getDateFromArgument(string $argument): Carbon
|
||||
{
|
||||
return match ($argument) {
|
||||
"dzisiaj" => Carbon::today(),
|
||||
"jutro" => Carbon::tomorrow(),
|
||||
default => Carbon::create($argument),
|
||||
};
|
||||
}
|
||||
|
||||
protected function findUserBySlackId(string $slackId): User
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = User::query()
|
||||
->whereRelation("profile", "slack_id", $slackId)
|
||||
->first();
|
||||
|
||||
return $user;
|
||||
}
|
||||
}
|
@ -7,13 +7,12 @@ namespace Toby\Domain\Slack\Handlers;
|
||||
use Spatie\SlashCommand\Attachment;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Toby\Domain\Slack\SignatureHandler;
|
||||
use Toby\Eloquent\Models\Key;
|
||||
|
||||
class KeyList extends SignatureHandler
|
||||
{
|
||||
protected $signature = "toby klucze";
|
||||
|
||||
protected $description = "Lista wszystkich kluczy";
|
||||
|
||||
public function handle(Request $request): Response
|
||||
@ -23,11 +22,11 @@ class KeyList extends SignatureHandler
|
||||
->get()
|
||||
->map(fn(Key $key) => "Klucz nr {$key->id} - <@{$key->user->profile->slack_id}>");
|
||||
|
||||
return $this->respondToSlack("Lista kluczy")
|
||||
return $this->respondToSlack("Lista kluczy :key:")
|
||||
->withAttachment(
|
||||
Attachment::create()
|
||||
->setColor('#3C5F97')
|
||||
->setText($keys->implode("\n"))
|
||||
->setColor("#3C5F97")
|
||||
->setText($keys->isNotEmpty() ? $keys->implode("\n") : "Nie ma żadnych kluczy w tobym"),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Handlers;
|
||||
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
|
||||
class SaySomething extends SignatureHandler
|
||||
{
|
||||
protected $signature = "toby powiedz {zdanie}";
|
||||
|
||||
protected $description = "Powiedz zdanie";
|
||||
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$sentence = $this->getArgument("zdanie");
|
||||
|
||||
return $this->respondToSlack($sentence)
|
||||
->displayResponseToEveryoneOnChannel();
|
||||
}
|
||||
}
|
@ -4,46 +4,68 @@ declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Handlers;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\SlashCommand\Request;
|
||||
use Spatie\SlashCommand\Response;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Toby\Domain\Notifications\KeyHasBeenTakenNotification;
|
||||
use Toby\Domain\Slack\SignatureHandler;
|
||||
use Toby\Domain\Slack\SlackUserExistsRule;
|
||||
use Toby\Domain\Slack\Traits\FindsUserBySlackId;
|
||||
use Toby\Domain\Slack\UserNotFoundException;
|
||||
use Toby\Eloquent\Models\Key;
|
||||
use Toby\Eloquent\Models\User;
|
||||
|
||||
class TakeKeysFrom extends SignatureHandler
|
||||
{
|
||||
protected $signature = "toby klucze:od {użytkownik}";
|
||||
use FindsUserBySlackId;
|
||||
|
||||
protected $signature = "toby klucze:od {user}";
|
||||
protected $description = "Zabierz klucze wskazanemu użytkownikowi";
|
||||
|
||||
/**
|
||||
* @throws UserNotFoundException|ValidationException
|
||||
*/
|
||||
public function handle(Request $request): Response
|
||||
{
|
||||
$from = $this->getArgument("użytkownik");
|
||||
["user" => $from] = $this->validate();
|
||||
|
||||
$id = Str::between($from, "@", "|");
|
||||
|
||||
$authUser = $this->findUserBySlackId($request->userId);
|
||||
$user = $this->findUserBySlackId($id);
|
||||
$authUser = $this->findUserBySlackIdOrFail($request->userId);
|
||||
$user = $this->findUserBySlackId($from);
|
||||
|
||||
/** @var Key $key */
|
||||
$key = $user->keys()->first();
|
||||
|
||||
if (!$key) {
|
||||
throw ValidationException::withMessages([
|
||||
"key" => "Użytkownik <@{$user->profile->slack_id}> nie ma żadnych kluczy",
|
||||
]);
|
||||
}
|
||||
|
||||
if ($key->user()->is($authUser)) {
|
||||
throw ValidationException::withMessages([
|
||||
"key" => "Nie możesz zabrać sobie kluczy :dzban:",
|
||||
]);
|
||||
}
|
||||
|
||||
$key->user()->associate($authUser);
|
||||
|
||||
$key->save();
|
||||
|
||||
return $this->respondToSlack("<@{$authUser->profile->slack_id}> zabiera klucz nr {$key->id} użytkownikowi <@{$user->profile->slack_id}>")
|
||||
->displayResponseToEveryoneOnChannel();
|
||||
$key->notify(new KeyHasBeenTakenNotification($authUser, $user));
|
||||
|
||||
return $this->respondToSlack(":white_check_mark: Klucz nr {$key->id} został zabrany użytkownikowi <@{$user->profile->slack_id}>");
|
||||
}
|
||||
|
||||
protected function findUserBySlackId(string $slackId): User
|
||||
protected function getRules(): array
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = User::query()
|
||||
->whereRelation("profile", "slack_id", $slackId)
|
||||
->first();
|
||||
return [
|
||||
"user" => ["required", new SlackUserExistsRule()],
|
||||
];
|
||||
}
|
||||
|
||||
return $user;
|
||||
protected function getMessages(): array
|
||||
{
|
||||
return [
|
||||
"user.required" => "Musisz podać użytkownika, któremu chcesz zabrać klucze",
|
||||
];
|
||||
}
|
||||
}
|
26
app/Domain/Slack/SignatureHandler.php
Normal file
26
app/Domain/Slack/SignatureHandler.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack;
|
||||
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler as BaseSignatureHandler;
|
||||
|
||||
abstract class SignatureHandler extends BaseSignatureHandler
|
||||
{
|
||||
public function validate()
|
||||
{
|
||||
return Validator::validate($this->getArguments(), $this->getRules(), $this->getMessages());
|
||||
}
|
||||
|
||||
protected function getRules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function getMessages(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Channels;
|
||||
namespace Toby\Domain\Slack;
|
||||
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Notifications\Notification;
|
||||
@ -14,12 +14,12 @@ class SlackApiChannel
|
||||
{
|
||||
$baseUrl = config("services.slack.url");
|
||||
$url = "{$baseUrl}/chat.postMessage";
|
||||
$channel = $notifiable->routeNotificationFor('slack', $notification);
|
||||
$channel = $notifiable->routeNotificationFor("slack", $notification);
|
||||
|
||||
return Http::withToken(config("services.slack.client_token"))
|
||||
->post($url, [
|
||||
"channel" => $channel,
|
||||
"text" => $notification->toSlack(),
|
||||
"text" => $notification->toSlack($notifiable),
|
||||
]);
|
||||
}
|
||||
}
|
24
app/Domain/Slack/SlackUserExistsRule.php
Normal file
24
app/Domain/Slack/SlackUserExistsRule.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use Illuminate\Support\Str;
|
||||
use Toby\Eloquent\Models\Profile;
|
||||
|
||||
class SlackUserExistsRule implements Rule
|
||||
{
|
||||
public function passes($attribute, $value): bool
|
||||
{
|
||||
$slackId = Str::between($value, "<@", "|");
|
||||
|
||||
return Profile::query()->where("slack_id", $slackId)->exists();
|
||||
}
|
||||
|
||||
public function message(): string
|
||||
{
|
||||
return "Użytkownik :input nie istnieje w tobym";
|
||||
}
|
||||
}
|
43
app/Domain/Slack/Traits/FindsUserBySlackId.php
Normal file
43
app/Domain/Slack/Traits/FindsUserBySlackId.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Traits;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Toby\Domain\Slack\UserNotFoundException;
|
||||
use Toby\Eloquent\Models\User;
|
||||
|
||||
trait FindsUserBySlackId
|
||||
{
|
||||
protected function findUserBySlackId(string $slackId): ?User
|
||||
{
|
||||
$id = $this->prepareSlackIdFromString($slackId);
|
||||
|
||||
/** @var User $user */
|
||||
$user = User::query()
|
||||
->whereRelation("profile", "slack_id", $id)
|
||||
->first();
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws UserNotFoundException
|
||||
*/
|
||||
protected function findUserBySlackIdOrFail(string $slackId): ?User
|
||||
{
|
||||
$user = $this->findUserBySlackId($slackId);
|
||||
|
||||
if (!$user) {
|
||||
throw new UserNotFoundException("Użytkownik {$slackId} nie istnieje w tobym");
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
protected function prepareSlackIdFromString(string $slackId): string
|
||||
{
|
||||
return Str::between($slackId, "<@", "|");
|
||||
}
|
||||
}
|
45
app/Domain/Slack/Traits/ListsHandlers.php
Normal file
45
app/Domain/Slack/Traits/ListsHandlers.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack\Traits;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\SlashCommand\AttachmentField;
|
||||
use Spatie\SlashCommand\Handlers\SignatureHandler;
|
||||
use Spatie\SlashCommand\Handlers\SignatureParts;
|
||||
use Spatie\SlashCommand\HandlesSlashCommand;
|
||||
|
||||
trait ListsHandlers
|
||||
{
|
||||
protected function findAvailableHandlers(): Collection
|
||||
{
|
||||
return collect(config("laravel-slack-slash-command.handlers"))
|
||||
->map(fn(string $handlerClassName) => new $handlerClassName($this->request))
|
||||
->filter(fn(HandlesSlashCommand $handler) => $handler instanceof SignatureHandler)
|
||||
->filter(function (SignatureHandler $handler) {
|
||||
$signatureParts = new SignatureParts($handler->getSignature());
|
||||
|
||||
return Str::is($signatureParts->getSlashCommandName(), $this->request->command);
|
||||
});
|
||||
}
|
||||
|
||||
protected function mapHandlersToAttachments(Collection $handlers): array
|
||||
{
|
||||
return $handlers
|
||||
->sort(
|
||||
fn(SignatureHandler $handlerA, SignatureHandler $handlerB) => strcmp(
|
||||
$handlerA->getFullCommand(),
|
||||
$handlerB->getFullCommand(),
|
||||
),
|
||||
)
|
||||
->map(
|
||||
fn(SignatureHandler $handler) => AttachmentField::create(
|
||||
$handler->getDescription(),
|
||||
"`/{$handler->getSignature()}`",
|
||||
),
|
||||
)
|
||||
->all();
|
||||
}
|
||||
}
|
11
app/Domain/Slack/UserNotFoundException.php
Normal file
11
app/Domain/Slack/UserNotFoundException.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Toby\Domain\Slack;
|
||||
|
||||
use Spatie\SlashCommand\Exceptions\SlackSlashCommandException;
|
||||
|
||||
class UserNotFoundException extends SlackSlashCommandException
|
||||
{
|
||||
}
|
@ -8,6 +8,7 @@ use Database\Factories\KeyFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
/**
|
||||
* @property int $id
|
||||
@ -16,6 +17,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
class Key extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Notifiable;
|
||||
|
||||
protected $guarded = [];
|
||||
|
||||
@ -24,6 +26,11 @@ class Key extends Model
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function routeNotificationForSlack(): string
|
||||
{
|
||||
return config("services.slack.default_channel");
|
||||
}
|
||||
|
||||
protected static function newFactory(): KeyFactory
|
||||
{
|
||||
return KeyFactory::new();
|
||||
|
@ -7,11 +7,9 @@ namespace Toby\Infrastructure\Console\Commands;
|
||||
use Carbon\CarbonInterface;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Spatie\SlashCommand\Attachment;
|
||||
use Toby\Domain\Enums\VacationType;
|
||||
use Toby\Domain\VacationTypeConfigRetriever;
|
||||
use Toby\Domain\DailySummaryRetriever;
|
||||
use Toby\Eloquent\Models\Holiday;
|
||||
use Toby\Eloquent\Models\User;
|
||||
use Toby\Eloquent\Models\Vacation;
|
||||
@ -21,7 +19,7 @@ class SendDailySummaryToSlack extends Command
|
||||
protected $signature = "toby:slack:daily-summary {--f|force}";
|
||||
protected $description = "Sent daily summary to slack";
|
||||
|
||||
public function handle(VacationTypeConfigRetriever $configRetriever): void
|
||||
public function handle(DailySummaryRetriever $dailySummaryRetriever): void
|
||||
{
|
||||
$now = Carbon::today();
|
||||
|
||||
@ -29,42 +27,28 @@ class SendDailySummaryToSlack extends Command
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Collection $absences */
|
||||
$absences = Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $now)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type)))
|
||||
->get()
|
||||
$absences = $dailySummaryRetriever->getAbsences($now)
|
||||
->map(fn(Vacation $vacation) => $vacation->user->profile->full_name);
|
||||
|
||||
/** @var Collection $remoteDays */
|
||||
$remoteDays = Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $now)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type)))
|
||||
->get()
|
||||
$remoteDays = $dailySummaryRetriever->getRemoteDays($now)
|
||||
->map(fn(Vacation $vacation) => $vacation->user->profile->full_name);
|
||||
|
||||
$birthdays = User::query()
|
||||
->whereRelation("profile", "birthday", $now)
|
||||
->get()
|
||||
$birthdays = $dailySummaryRetriever->getBirthdays($now)
|
||||
->map(fn(User $user) => $user->profile->full_name);
|
||||
|
||||
$absencesAttachment = Attachment::create()
|
||||
->setTitle("Nieobecności :palm_tree:")
|
||||
->setColor('#eab308')
|
||||
->setColor("#eab308")
|
||||
->setText($absences->isNotEmpty() ? $absences->implode("\n") : "Wszyscy dzisiaj pracują :muscle:");
|
||||
|
||||
$remoteAttachment = Attachment::create()
|
||||
->setTitle("Praca zdalna :house_with_garden:")
|
||||
->setColor('#d946ef')
|
||||
->setColor("#d946ef")
|
||||
->setText($remoteDays->isNotEmpty() ? $remoteDays->implode("\n") : "Wszyscy dzisiaj są w biurze :boom:");
|
||||
|
||||
$birthdayAttachment = Attachment::create()
|
||||
->setTitle("Urodziny :birthday:")
|
||||
->setColor('#3C5F97')
|
||||
->setColor("#3C5F97")
|
||||
->setText($birthdays->isNotEmpty() ? $birthdays->implode("\n") : "Dzisiaj nikt nie ma urodzin :cry:");
|
||||
|
||||
$baseUrl = config("services.slack.url");
|
||||
@ -74,8 +58,8 @@ class SendDailySummaryToSlack extends Command
|
||||
->post($url, [
|
||||
"channel" => config("services.slack.default_channel"),
|
||||
"text" => "Podsumowanie dla dnia {$now->toDisplayString()}",
|
||||
'attachments' => collect([$absencesAttachment, $remoteAttachment, $birthdayAttachment])->map(
|
||||
fn(Attachment $attachment) => $attachment->toArray()
|
||||
"attachments" => collect([$absencesAttachment, $remoteAttachment, $birthdayAttachment])->map(
|
||||
fn(Attachment $attachment) => $attachment->toArray(),
|
||||
)->toArray(),
|
||||
]);
|
||||
}
|
||||
|
@ -7,12 +7,11 @@ namespace Toby\Infrastructure\Http\Controllers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Inertia\Response;
|
||||
use Toby\Domain\Enums\VacationType;
|
||||
use Toby\Domain\DailySummaryRetriever;
|
||||
use Toby\Domain\UserVacationStatsRetriever;
|
||||
use Toby\Domain\VacationRequestStatesRetriever;
|
||||
use Toby\Domain\VacationTypeConfigRetriever;
|
||||
use Toby\Eloquent\Helpers\YearPeriodRetriever;
|
||||
use Toby\Eloquent\Models\Vacation;
|
||||
use Toby\Eloquent\Models\VacationRequest;
|
||||
use Toby\Infrastructure\Http\Resources\HolidayResource;
|
||||
use Toby\Infrastructure\Http\Resources\VacationRequestResource;
|
||||
@ -25,24 +24,14 @@ class DashboardController extends Controller
|
||||
YearPeriodRetriever $yearPeriodRetriever,
|
||||
UserVacationStatsRetriever $vacationStatsRetriever,
|
||||
VacationTypeConfigRetriever $configRetriever,
|
||||
DailySummaryRetriever $dailySummaryRetriever,
|
||||
): Response {
|
||||
$user = $request->user();
|
||||
$now = Carbon::now();
|
||||
$yearPeriod = $yearPeriodRetriever->selected();
|
||||
|
||||
$absences = Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $now)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type)))
|
||||
->get();
|
||||
|
||||
$remoteDays = Vacation::query()
|
||||
->with(["user", "vacationRequest"])
|
||||
->whereDate("date", $now)
|
||||
->approved()
|
||||
->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type)))
|
||||
->get();
|
||||
$absences = $dailySummaryRetriever->getAbsences($now);
|
||||
$remoteDays = $dailySummaryRetriever->getRemoteDays($now);
|
||||
|
||||
if ($user->can("listAll", VacationRequest::class)) {
|
||||
$vacationRequests = $yearPeriod->vacationRequests()
|
||||
|
@ -8,6 +8,8 @@ use Illuminate\Auth\Access\AuthorizationException;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Response;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Toby\Domain\Notifications\KeyHasBeenGivenNotification;
|
||||
use Toby\Domain\Notifications\KeyHasBeenTakenNotification;
|
||||
use Toby\Eloquent\Models\Key;
|
||||
use Toby\Eloquent\Models\User;
|
||||
use Toby\Infrastructure\Http\Requests\GiveKeyRequest;
|
||||
@ -60,6 +62,8 @@ class KeysController extends Controller
|
||||
|
||||
$key->save();
|
||||
|
||||
$key->notify(new KeyHasBeenTakenNotification($request->user(), $previousUser));
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with("success", __("Key no :number has been taken from :user.", [
|
||||
@ -81,6 +85,8 @@ class KeysController extends Controller
|
||||
|
||||
$key->save();
|
||||
|
||||
$key->notify(new KeyHasBeenGivenNotification($request->user(), $recipient));
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with("success", __("Key no :number has been given to :user.", [
|
||||
|
@ -62,7 +62,8 @@
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"dont-discover": [
|
||||
"laravel/telescope"
|
||||
"laravel/telescope",
|
||||
"spatie/laravel-slack-slash-command"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -8,21 +8,18 @@ use Toby\Domain\Slack\Handlers\GiveKeysTo;
|
||||
use Toby\Domain\Slack\Handlers\Help;
|
||||
use Toby\Domain\Slack\Handlers\HomeOffice;
|
||||
use Toby\Domain\Slack\Handlers\KeyList;
|
||||
use Toby\Domain\Slack\Handlers\SaySomething;
|
||||
use Toby\Domain\Slack\Handlers\TakeKeysFrom;
|
||||
|
||||
return [
|
||||
'url' => 'api/slack',
|
||||
'signing_secret' => env('SLACK_SIGNING_SECRET'),
|
||||
'verify_with_signing' => true,
|
||||
'handlers' => [
|
||||
"signing_secret" => env("SLACK_SIGNING_SECRET"),
|
||||
"verify_with_signing" => true,
|
||||
"handlers" => [
|
||||
TakeKeysFrom::class,
|
||||
GiveKeysTo::class,
|
||||
KeyList::class,
|
||||
HomeOffice::class,
|
||||
DailySummary::class,
|
||||
SaySomething::class,
|
||||
Help::class,
|
||||
CatchAll::class
|
||||
CatchAll::class,
|
||||
],
|
||||
];
|
||||
|
@ -23,11 +23,11 @@
|
||||
"cancelled": "anulowany",
|
||||
"rejected": "odrzucony",
|
||||
"approved": "zatwierdzony",
|
||||
"You have pending vacation request in this range.": "Masz oczekujący wniosek urlopowy w tym zakresie dat.",
|
||||
"You have approved vacation request in this range.": "Masz zaakceptowany wniosek urlopowy w tym zakresie dat.",
|
||||
"You have pending vacation request in this range.": "Masz oczekujący wniosek w tym zakresie dat.",
|
||||
"You have approved vacation request in this range.": "Masz zaakceptowany wniosek w tym zakresie dat.",
|
||||
"Vacation limit has been exceeded.": "Limit urlopu został przekroczony.",
|
||||
"Vacation needs minimum one day.": "Urlop musi być co najmniej na jeden dzień.",
|
||||
"The vacation request cannot be created at the turn of the year.": "Wniosek urlopowy nie może zostać złożony na przełomie roku.",
|
||||
"The vacation request cannot be created at the turn of the year.": "Wniosek nie może zostać złożony na przełomie roku.",
|
||||
"User has been created.": "Użytkownik został utworzony.",
|
||||
"User has been updated.": "Użytkownik został zaktualizowany.",
|
||||
"User has been deleted.": "Użytkownik został usunięty.",
|
||||
@ -37,11 +37,11 @@
|
||||
"Holiday has been deleted.": "Dzień wolny został usunięty.",
|
||||
"Selected year period has been changed.": "Wybrany rok został zmieniony.",
|
||||
"Vacation limits have been updated.": "Limity urlopów zostały zaktualizowane.",
|
||||
"Vacation request has been created.": "Wniosek urlopowy został utworzony.",
|
||||
"Vacation request has been accepted.": "Wniosek urlopowy został zaakceptowany.",
|
||||
"Vacation request has been approved.": "Wniosek urlopowy został zatwierdzony.",
|
||||
"Vacation request has been rejected.": "Wniosek urlopowy został odrzucony.",
|
||||
"Vacation request has been cancelled.": "Wniosek urlopowy został anulowany.",
|
||||
"Vacation request has been created.": "Wniosek został utworzony.",
|
||||
"Vacation request has been accepted.": "Wniosek został zaakceptowany.",
|
||||
"Vacation request has been approved.": "Wniosek został zatwierdzony.",
|
||||
"Vacation request has been rejected.": "Wniosek został odrzucony.",
|
||||
"Vacation request has been cancelled.": "Wniosek został anulowany.",
|
||||
"Sum:": "Suma:",
|
||||
"Date": "Data",
|
||||
"Day of week": "Dzień tygodnia",
|
||||
@ -71,5 +71,7 @@
|
||||
"Key no :number has been created.": "Klucz nr :number został utworzony.",
|
||||
"Key no :number has been deleted.": "Klucz nr :number został usunięty.",
|
||||
"Key no :number has been taken from :user.": "Klucz nr :number został zabrany użytkownikowi :user.",
|
||||
"Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user."
|
||||
"Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user.",
|
||||
":sender gives key no :key to :recipient": ":sender przekazuje klucz nr :key :recipient",
|
||||
":recipient takes key no :key from :sender": ":recipient zabiera klucz nr :key :sender"
|
||||
}
|
||||
|
@ -3,11 +3,14 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Toby\Domain\Slack\Controller as SlackController;
|
||||
use Toby\Infrastructure\Http\Controllers\Api\CalculateUserUnavailableDaysController;
|
||||
use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController;
|
||||
use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController;
|
||||
use Toby\Infrastructure\Http\Controllers\Api\GetAvailableVacationTypesController;
|
||||
|
||||
Route::post("slack", [SlackController::class, "getResponse"]);
|
||||
|
||||
Route::middleware("auth:sanctum")->group(function (): void {
|
||||
Route::post("vacation/calculate-days", CalculateVacationDaysController::class);
|
||||
Route::post("vacation/calculate-stats", CalculateUserVacationStatsController::class);
|
||||
|
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Inertia\Testing\AssertableInertia as Assert;
|
||||
use Tests\FeatureTestCase;
|
||||
use Toby\Eloquent\Models\Key;
|
||||
@ -14,6 +15,13 @@ class KeyTest extends FeatureTestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Notification::fake();
|
||||
}
|
||||
|
||||
public function testUserCanSeeKeyList(): void
|
||||
{
|
||||
Key::factory()->count(10)->create();
|
||||
|
Loading…
x
Reference in New Issue
Block a user