* wip * wip * wip * wip * fix * wip * wip * fix * fix * cs fix * #116 - fix * #116 - changed home-office icon * Apply suggestions from code review Co-authored-by: Krzysztof Rewak <krzysztof.rewak@gmail.com> * #116 - cr fix * #116 - cs fix * #116 - cs fix * Apply suggestions from code review Co-authored-by: Ewelina Lasowy <56546832+EwelinaLasowy@users.noreply.github.com> * #5 - bump codestyle Co-authored-by: EwelinaLasowy <ewelina.lasowy@blumilk.pl> Co-authored-by: Krzysztof Rewak <krzysztof.rewak@gmail.com> Co-authored-by: Ewelina Lasowy <56546832+EwelinaLasowy@users.noreply.github.com>
This commit is contained in:
		| @@ -16,7 +16,6 @@ class ExceptionHandler extends Handler | |||||||
|         "password", |         "password", | ||||||
|         "password_confirmation", |         "password_confirmation", | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     protected array $handleByInertia = [ |     protected array $handleByInertia = [ | ||||||
|         Response::HTTP_INTERNAL_SERVER_ERROR, |         Response::HTTP_INTERNAL_SERVER_ERROR, | ||||||
|         Response::HTTP_SERVICE_UNAVAILABLE, |         Response::HTTP_SERVICE_UNAVAILABLE, | ||||||
|   | |||||||
| @@ -4,13 +4,24 @@ declare(strict_types=1); | |||||||
|  |  | ||||||
| namespace Toby\Architecture\Providers; | namespace Toby\Architecture\Providers; | ||||||
|  |  | ||||||
|  | use Illuminate\Contracts\Foundation\Application; | ||||||
|  | use Illuminate\Notifications\ChannelManager; | ||||||
| use Illuminate\Support\Carbon; | use Illuminate\Support\Carbon; | ||||||
|  | use Illuminate\Support\Facades\Notification; | ||||||
| use Illuminate\Support\ServiceProvider; | use Illuminate\Support\ServiceProvider; | ||||||
|  | use Toby\Infrastructure\Slack\Channels\SlackApiChannel; | ||||||
|  |  | ||||||
| class AppServiceProvider extends ServiceProvider | class AppServiceProvider extends ServiceProvider | ||||||
| { | { | ||||||
|  |     public function register(): void | ||||||
|  |     { | ||||||
|  |         Notification::resolved(function (ChannelManager $service): void { | ||||||
|  |             $service->extend("slack", fn(Application $app): SlackApiChannel => $app->make(SlackApiChannel::class)); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public function boot(): void |     public function boot(): void | ||||||
|     { |     { | ||||||
|         Carbon::macro("toDisplayString", fn() => $this->translatedFormat("d.m.Y")); |         Carbon::macro("toDisplayString", fn(): string => $this->translatedFormat("d.m.Y")); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -30,10 +30,10 @@ class AuthServiceProvider extends ServiceProvider | |||||||
|             } |             } | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         Gate::define("manageUsers", fn(User $user) => $user->role === Role::AdministrativeApprover); |         Gate::define("manageUsers", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|         Gate::define("manageHolidays", fn(User $user) => $user->role === Role::AdministrativeApprover); |         Gate::define("manageHolidays", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|         Gate::define("manageVacationLimits", fn(User $user) => $user->role === Role::AdministrativeApprover); |         Gate::define("manageVacationLimits", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|         Gate::define("generateTimesheet", fn(User $user) => $user->role === Role::AdministrativeApprover); |         Gate::define("generateTimesheet", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|         Gate::define("listMonthlyUsage", fn(User $user) => $user->role === Role::AdministrativeApprover); |         Gate::define("listMonthlyUsage", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,6 +28,6 @@ class RouteServiceProvider extends ServiceProvider | |||||||
|  |  | ||||||
|     protected function configureRateLimiting(): void |     protected function configureRateLimiting(): void | ||||||
|     { |     { | ||||||
|         RateLimiter::for("api", fn(Request $request) => Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip())); |         RateLimiter::for("api", fn(Request $request): Limit => Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip())); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -53,7 +53,6 @@ class CreateAction | |||||||
|         $vacationRequest->save(); |         $vacationRequest->save(); | ||||||
|  |  | ||||||
|         $days = $this->vacationDaysCalculator->calculateDays( |         $days = $this->vacationDaysCalculator->calculateDays( | ||||||
|             $vacationRequest->yearPeriod, |  | ||||||
|             $vacationRequest->from, |             $vacationRequest->from, | ||||||
|             $vacationRequest->to, |             $vacationRequest->to, | ||||||
|         ); |         ); | ||||||
|   | |||||||
| @@ -57,6 +57,6 @@ class CalendarGenerator | |||||||
|             ->approved() |             ->approved() | ||||||
|             ->with("vacationRequest") |             ->with("vacationRequest") | ||||||
|             ->get() |             ->get() | ||||||
|             ->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString()); |             ->groupBy(fn(Vacation $vacation): string => $vacation->date->toDateString()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								app/Domain/DailySummaryRetriever.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								app/Domain/DailySummaryRetriever.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | <?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): bool => $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): bool => !$this->configRetriever->isVacation($type)), | ||||||
|  |             ) | ||||||
|  |             ->get(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getBirthdays(Carbon $date): Collection | ||||||
|  |     { | ||||||
|  |         return User::query() | ||||||
|  |             ->whereRelation("profile", "birthday", $date) | ||||||
|  |             ->get(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -21,7 +21,7 @@ enum EmploymentForm: string | |||||||
|         $cases = collect(EmploymentForm::cases()); |         $cases = collect(EmploymentForm::cases()); | ||||||
|  |  | ||||||
|         return $cases->map( |         return $cases->map( | ||||||
|             fn(EmploymentForm $enum) => [ |             fn(EmploymentForm $enum): array => [ | ||||||
|                 "label" => $enum->label(), |                 "label" => $enum->label(), | ||||||
|                 "value" => $enum->value, |                 "value" => $enum->value, | ||||||
|             ], |             ], | ||||||
|   | |||||||
| @@ -21,7 +21,7 @@ enum Role: string | |||||||
|         $cases = collect(Role::cases()); |         $cases = collect(Role::cases()); | ||||||
|  |  | ||||||
|         return $cases->map( |         return $cases->map( | ||||||
|             fn(Role $enum) => [ |             fn(Role $enum): array => [ | ||||||
|                 "label" => $enum->label(), |                 "label" => $enum->label(), | ||||||
|                 "value" => $enum->value, |                 "value" => $enum->value, | ||||||
|             ], |             ], | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ enum VacationType: string | |||||||
|         $cases = VacationType::all(); |         $cases = VacationType::all(); | ||||||
|  |  | ||||||
|         return $cases->map( |         return $cases->map( | ||||||
|             fn(VacationType $enum) => [ |             fn(VacationType $enum): array => [ | ||||||
|                 "label" => $enum->label(), |                 "label" => $enum->label(), | ||||||
|                 "value" => $enum->value, |                 "value" => $enum->value, | ||||||
|             ], |             ], | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								app/Domain/Notifications/Channels.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								app/Domain/Notifications/Channels.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Domain\Notifications; | ||||||
|  |  | ||||||
|  | class Channels | ||||||
|  | { | ||||||
|  |     public const MAIL = "mail"; | ||||||
|  |     public const SLACK = "slack"; | ||||||
|  | } | ||||||
							
								
								
									
										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 [Channels::SLACK]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toSlack(Notifiable $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 [Channels::SLACK]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toSlack(Notifiable $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; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										10
									
								
								app/Domain/Notifications/Notifiable.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app/Domain/Notifications/Notifiable.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Domain\Notifications; | ||||||
|  |  | ||||||
|  | interface Notifiable | ||||||
|  | { | ||||||
|  |     public function notify($instance); | ||||||
|  | } | ||||||
| @@ -20,7 +20,17 @@ class VacationRequestCreatedNotification extends Notification | |||||||
|  |  | ||||||
|     public function via(): array |     public function via(): array | ||||||
|     { |     { | ||||||
|         return ["mail"]; |         return [Channels::MAIL, Channels::SLACK]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toSlack(): string | ||||||
|  |     { | ||||||
|  |         $url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]); | ||||||
|  |  | ||||||
|  |         return implode("\n", [ | ||||||
|  |             $this->buildDescription(), | ||||||
|  |             "<${url}|Zobacz szczegóły>", | ||||||
|  |         ]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -80,18 +90,16 @@ class VacationRequestCreatedNotification extends Notification | |||||||
|     protected function buildDescription(): string |     protected function buildDescription(): string | ||||||
|     { |     { | ||||||
|         $name = $this->vacationRequest->name; |         $name = $this->vacationRequest->name; | ||||||
|         $appName = config("app.name"); |  | ||||||
|  |  | ||||||
|         if ($this->vacationRequest->creator()->is($this->vacationRequest->user)) { |         if ($this->vacationRequest->creator()->is($this->vacationRequest->user)) { | ||||||
|             return __("The vacation request :title has been created correctly in the :appName.", [ |             return __("The vacation request :title from user :user has been created successfully.", [ | ||||||
|  |                 "user" => $this->vacationRequest->user->profile->full_name, | ||||||
|                 "title" => $name, |                 "title" => $name, | ||||||
|                 "appName" => $appName, |  | ||||||
|             ]); |             ]); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return __("The vacation request :title has been created correctly by user :creator on your behalf in the :appName.", [ |         return __("The vacation request :title has been created successfully by user :creator on your behalf.", [ | ||||||
|             "title" => $this->vacationRequest->name, |             "title" => $this->vacationRequest->name, | ||||||
|             "appName" => $appName, |  | ||||||
|             "creator" => $this->vacationRequest->creator->profile->full_name, |             "creator" => $this->vacationRequest->creator->profile->full_name, | ||||||
|         ]); |         ]); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -22,7 +22,17 @@ class VacationRequestStatusChangedNotification extends Notification | |||||||
|  |  | ||||||
|     public function via(): array |     public function via(): array | ||||||
|     { |     { | ||||||
|         return ["mail"]; |         return [Channels::MAIL, Channels::SLACK]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toSlack(): string | ||||||
|  |     { | ||||||
|  |         $url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]); | ||||||
|  |  | ||||||
|  |         return implode("\n", [ | ||||||
|  |             $this->buildDescription(), | ||||||
|  |             "<${url}|Zobacz szczegóły>", | ||||||
|  |         ]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -43,27 +53,17 @@ class VacationRequestStatusChangedNotification extends Notification | |||||||
|     protected function buildMailMessage(string $url): MailMessage |     protected function buildMailMessage(string $url): MailMessage | ||||||
|     { |     { | ||||||
|         $user = $this->user->profile->first_name; |         $user = $this->user->profile->first_name; | ||||||
|         $title = $this->vacationRequest->name; |  | ||||||
|         $type = $this->vacationRequest->type->label(); |         $type = $this->vacationRequest->type->label(); | ||||||
|         $status = $this->vacationRequest->state->label(); |  | ||||||
|         $from = $this->vacationRequest->from->toDisplayString(); |         $from = $this->vacationRequest->from->toDisplayString(); | ||||||
|         $to = $this->vacationRequest->to->toDisplayString(); |         $to = $this->vacationRequest->to->toDisplayString(); | ||||||
|         $days = $this->vacationRequest->vacations()->count(); |         $days = $this->vacationRequest->vacations()->count(); | ||||||
|         $requester = $this->vacationRequest->user->profile->full_name; |  | ||||||
|  |  | ||||||
|         return (new MailMessage()) |         return (new MailMessage()) | ||||||
|             ->greeting(__("Hi :user!", [ |             ->greeting(__("Hi :user!", [ | ||||||
|                 "user" => $user, |                 "user" => $user, | ||||||
|             ])) |             ])) | ||||||
|             ->subject(__("Vacation request :title has been :status", [ |             ->subject($this->buildSubject()) | ||||||
|                 "title" => $title, |             ->line($this->buildDescription()) | ||||||
|                 "status" => $status, |  | ||||||
|             ])) |  | ||||||
|             ->line(__("The vacation request :title from user :requester has been :status.", [ |  | ||||||
|                 "title" => $title, |  | ||||||
|                 "requester" => $requester, |  | ||||||
|                 "status" => $status, |  | ||||||
|             ])) |  | ||||||
|             ->line(__("Vacation type: :type", [ |             ->line(__("Vacation type: :type", [ | ||||||
|                 "type" => $type, |                 "type" => $type, | ||||||
|             ])) |             ])) | ||||||
| @@ -74,4 +74,21 @@ class VacationRequestStatusChangedNotification extends Notification | |||||||
|             ])) |             ])) | ||||||
|             ->action(__("Click here for details"), $url); |             ->action(__("Click here for details"), $url); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     protected function buildSubject(): string | ||||||
|  |     { | ||||||
|  |         return __("Vacation request :title has been :status", [ | ||||||
|  |             "title" => $this->vacationRequest->name, | ||||||
|  |             "status" => $this->vacationRequest->state->label(), | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function buildDescription(): string | ||||||
|  |     { | ||||||
|  |         return __("The vacation request :title from user :requester has been :status.", [ | ||||||
|  |             "title" => $this->vacationRequest->name, | ||||||
|  |             "requester" => $this->vacationRequest->user->profile->full_name, | ||||||
|  |             "status" => $this->vacationRequest->state->label(), | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -23,7 +23,17 @@ class VacationRequestWaitsForApprovalNotification extends Notification | |||||||
|  |  | ||||||
|     public function via(): array |     public function via(): array | ||||||
|     { |     { | ||||||
|         return ["mail"]; |         return [Channels::MAIL, Channels::SLACK]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toSlack(): string | ||||||
|  |     { | ||||||
|  |         $url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]); | ||||||
|  |  | ||||||
|  |         return implode("\n", [ | ||||||
|  |             $this->buildDescription(), | ||||||
|  |             "<${url}|Zobacz szczegóły>", | ||||||
|  |         ]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -99,4 +109,3 @@ class VacationRequestWaitsForApprovalNotification extends Notification | |||||||
|         ]); |         ]); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ class PolishHolidaysRetriever | |||||||
|  |  | ||||||
|     protected function prepareHolidays(array $holidays): Collection |     protected function prepareHolidays(array $holidays): Collection | ||||||
|     { |     { | ||||||
|         return collect($holidays)->map(fn(Holiday $holiday) => [ |         return collect($holidays)->map(fn(Holiday $holiday): array => [ | ||||||
|             "name" => $holiday->getName([static::LANG_KEY]), |             "name" => $holiday->getName([static::LANG_KEY]), | ||||||
|             "date" => Carbon::createFromTimestamp($holiday->getTimestamp()), |             "date" => Carbon::createFromTimestamp($holiday->getTimestamp()), | ||||||
|         ])->values(); |         ])->values(); | ||||||
|   | |||||||
| @@ -18,7 +18,7 @@ class TimesheetExport implements WithMultipleSheets | |||||||
|     public function sheets(): array |     public function sheets(): array | ||||||
|     { |     { | ||||||
|         return $this->users |         return $this->users | ||||||
|             ->map(fn(User $user) => new TimesheetPerUserSheet($user, $this->month, $this->types)) |             ->map(fn(User $user): TimesheetPerUserSheet => new TimesheetPerUserSheet($user, $this->month, $this->types)) | ||||||
|             ->toArray(); |             ->toArray(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -193,8 +193,8 @@ class TimesheetPerUserSheet implements WithTitle, WithHeadings, WithEvents, With | |||||||
|             ->get() |             ->get() | ||||||
|             ->groupBy( |             ->groupBy( | ||||||
|                 [ |                 [ | ||||||
|                     fn(Vacation $vacation) => $vacation->date->toDateString(), |                     fn(Vacation $vacation): string => $vacation->date->toDateString(), | ||||||
|                     fn(Vacation $vacation) => $vacation->vacationRequest->type->value, |                     fn(Vacation $vacation): string => $vacation->vacationRequest->type->value, | ||||||
|                 ], |                 ], | ||||||
|             ); |             ); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -42,8 +42,8 @@ class UserVacationStatsRetriever | |||||||
|                     ->states(VacationRequestStatesRetriever::successStates()), |                     ->states(VacationRequestStatesRetriever::successStates()), | ||||||
|             ) |             ) | ||||||
|             ->get() |             ->get() | ||||||
|             ->groupBy(fn(Vacation $vacation) => strtolower($vacation->date->englishMonth)) |             ->groupBy(fn(Vacation $vacation): string => strtolower($vacation->date->englishMonth)) | ||||||
|             ->map(fn(Collection $items) => $items->count()); |             ->map(fn(Collection $items): int => $items->count()); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public function getPendingVacationDays(User $user, YearPeriod $yearPeriod): int |     public function getPendingVacationDays(User $user, YearPeriod $yearPeriod): int | ||||||
| @@ -107,13 +107,13 @@ class UserVacationStatsRetriever | |||||||
|     { |     { | ||||||
|         $types = VacationType::all(); |         $types = VacationType::all(); | ||||||
|  |  | ||||||
|         return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type)); |         return $types->filter(fn(VacationType $type): bool => $this->configRetriever->hasLimit($type)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     protected function getNotLimitableVacationTypes(): Collection |     protected function getNotLimitableVacationTypes(): Collection | ||||||
|     { |     { | ||||||
|         $types = VacationType::all(); |         $types = VacationType::all(); | ||||||
|  |  | ||||||
|         return $types->filter(fn(VacationType $type) => !$this->configRetriever->hasLimit($type)); |         return $types->filter(fn(VacationType $type): bool => !$this->configRetriever->hasLimit($type)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,9 +11,10 @@ use Toby\Eloquent\Models\YearPeriod; | |||||||
|  |  | ||||||
| class VacationDaysCalculator | class VacationDaysCalculator | ||||||
| { | { | ||||||
|     public function calculateDays(YearPeriod $yearPeriod, CarbonInterface $from, CarbonInterface $to): Collection |     public function calculateDays(CarbonInterface $from, CarbonInterface $to): Collection | ||||||
|     { |     { | ||||||
|         $period = CarbonPeriod::create($from, $to); |         $period = CarbonPeriod::create($from, $to); | ||||||
|  |         $yearPeriod = YearPeriod::findByYear($from->year); | ||||||
|         $holidays = $yearPeriod->holidays()->pluck("date"); |         $holidays = $yearPeriod->holidays()->pluck("date"); | ||||||
|  |  | ||||||
|         $validDays = new Collection(); |         $validDays = new Collection(); | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ class DoesNotExceedLimitRule implements VacationRequestRule | |||||||
|  |  | ||||||
|         $limit = $this->getUserVacationLimit($vacationRequest->user, $vacationRequest->yearPeriod); |         $limit = $this->getUserVacationLimit($vacationRequest->user, $vacationRequest->yearPeriod); | ||||||
|         $vacationDays = $this->getVacationDaysWithLimit($vacationRequest->user, $vacationRequest->yearPeriod); |         $vacationDays = $this->getVacationDaysWithLimit($vacationRequest->user, $vacationRequest->yearPeriod); | ||||||
|         $estimatedDays = $this->vacationDaysCalculator->calculateDays($vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to)->count(); |         $estimatedDays = $this->vacationDaysCalculator->calculateDays($vacationRequest->from, $vacationRequest->to)->count(); | ||||||
|  |  | ||||||
|         return $limit >= ($vacationDays + $estimatedDays); |         return $limit >= ($vacationDays + $estimatedDays); | ||||||
|     } |     } | ||||||
| @@ -64,6 +64,6 @@ class DoesNotExceedLimitRule implements VacationRequestRule | |||||||
|     { |     { | ||||||
|         $types = VacationType::all(); |         $types = VacationType::all(); | ||||||
|  |  | ||||||
|         return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type)); |         return $types->filter(fn(VacationType $type): bool => $this->configRetriever->hasLimit($type)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ class MinimumOneVacationDayRule implements VacationRequestRule | |||||||
|     public function check(VacationRequest $vacationRequest): bool |     public function check(VacationRequest $vacationRequest): bool | ||||||
|     { |     { | ||||||
|         return $this->vacationDaysCalculator |         return $this->vacationDaysCalculator | ||||||
|             ->calculateDays($vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to) |             ->calculateDays($vacationRequest->from, $vacationRequest->to) | ||||||
|             ->isNotEmpty(); |             ->isNotEmpty(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -9,5 +9,6 @@ use Toby\Eloquent\Models\VacationRequest; | |||||||
| interface VacationRequestRule | interface VacationRequestRule | ||||||
| { | { | ||||||
|     public function check(VacationRequest $vacationRequest): bool; |     public function check(VacationRequest $vacationRequest): bool; | ||||||
|  |  | ||||||
|     public function errorMessage(): string; |     public function errorMessage(): string; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ class VacationTypeCanBeSelected implements VacationRequestRule | |||||||
|         $employmentForm = $vacationRequest->user->profile->employment_form; |         $employmentForm = $vacationRequest->user->profile->employment_form; | ||||||
|  |  | ||||||
|         $availableTypes = VacationType::all() |         $availableTypes = VacationType::all() | ||||||
|             ->filter(fn(VacationType $type) => $this->configRetriever->isAvailableFor($type, $employmentForm)); |             ->filter(fn(VacationType $type): bool => $this->configRetriever->isAvailableFor($type, $employmentForm)); | ||||||
|  |  | ||||||
|         return $availableTypes->contains($vacationRequest->type); |         return $availableTypes->contains($vacationRequest->type); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ class YearPeriodRetriever | |||||||
|  |  | ||||||
|         $years = YearPeriod::all(); |         $years = YearPeriod::all(); | ||||||
|  |  | ||||||
|         $navigation = $years->map(fn(YearPeriod $yearPeriod) => $this->toNavigation($yearPeriod)); |         $navigation = $years->map(fn(YearPeriod $yearPeriod): array => $this->toNavigation($yearPeriod)); | ||||||
|  |  | ||||||
|         return [ |         return [ | ||||||
|             "current" => $this->toNavigation($current), |             "current" => $this->toNavigation($current), | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ class Holiday extends Model | |||||||
|     use HasFactory; |     use HasFactory; | ||||||
|  |  | ||||||
|     protected $guarded = []; |     protected $guarded = []; | ||||||
|  |  | ||||||
|     protected $casts = [ |     protected $casts = [ | ||||||
|         "date" => "date", |         "date" => "date", | ||||||
|     ]; |     ]; | ||||||
|   | |||||||
| @@ -8,14 +8,17 @@ use Database\Factories\KeyFactory; | |||||||
| use Illuminate\Database\Eloquent\Factories\HasFactory; | use Illuminate\Database\Eloquent\Factories\HasFactory; | ||||||
| use Illuminate\Database\Eloquent\Model; | use Illuminate\Database\Eloquent\Model; | ||||||
| use Illuminate\Database\Eloquent\Relations\BelongsTo; | use Illuminate\Database\Eloquent\Relations\BelongsTo; | ||||||
|  | use Illuminate\Notifications\Notifiable; | ||||||
|  | use Toby\Domain\Notifications\Notifiable as NotifiableInterface; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @property int $id |  * @property int $id | ||||||
|  * @property User $user |  * @property User $user | ||||||
|  */ |  */ | ||||||
| class Key extends Model | class Key extends Model implements NotifiableInterface | ||||||
| { | { | ||||||
|     use HasFactory; |     use HasFactory; | ||||||
|  |     use Notifiable; | ||||||
|  |  | ||||||
|     protected $guarded = []; |     protected $guarded = []; | ||||||
|  |  | ||||||
| @@ -24,6 +27,11 @@ class Key extends Model | |||||||
|         return $this->belongsTo(User::class); |         return $this->belongsTo(User::class); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public function routeNotificationForSlack(): string | ||||||
|  |     { | ||||||
|  |         return config("services.slack.default_channel"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     protected static function newFactory(): KeyFactory |     protected static function newFactory(): KeyFactory | ||||||
|     { |     { | ||||||
|         return KeyFactory::new(); |         return KeyFactory::new(); | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ use Toby\Eloquent\Helpers\ColorGenerator; | |||||||
|  * @property string $position |  * @property string $position | ||||||
|  * @property EmploymentForm $employment_form |  * @property EmploymentForm $employment_form | ||||||
|  * @property Carbon $employment_date |  * @property Carbon $employment_date | ||||||
|  |  * @property Carbon $birthday | ||||||
|  */ |  */ | ||||||
| class Profile extends Model | class Profile extends Model | ||||||
| { | { | ||||||
| @@ -26,12 +27,11 @@ class Profile extends Model | |||||||
|     use HasAvatar; |     use HasAvatar; | ||||||
|  |  | ||||||
|     protected $primaryKey = "user_id"; |     protected $primaryKey = "user_id"; | ||||||
|  |  | ||||||
|     protected $guarded = []; |     protected $guarded = []; | ||||||
|  |  | ||||||
|     protected $casts = [ |     protected $casts = [ | ||||||
|         "employment_form" => EmploymentForm::class, |         "employment_form" => EmploymentForm::class, | ||||||
|         "employment_date" => "date", |         "employment_date" => "date", | ||||||
|  |         "birthday" => "date", | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     public function user(): BelongsTo |     public function user(): BelongsTo | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ use Illuminate\Notifications\Notifiable; | |||||||
| use Illuminate\Support\Collection; | use Illuminate\Support\Collection; | ||||||
| use Toby\Domain\Enums\EmploymentForm; | use Toby\Domain\Enums\EmploymentForm; | ||||||
| use Toby\Domain\Enums\Role; | use Toby\Domain\Enums\Role; | ||||||
|  | use Toby\Domain\Notifications\Notifiable as NotifiableInterface; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @property int $id |  * @property int $id | ||||||
| @@ -26,25 +27,22 @@ use Toby\Domain\Enums\Role; | |||||||
|  * @property Collection $vacationRequests |  * @property Collection $vacationRequests | ||||||
|  * @property Collection $vacations |  * @property Collection $vacations | ||||||
|  */ |  */ | ||||||
| class User extends Authenticatable | class User extends Authenticatable implements NotifiableInterface | ||||||
| { | { | ||||||
|     use HasFactory; |     use HasFactory; | ||||||
|     use Notifiable; |     use Notifiable; | ||||||
|     use SoftDeletes; |     use SoftDeletes; | ||||||
|  |  | ||||||
|     protected $guarded = []; |     protected $guarded = []; | ||||||
|  |  | ||||||
|     protected $casts = [ |     protected $casts = [ | ||||||
|         "role" => Role::class, |         "role" => Role::class, | ||||||
|         "last_active_at" => "datetime", |         "last_active_at" => "datetime", | ||||||
|         "employment_form" => EmploymentForm::class, |         "employment_form" => EmploymentForm::class, | ||||||
|         "employment_date" => "date", |         "employment_date" => "date", | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     protected $hidden = [ |     protected $hidden = [ | ||||||
|         "remember_token", |         "remember_token", | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     protected $with = [ |     protected $with = [ | ||||||
|         "profile", |         "profile", | ||||||
|     ]; |     ]; | ||||||
| @@ -102,7 +100,7 @@ class User extends Authenticatable | |||||||
|             ->where("email", "ILIKE", "%{$text}%") |             ->where("email", "ILIKE", "%{$text}%") | ||||||
|             ->orWhereRelation( |             ->orWhereRelation( | ||||||
|                 "profile", |                 "profile", | ||||||
|                 fn(Builder $query) => $query |                 fn(Builder $query): Builder => $query | ||||||
|                     ->where("first_name", "ILIKE", "%{$text}%") |                     ->where("first_name", "ILIKE", "%{$text}%") | ||||||
|                     ->orWhere("last_name", "ILIKE", "%{$text}%"), |                     ->orWhere("last_name", "ILIKE", "%{$text}%"), | ||||||
|             ); |             ); | ||||||
| @@ -125,6 +123,11 @@ class User extends Authenticatable | |||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public function routeNotificationForSlack() | ||||||
|  |     { | ||||||
|  |         return $this->profile->slack_id; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     protected static function newFactory(): UserFactory |     protected static function newFactory(): UserFactory | ||||||
|     { |     { | ||||||
|         return UserFactory::new(); |         return UserFactory::new(); | ||||||
|   | |||||||
| @@ -41,7 +41,6 @@ class VacationRequest extends Model | |||||||
|     use HasStates; |     use HasStates; | ||||||
|  |  | ||||||
|     protected $guarded = []; |     protected $guarded = []; | ||||||
|  |  | ||||||
|     protected $casts = [ |     protected $casts = [ | ||||||
|         "type" => VacationType::class, |         "type" => VacationType::class, | ||||||
|         "state" => VacationRequestState::class, |         "state" => VacationRequestState::class, | ||||||
|   | |||||||
| @@ -22,7 +22,6 @@ class VacationRequestActivity extends Model | |||||||
|     use HasFactory; |     use HasFactory; | ||||||
|  |  | ||||||
|     protected $guarded = []; |     protected $guarded = []; | ||||||
|  |  | ||||||
|     protected $casts = [ |     protected $casts = [ | ||||||
|         "from" => VacationRequestState::class, |         "from" => VacationRequestState::class, | ||||||
|         "to" => VacationRequestState::class, |         "to" => VacationRequestState::class, | ||||||
|   | |||||||
| @@ -0,0 +1,79 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | 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 Toby\Domain\DailySummaryRetriever; | ||||||
|  | use Toby\Eloquent\Models\Holiday; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\AbsencesAttachment; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\BirthdaysAttachment; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\RemotesAttachment; | ||||||
|  |  | ||||||
|  | class SendDailySummaryToSlack extends Command | ||||||
|  | { | ||||||
|  |     protected $signature = "toby:slack:daily-summary {--f|force}"; | ||||||
|  |     protected $description = "Sent daily summary to slack"; | ||||||
|  |  | ||||||
|  |     public function handle(DailySummaryRetriever $dailySummaryRetriever): void | ||||||
|  |     { | ||||||
|  |         $now = Carbon::today(); | ||||||
|  |  | ||||||
|  |         if (!$this->option("force") && !$this->shouldHandle($now)) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $attachments = new Collection([ | ||||||
|  |             new AbsencesAttachment($dailySummaryRetriever->getAbsences($now)), | ||||||
|  |             new RemotesAttachment($dailySummaryRetriever->getRemoteDays($now)), | ||||||
|  |             new BirthdaysAttachment($dailySummaryRetriever->getBirthdays($now)), | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         Http::withToken($this->getSlackClientToken()) | ||||||
|  |             ->post($this->getUrl(), [ | ||||||
|  |                 "channel" => $this->getSlackChannel(), | ||||||
|  |                 "text" => "Podsumowanie dla dnia {$now->toDisplayString()}", | ||||||
|  |                 "attachments" => $attachments, | ||||||
|  |             ]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function shouldHandle(CarbonInterface $day): bool | ||||||
|  |     { | ||||||
|  |         $holidays = Holiday::query()->whereDate("date", $day)->pluck("date"); | ||||||
|  |  | ||||||
|  |         if ($day->isWeekend()) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if ($holidays->contains($day)) { | ||||||
|  |             return false; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getUrl(): string | ||||||
|  |     { | ||||||
|  |         return "{$this->getSlackBaseUrl()}/chat.postMessage"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getSlackBaseUrl(): ?string | ||||||
|  |     { | ||||||
|  |         return config("services.slack.url"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getSlackClientToken(): ?string | ||||||
|  |     { | ||||||
|  |         return config("services.slack.client_token"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getSlackChannel(): ?string | ||||||
|  |     { | ||||||
|  |         return config("services.slack.default_channel"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -14,8 +14,8 @@ class CalculateVacationDaysController extends Controller | |||||||
| { | { | ||||||
|     public function __invoke(CalculateVacationDaysRequest $request, VacationDaysCalculator $calculator): JsonResponse |     public function __invoke(CalculateVacationDaysRequest $request, VacationDaysCalculator $calculator): JsonResponse | ||||||
|     { |     { | ||||||
|         $days = $calculator->calculateDays($request->yearPeriod(), $request->from(), $request->to()); |         $days = $calculator->calculateDays($request->from(), $request->to()); | ||||||
|  |  | ||||||
|         return new JsonResponse($days->map(fn(Carbon $day) => $day->toDateString())->all()); |         return new JsonResponse($days->map(fn(Carbon $day): string => $day->toDateString())->all()); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,8 +21,8 @@ class GetAvailableVacationTypesController extends Controller | |||||||
|         $user = User::query()->find($request->get("user")); |         $user = User::query()->find($request->get("user")); | ||||||
|  |  | ||||||
|         $types = VacationType::all() |         $types = VacationType::all() | ||||||
|             ->filter(fn(VacationType $type) => $configRetriever->isAvailableFor($type, $user->profile->employment_form)) |             ->filter(fn(VacationType $type): bool => $configRetriever->isAvailableFor($type, $user->profile->employment_form)) | ||||||
|             ->map(fn(VacationType $type) => [ |             ->map(fn(VacationType $type): array => [ | ||||||
|                 "label" => $type->label(), |                 "label" => $type->label(), | ||||||
|                 "value" => $type->value, |                 "value" => $type->value, | ||||||
|             ]) |             ]) | ||||||
|   | |||||||
| @@ -7,12 +7,11 @@ namespace Toby\Infrastructure\Http\Controllers; | |||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| use Illuminate\Support\Carbon; | use Illuminate\Support\Carbon; | ||||||
| use Inertia\Response; | use Inertia\Response; | ||||||
| use Toby\Domain\Enums\VacationType; | use Toby\Domain\DailySummaryRetriever; | ||||||
| use Toby\Domain\UserVacationStatsRetriever; | use Toby\Domain\UserVacationStatsRetriever; | ||||||
| use Toby\Domain\VacationRequestStatesRetriever; | use Toby\Domain\VacationRequestStatesRetriever; | ||||||
| use Toby\Domain\VacationTypeConfigRetriever; | use Toby\Domain\VacationTypeConfigRetriever; | ||||||
| use Toby\Eloquent\Helpers\YearPeriodRetriever; | use Toby\Eloquent\Helpers\YearPeriodRetriever; | ||||||
| use Toby\Eloquent\Models\Vacation; |  | ||||||
| use Toby\Eloquent\Models\VacationRequest; | use Toby\Eloquent\Models\VacationRequest; | ||||||
| use Toby\Infrastructure\Http\Resources\HolidayResource; | use Toby\Infrastructure\Http\Resources\HolidayResource; | ||||||
| use Toby\Infrastructure\Http\Resources\VacationRequestResource; | use Toby\Infrastructure\Http\Resources\VacationRequestResource; | ||||||
| @@ -25,24 +24,14 @@ class DashboardController extends Controller | |||||||
|         YearPeriodRetriever $yearPeriodRetriever, |         YearPeriodRetriever $yearPeriodRetriever, | ||||||
|         UserVacationStatsRetriever $vacationStatsRetriever, |         UserVacationStatsRetriever $vacationStatsRetriever, | ||||||
|         VacationTypeConfigRetriever $configRetriever, |         VacationTypeConfigRetriever $configRetriever, | ||||||
|  |         DailySummaryRetriever $dailySummaryRetriever, | ||||||
|     ): Response { |     ): Response { | ||||||
|         $user = $request->user(); |         $user = $request->user(); | ||||||
|         $now = Carbon::now(); |         $now = Carbon::now(); | ||||||
|         $yearPeriod = $yearPeriodRetriever->selected(); |         $yearPeriod = $yearPeriodRetriever->selected(); | ||||||
|  |  | ||||||
|         $absences = Vacation::query() |         $absences = $dailySummaryRetriever->getAbsences($now); | ||||||
|             ->with(["user", "vacationRequest"]) |         $remoteDays = $dailySummaryRetriever->getRemoteDays($now); | ||||||
|             ->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(); |  | ||||||
|  |  | ||||||
|         if ($user->can("listAll", VacationRequest::class)) { |         if ($user->can("listAll", VacationRequest::class)) { | ||||||
|             $vacationRequests = $yearPeriod->vacationRequests() |             $vacationRequests = $yearPeriod->vacationRequests() | ||||||
|   | |||||||
| @@ -8,6 +8,8 @@ use Illuminate\Auth\Access\AuthorizationException; | |||||||
| use Illuminate\Http\Request; | use Illuminate\Http\Request; | ||||||
| use Inertia\Response; | use Inertia\Response; | ||||||
| use Symfony\Component\HttpFoundation\RedirectResponse; | use Symfony\Component\HttpFoundation\RedirectResponse; | ||||||
|  | use Toby\Domain\Notifications\KeyHasBeenGivenNotification; | ||||||
|  | use Toby\Domain\Notifications\KeyHasBeenTakenNotification; | ||||||
| use Toby\Eloquent\Models\Key; | use Toby\Eloquent\Models\Key; | ||||||
| use Toby\Eloquent\Models\User; | use Toby\Eloquent\Models\User; | ||||||
| use Toby\Infrastructure\Http\Requests\GiveKeyRequest; | use Toby\Infrastructure\Http\Requests\GiveKeyRequest; | ||||||
| @@ -60,6 +62,8 @@ class KeysController extends Controller | |||||||
|  |  | ||||||
|         $key->save(); |         $key->save(); | ||||||
|  |  | ||||||
|  |         $key->notify(new KeyHasBeenTakenNotification($request->user(), $previousUser)); | ||||||
|  |  | ||||||
|         return redirect() |         return redirect() | ||||||
|             ->back() |             ->back() | ||||||
|             ->with("success", __("Key no :number has been taken from :user.", [ |             ->with("success", __("Key no :number has been taken from :user.", [ | ||||||
| @@ -81,6 +85,8 @@ class KeysController extends Controller | |||||||
|  |  | ||||||
|         $key->save(); |         $key->save(); | ||||||
|  |  | ||||||
|  |         $key->notify(new KeyHasBeenGivenNotification($request->user(), $recipient)); | ||||||
|  |  | ||||||
|         return redirect() |         return redirect() | ||||||
|             ->back() |             ->back() | ||||||
|             ->with("success", __("Key no :number has been given to :user.", [ |             ->with("success", __("Key no :number has been given to :user.", [ | ||||||
|   | |||||||
| @@ -35,8 +35,10 @@ class TimesheetController extends Controller | |||||||
|  |  | ||||||
|         $types = VacationType::all() |         $types = VacationType::all() | ||||||
|             ->filter( |             ->filter( | ||||||
|                 fn(VacationType $type) => $configRetriever->isAvailableFor($type, EmploymentForm::EmploymentContract) |                 fn(VacationType $type): bool => $configRetriever->isAvailableFor( | ||||||
|                     && $configRetriever->isVacation($type), |                     $type, | ||||||
|  |                     EmploymentForm::EmploymentContract, | ||||||
|  |                 ) && $configRetriever->isVacation($type), | ||||||
|             ); |             ); | ||||||
|  |  | ||||||
|         $filename = "{$carbonMonth->translatedFormat("F Y")}.xlsx"; |         $filename = "{$carbonMonth->translatedFormat("F Y")}.xlsx"; | ||||||
|   | |||||||
| @@ -30,7 +30,7 @@ class VacationLimitController extends Controller | |||||||
|             ->sortBy(fn(VacationLimit $limit): string => "{$limit->user->profile->last_name} {$limit->user->profile->first_name}") |             ->sortBy(fn(VacationLimit $limit): string => "{$limit->user->profile->last_name} {$limit->user->profile->first_name}") | ||||||
|             ->values(); |             ->values(); | ||||||
|  |  | ||||||
|         $limitsResource = $limits->map(fn(VacationLimit $limit) => [ |         $limitsResource = $limits->map(fn(VacationLimit $limit): array => [ | ||||||
|             "id" => $limit->id, |             "id" => $limit->id, | ||||||
|             "user" => new UserResource($limit->user), |             "user" => new UserResource($limit->user), | ||||||
|             "hasVacation" => $limit->hasVacation(), |             "hasVacation" => $limit->hasVacation(), | ||||||
|   | |||||||
| @@ -40,7 +40,6 @@ class Kernel extends HttpKernel | |||||||
|         TrimStrings::class, |         TrimStrings::class, | ||||||
|         ConvertEmptyStringsToNull::class, |         ConvertEmptyStringsToNull::class, | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     protected $middlewareGroups = [ |     protected $middlewareGroups = [ | ||||||
|         "web" => [ |         "web" => [ | ||||||
|             EncryptCookies::class, |             EncryptCookies::class, | ||||||
| @@ -58,7 +57,6 @@ class Kernel extends HttpKernel | |||||||
|             SubstituteBindings::class, |             SubstituteBindings::class, | ||||||
|         ], |         ], | ||||||
|     ]; |     ]; | ||||||
|  |  | ||||||
|     protected $routeMiddleware = [ |     protected $routeMiddleware = [ | ||||||
|         "auth" => Authenticate::class, |         "auth" => Authenticate::class, | ||||||
|         "auth.basic" => AuthenticateWithBasicAuth::class, |         "auth.basic" => AuthenticateWithBasicAuth::class, | ||||||
|   | |||||||
| @@ -32,7 +32,7 @@ class HandleInertiaRequests extends Middleware | |||||||
|     { |     { | ||||||
|         $user = $request->user(); |         $user = $request->user(); | ||||||
|  |  | ||||||
|         return fn() => [ |         return fn(): array => [ | ||||||
|             "user" => $user ? new UserResource($user) : null, |             "user" => $user ? new UserResource($user) : null, | ||||||
|             "can" => [ |             "can" => [ | ||||||
|                 "manageVacationLimits" => $user ? $user->can("manageVacationLimits") : false, |                 "manageVacationLimits" => $user ? $user->can("manageVacationLimits") : false, | ||||||
| @@ -45,7 +45,7 @@ class HandleInertiaRequests extends Middleware | |||||||
|  |  | ||||||
|     protected function getFlashData(Request $request): Closure |     protected function getFlashData(Request $request): Closure | ||||||
|     { |     { | ||||||
|         return fn() => [ |         return fn(): array => [ | ||||||
|             "success" => $request->session()->get("success"), |             "success" => $request->session()->get("success"), | ||||||
|             "error" => $request->session()->get("error"), |             "error" => $request->session()->get("error"), | ||||||
|             "info" => $request->session()->get("info"), |             "info" => $request->session()->get("info"), | ||||||
|   | |||||||
| @@ -22,6 +22,8 @@ class UserRequest extends FormRequest | |||||||
|             "position" => ["required"], |             "position" => ["required"], | ||||||
|             "employmentForm" => ["required", new Enum(EmploymentForm::class)], |             "employmentForm" => ["required", new Enum(EmploymentForm::class)], | ||||||
|             "employmentDate" => ["required", "date_format:Y-m-d"], |             "employmentDate" => ["required", "date_format:Y-m-d"], | ||||||
|  |             "birthday" => ["nullable", "date_format:Y-m-d"], | ||||||
|  |             "slackId" => [], | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -41,6 +43,8 @@ class UserRequest extends FormRequest | |||||||
|             "position" => $this->get("position"), |             "position" => $this->get("position"), | ||||||
|             "employment_form" => $this->get("employmentForm"), |             "employment_form" => $this->get("employmentForm"), | ||||||
|             "employment_date" => $this->get("employmentDate"), |             "employment_date" => $this->get("employmentDate"), | ||||||
|  |             "birthday" => $this->get("birthday"), | ||||||
|  |             "slack_id" => $this->get("slackId"), | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -21,6 +21,8 @@ class UserFormDataResource extends JsonResource | |||||||
|             "position" => $this->profile->position, |             "position" => $this->profile->position, | ||||||
|             "employmentForm" => $this->profile->employment_form, |             "employmentForm" => $this->profile->employment_form, | ||||||
|             "employmentDate" => $this->profile->employment_date->toDateString(), |             "employmentDate" => $this->profile->employment_date->toDateString(), | ||||||
|  |             "birthday" => $this->profile->birthday?->toDateString(), | ||||||
|  |             "slackId" => $this->profile->slack_id, | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										36
									
								
								app/Infrastructure/Slack/Channels/SlackApiChannel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Infrastructure/Slack/Channels/SlackApiChannel.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Channels; | ||||||
|  |  | ||||||
|  | use Illuminate\Http\Client\Response; | ||||||
|  | use Illuminate\Notifications\Notification; | ||||||
|  | use Illuminate\Support\Facades\Http; | ||||||
|  | use Toby\Domain\Notifications\Notifiable; | ||||||
|  |  | ||||||
|  | class SlackApiChannel | ||||||
|  | { | ||||||
|  |     public function send(Notifiable $notifiable, Notification $notification): Response | ||||||
|  |     { | ||||||
|  |         $baseUrl = $this->getBaseUrl(); | ||||||
|  |         $url = "{$baseUrl}/chat.postMessage"; | ||||||
|  |         $channel = $notifiable->routeNotificationFor("slack", $notification); | ||||||
|  |  | ||||||
|  |         return Http::withToken($this->getClientToken()) | ||||||
|  |             ->post($url, [ | ||||||
|  |                 "channel" => $channel, | ||||||
|  |                 "text" => $notification->toSlack($notifiable), | ||||||
|  |             ]); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getClientToken(): string | ||||||
|  |     { | ||||||
|  |         return config("services.slack.client_token"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getBaseUrl(): string | ||||||
|  |     { | ||||||
|  |         return config("services.slack.url"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								app/Infrastructure/Slack/Controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								app/Infrastructure/Slack/Controller.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\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\InvalidRequest; | ||||||
|  | use Spatie\SlashCommand\Exceptions\RequestCouldNotBeHandled; | ||||||
|  | use Spatie\SlashCommand\Exceptions\SlackSlashCommandException; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  |  | ||||||
|  | class Controller extends SlackController | ||||||
|  | { | ||||||
|  |     /** | ||||||
|  |      * @throws InvalidRequest|RequestCouldNotBeHandled | ||||||
|  |      */ | ||||||
|  |     public function getResponse(IlluminateRequest $request): IlluminateResponse | ||||||
|  |     { | ||||||
|  |         $this->verifyWithSigning($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 => Attachment::create() | ||||||
|  |                     ->setColor("danger") | ||||||
|  |                     ->setText($message[0]), | ||||||
|  |             ); | ||||||
|  |  | ||||||
|  |         return Response::create($this->request) | ||||||
|  |             ->withText(":x: Polecenie `/{$this->request->command} {$this->request->text}` jest niepoprawne:") | ||||||
|  |             ->withAttachments($errors->all()); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								app/Infrastructure/Slack/Elements/AbsencesAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Infrastructure/Slack/Elements/AbsencesAttachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Elements; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Toby\Eloquent\Models\Vacation; | ||||||
|  |  | ||||||
|  | class AbsencesAttachment extends ListAttachment | ||||||
|  | { | ||||||
|  |     public function __construct(Collection $absences) | ||||||
|  |     { | ||||||
|  |         parent::__construct(); | ||||||
|  |  | ||||||
|  |         $this | ||||||
|  |             ->setTitle("Nieobecności :palm_tree:") | ||||||
|  |             ->setColor("#eab308") | ||||||
|  |             ->setItems($absences->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name)) | ||||||
|  |             ->setEmptyText("Wszyscy dzisiaj pracują :muscle:"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								app/Infrastructure/Slack/Elements/Attachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app/Infrastructure/Slack/Elements/Attachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Elements; | ||||||
|  |  | ||||||
|  | use Illuminate\Contracts\Support\Arrayable; | ||||||
|  | use Spatie\SlashCommand\Attachment as BaseAttachment; | ||||||
|  |  | ||||||
|  | class Attachment extends BaseAttachment implements Arrayable | ||||||
|  | { | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								app/Infrastructure/Slack/Elements/BirthdaysAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Infrastructure/Slack/Elements/BirthdaysAttachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Elements; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Toby\Eloquent\Models\User; | ||||||
|  |  | ||||||
|  | class BirthdaysAttachment extends ListAttachment | ||||||
|  | { | ||||||
|  |     public function __construct(Collection $birthdays) | ||||||
|  |     { | ||||||
|  |         parent::__construct(); | ||||||
|  |  | ||||||
|  |         $this | ||||||
|  |             ->setTitle("Urodziny :birthday:") | ||||||
|  |             ->setColor("#3c5f97") | ||||||
|  |             ->setItems($birthdays->map(fn(User $user): string => $user->profile->full_name)) | ||||||
|  |             ->setEmptyText("Dzisiaj nikt nie ma urodzin :cry:"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								app/Infrastructure/Slack/Elements/KeysAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								app/Infrastructure/Slack/Elements/KeysAttachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Elements; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Toby\Eloquent\Models\Key; | ||||||
|  |  | ||||||
|  | class KeysAttachment extends ListAttachment | ||||||
|  | { | ||||||
|  |     public function __construct(Collection $keys) | ||||||
|  |     { | ||||||
|  |         parent::__construct(); | ||||||
|  |  | ||||||
|  |         $this | ||||||
|  |             ->setColor("#3c5f97") | ||||||
|  |             ->setItems($keys->map(fn(Key $key): string => "Klucz nr {$key->id} - <@{$key->user->profile->slack_id}>")) | ||||||
|  |             ->setEmptyText("Nie ma żadnych kluczy w tobym"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								app/Infrastructure/Slack/Elements/ListAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Infrastructure/Slack/Elements/ListAttachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Elements; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  |  | ||||||
|  | class ListAttachment extends Attachment | ||||||
|  | { | ||||||
|  |     protected Collection $items; | ||||||
|  |     protected string $emptyText = ""; | ||||||
|  |  | ||||||
|  |     public function setItems(Collection $items): static | ||||||
|  |     { | ||||||
|  |         $this->items = $items; | ||||||
|  |  | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function setEmptyText(string $emptyText): static | ||||||
|  |     { | ||||||
|  |         $this->emptyText = $emptyText; | ||||||
|  |  | ||||||
|  |         return $this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function toArray(): array | ||||||
|  |     { | ||||||
|  |         $fields = parent::toArray(); | ||||||
|  |  | ||||||
|  |         return array_merge($fields, [ | ||||||
|  |             "text" => $this->items->isNotEmpty() ? $this->items->implode("\n") : $this->emptyText, | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								app/Infrastructure/Slack/Elements/RemotesAttachment.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Infrastructure/Slack/Elements/RemotesAttachment.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Elements; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Toby\Eloquent\Models\Vacation; | ||||||
|  |  | ||||||
|  | class RemotesAttachment extends ListAttachment | ||||||
|  | { | ||||||
|  |     public function __construct(Collection $remoteDays) | ||||||
|  |     { | ||||||
|  |         parent::__construct(); | ||||||
|  |  | ||||||
|  |         $this | ||||||
|  |             ->setTitle("Praca zdalna :house_with_garden:") | ||||||
|  |             ->setColor("#527aba") | ||||||
|  |             ->setItems($remoteDays->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name)) | ||||||
|  |             ->setEmptyText("Wszyscy dzisiaj są w biurze :boom:"); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,11 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Exceptions; | ||||||
|  |  | ||||||
|  | use Spatie\SlashCommand\Exceptions\SlackSlashCommandException; | ||||||
|  |  | ||||||
|  | class UserNotFoundException extends SlackSlashCommandException | ||||||
|  | { | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								app/Infrastructure/Slack/Handlers/CatchAll.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								app/Infrastructure/Slack/Handlers/CatchAll.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Spatie\SlashCommand\Handlers\BaseHandler; | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\Attachment; | ||||||
|  | use Toby\Infrastructure\Slack\Traits\ListsHandlers; | ||||||
|  |  | ||||||
|  | class CatchAll extends BaseHandler | ||||||
|  | { | ||||||
|  |     use ListsHandlers; | ||||||
|  |  | ||||||
|  |     public function canHandle(Request $request): bool | ||||||
|  |     { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         $handlers = $this->findAvailableHandlers(); | ||||||
|  |         $attachmentFields = $this->mapHandlersToAttachments($handlers); | ||||||
|  |  | ||||||
|  |         return $this->respondToSlack(":x: Nie rozpoznaję polecenia. Lista wszystkich poleceń:") | ||||||
|  |             ->withAttachment( | ||||||
|  |                 Attachment::create() | ||||||
|  |                     ->setColor("danger") | ||||||
|  |                     ->useMarkdown() | ||||||
|  |                     ->setFields($attachmentFields), | ||||||
|  |             ); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										36
									
								
								app/Infrastructure/Slack/Handlers/DailySummary.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Infrastructure/Slack/Handlers/DailySummary.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Carbon; | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Domain\DailySummaryRetriever; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\AbsencesAttachment; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\BirthdaysAttachment; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\RemotesAttachment; | ||||||
|  |  | ||||||
|  | class DailySummary extends SignatureHandler | ||||||
|  | { | ||||||
|  |     protected $signature = "toby dzisiaj"; | ||||||
|  |     protected $description = "Codzienne podsumowanie"; | ||||||
|  |  | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         $dailySummaryRetriever = app()->make(DailySummaryRetriever::class); | ||||||
|  |  | ||||||
|  |         $now = Carbon::today(); | ||||||
|  |  | ||||||
|  |         $attachments = new Collection([ | ||||||
|  |             new AbsencesAttachment($dailySummaryRetriever->getAbsences($now)), | ||||||
|  |             new RemotesAttachment($dailySummaryRetriever->getRemoteDays($now)), | ||||||
|  |             new BirthdaysAttachment($dailySummaryRetriever->getBirthdays($now)), | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         return $this->respondToSlack("Podsumowanie dla dnia {$now->toDisplayString()}") | ||||||
|  |             ->withAttachments($attachments->all()); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										71
									
								
								app/Infrastructure/Slack/Handlers/GiveKeysTo.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								app/Infrastructure/Slack/Handlers/GiveKeysTo.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Illuminate\Validation\ValidationException; | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Domain\Notifications\KeyHasBeenGivenNotification; | ||||||
|  | use Toby\Eloquent\Models\Key; | ||||||
|  | use Toby\Infrastructure\Slack\Exceptions\UserNotFoundException; | ||||||
|  | use Toby\Infrastructure\Slack\Rules\SlackUserExistsRule; | ||||||
|  | use Toby\Infrastructure\Slack\Traits\FindsUserBySlackId; | ||||||
|  |  | ||||||
|  | class GiveKeysTo extends SignatureHandler | ||||||
|  | { | ||||||
|  |     use FindsUserBySlackId; | ||||||
|  |  | ||||||
|  |     protected $signature = "toby klucze:dla {user}"; | ||||||
|  |     protected $description = "Przekaż klucze wskazanemu użytkownikowi"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @throws UserNotFoundException | ||||||
|  |      * @throws ValidationException | ||||||
|  |      */ | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         ["user" => $from] = $this->validate(); | ||||||
|  |  | ||||||
|  |         $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(); | ||||||
|  |  | ||||||
|  |         $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 getRules(): array | ||||||
|  |     { | ||||||
|  |         return [ | ||||||
|  |             "user" => ["required", new SlackUserExistsRule()], | ||||||
|  |         ]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getMessages(): array | ||||||
|  |     { | ||||||
|  |         return [ | ||||||
|  |             "user.required" => "Musisz podać użytkownika, któremu chcesz przekazać klucze", | ||||||
|  |         ]; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										33
									
								
								app/Infrastructure/Slack/Handlers/Help.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								app/Infrastructure/Slack/Handlers/Help.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\Attachment; | ||||||
|  | use Toby\Infrastructure\Slack\Traits\ListsHandlers; | ||||||
|  |  | ||||||
|  | class Help extends SignatureHandler | ||||||
|  | { | ||||||
|  |     use ListsHandlers; | ||||||
|  |  | ||||||
|  |     protected $signature = "toby pomoc"; | ||||||
|  |     protected $description = "Wyświetl wszystkie dostępne polecenia"; | ||||||
|  |  | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         $handlers = $this->findAvailableHandlers(); | ||||||
|  |  | ||||||
|  |         $attachmentFields = $this->mapHandlersToAttachments($handlers); | ||||||
|  |  | ||||||
|  |         return $this->respondToSlack("Dostępne polecenia:") | ||||||
|  |             ->withAttachment( | ||||||
|  |                 Attachment::create() | ||||||
|  |                     ->setColor("good") | ||||||
|  |                     ->useMarkdown() | ||||||
|  |                     ->setFields($attachmentFields), | ||||||
|  |             ); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										45
									
								
								app/Infrastructure/Slack/Handlers/HomeOffice.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								app/Infrastructure/Slack/Handlers/HomeOffice.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Carbon; | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Domain\Actions\VacationRequest\CreateAction; | ||||||
|  | use Toby\Domain\Enums\VacationType; | ||||||
|  | use Toby\Eloquent\Models\User; | ||||||
|  | use Toby\Eloquent\Models\YearPeriod; | ||||||
|  | use Toby\Infrastructure\Slack\Traits\FindsUserBySlackId; | ||||||
|  |  | ||||||
|  | class HomeOffice extends SignatureHandler | ||||||
|  | { | ||||||
|  |     use FindsUserBySlackId; | ||||||
|  |  | ||||||
|  |     protected $signature = "toby zdalnie"; | ||||||
|  |     protected $description = "Pracuj dzisiaj zdalnie"; | ||||||
|  |  | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         $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([ | ||||||
|  |             "user_id" => $user->id, | ||||||
|  |             "type" => VacationType::HomeOffice, | ||||||
|  |             "from" => $date, | ||||||
|  |             "to" => $date, | ||||||
|  |             "year_period_id" => $yearPeriod->id, | ||||||
|  |             "flow_skipped" => false, | ||||||
|  |         ], $user); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								app/Infrastructure/Slack/Handlers/KeyList.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Infrastructure/Slack/Handlers/KeyList.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Eloquent\Models\Key; | ||||||
|  | use Toby\Infrastructure\Slack\Elements\KeysAttachment; | ||||||
|  |  | ||||||
|  | class KeyList extends SignatureHandler | ||||||
|  | { | ||||||
|  |     protected $signature = "toby klucze"; | ||||||
|  |     protected $description = "Lista wszystkich kluczy"; | ||||||
|  |  | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         $keys = Key::query() | ||||||
|  |             ->orderBy("id") | ||||||
|  |             ->get(); | ||||||
|  |  | ||||||
|  |         return $this->respondToSlack("Lista kluczy :key:") | ||||||
|  |             ->withAttachment(new KeysAttachment($keys)); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								app/Infrastructure/Slack/Handlers/SignatureHandler.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Infrastructure/Slack/Handlers/SignatureHandler.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | 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 []; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										70
									
								
								app/Infrastructure/Slack/Handlers/TakeKeysFrom.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								app/Infrastructure/Slack/Handlers/TakeKeysFrom.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Handlers; | ||||||
|  |  | ||||||
|  | use Illuminate\Validation\ValidationException; | ||||||
|  | use Spatie\SlashCommand\Request; | ||||||
|  | use Spatie\SlashCommand\Response; | ||||||
|  | use Toby\Domain\Notifications\KeyHasBeenTakenNotification; | ||||||
|  | use Toby\Eloquent\Models\Key; | ||||||
|  | use Toby\Infrastructure\Slack\Exceptions\UserNotFoundException; | ||||||
|  | use Toby\Infrastructure\Slack\Rules\SlackUserExistsRule; | ||||||
|  | use Toby\Infrastructure\Slack\Traits\FindsUserBySlackId; | ||||||
|  |  | ||||||
|  | class TakeKeysFrom extends SignatureHandler | ||||||
|  | { | ||||||
|  |     use FindsUserBySlackId; | ||||||
|  |  | ||||||
|  |     protected $signature = "toby klucze:od {user}"; | ||||||
|  |     protected $description = "Zabierz klucze wskazanemu użytkownikowi"; | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @throws UserNotFoundException|ValidationException | ||||||
|  |      */ | ||||||
|  |     public function handle(Request $request): Response | ||||||
|  |     { | ||||||
|  |         ["user" => $from] = $this->validate(); | ||||||
|  |  | ||||||
|  |         $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(); | ||||||
|  |  | ||||||
|  |         $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 getRules(): array | ||||||
|  |     { | ||||||
|  |         return [ | ||||||
|  |             "user" => ["required", new SlackUserExistsRule()], | ||||||
|  |         ]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getMessages(): array | ||||||
|  |     { | ||||||
|  |         return [ | ||||||
|  |             "user.required" => "Musisz podać użytkownika, któremu chcesz zabrać klucze", | ||||||
|  |         ]; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										24
									
								
								app/Infrastructure/Slack/Rules/SlackUserExistsRule.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Infrastructure/Slack/Rules/SlackUserExistsRule.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Rules; | ||||||
|  |  | ||||||
|  | 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/Infrastructure/Slack/Traits/FindsUserBySlackId.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Infrastructure/Slack/Traits/FindsUserBySlackId.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Traits; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Str; | ||||||
|  | use Toby\Eloquent\Models\User; | ||||||
|  | use Toby\Infrastructure\Slack\Exceptions\UserNotFoundException; | ||||||
|  |  | ||||||
|  | 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, "<@", "|"); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										46
									
								
								app/Infrastructure/Slack/Traits/ListsHandlers.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/Infrastructure/Slack/Traits/ListsHandlers.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Infrastructure\Slack\Traits; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Illuminate\Support\Str; | ||||||
|  | use Spatie\SlashCommand\AttachmentField; | ||||||
|  | use Spatie\SlashCommand\Handlers\BaseHandler; | ||||||
|  | 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): BaseHandler => new $handlerClassName($this->request)) | ||||||
|  |             ->filter(fn(HandlesSlashCommand $handler): bool => $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): int => strcmp( | ||||||
|  |                     $handlerA->getFullCommand(), | ||||||
|  |                     $handlerB->getFullCommand(), | ||||||
|  |                 ), | ||||||
|  |             ) | ||||||
|  |             ->map( | ||||||
|  |                 fn(SignatureHandler $handler): AttachmentField => AttachmentField::create( | ||||||
|  |                     $handler->getDescription(), | ||||||
|  |                     "`/{$handler->getSignature()}`", | ||||||
|  |                 ), | ||||||
|  |             ) | ||||||
|  |             ->all(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -21,7 +21,8 @@ | |||||||
|         "maatwebsite/excel": "^3.1", |         "maatwebsite/excel": "^3.1", | ||||||
|         "rackbeat/laravel-ui-avatars": "^1.0", |         "rackbeat/laravel-ui-avatars": "^1.0", | ||||||
|         "spatie/laravel-google-calendar": "^3.5", |         "spatie/laravel-google-calendar": "^3.5", | ||||||
|         "spatie/laravel-model-states": "^2.1" |         "spatie/laravel-model-states": "^2.1", | ||||||
|  |         "spatie/laravel-slack-slash-command": "^1.11" | ||||||
|     }, |     }, | ||||||
|     "require-dev": { |     "require-dev": { | ||||||
|         "blumilksoftware/codestyle": "^1.0.0", |         "blumilksoftware/codestyle": "^1.0.0", | ||||||
| @@ -61,7 +62,8 @@ | |||||||
|     "extra": { |     "extra": { | ||||||
|         "laravel": { |         "laravel": { | ||||||
|             "dont-discover": [ |             "dont-discover": [ | ||||||
|                 "laravel/telescope" |                 "laravel/telescope", | ||||||
|  |                 "spatie/laravel-slack-slash-command" | ||||||
|             ] |             ] | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|   | |||||||
							
								
								
									
										402
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										402
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							| @@ -4,7 +4,7 @@ | |||||||
|         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", |         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | ||||||
|         "This file is @generated automatically" |         "This file is @generated automatically" | ||||||
|     ], |     ], | ||||||
|     "content-hash": "414a1fc13e0731e59605248bd4e39de6", |     "content-hash": "24a1b3a5dd7c4d4f50d521dda4b6654e", | ||||||
|     "packages": [ |     "packages": [ | ||||||
|         { |         { | ||||||
|             "name": "asm89/stack-cors", |             "name": "asm89/stack-cors", | ||||||
| @@ -815,23 +815,23 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "firebase/php-jwt", |             "name": "firebase/php-jwt", | ||||||
|             "version": "v5.5.1", |             "version": "v6.1.2", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/firebase/php-jwt.git", |                 "url": "https://github.com/firebase/php-jwt.git", | ||||||
|                 "reference": "83b609028194aa042ea33b5af2d41a7427de80e6" |                 "reference": "c297139da7c6873dbd67cbd1093f09ec0bbd0c50" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6", |                 "url": "https://api.github.com/repos/firebase/php-jwt/zipball/c297139da7c6873dbd67cbd1093f09ec0bbd0c50", | ||||||
|                 "reference": "83b609028194aa042ea33b5af2d41a7427de80e6", |                 "reference": "c297139da7c6873dbd67cbd1093f09ec0bbd0c50", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
|                 "php": ">=5.3.0" |                 "php": "^7.1||^8.0" | ||||||
|             }, |             }, | ||||||
|             "require-dev": { |             "require-dev": { | ||||||
|                 "phpunit/phpunit": ">=4.8 <=9" |                 "phpunit/phpunit": "^7.5||9.5" | ||||||
|             }, |             }, | ||||||
|             "suggest": { |             "suggest": { | ||||||
|                 "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" |                 "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" | ||||||
| @@ -866,9 +866,9 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/firebase/php-jwt/issues", |                 "issues": "https://github.com/firebase/php-jwt/issues", | ||||||
|                 "source": "https://github.com/firebase/php-jwt/tree/v5.5.1" |                 "source": "https://github.com/firebase/php-jwt/tree/v6.1.2" | ||||||
|             }, |             }, | ||||||
|             "time": "2021-11-08T20:18:51+00:00" |             "time": "2022-04-21T14:37:18+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "fruitcake/laravel-cors", |             "name": "fruitcake/laravel-cors", | ||||||
| @@ -1022,16 +1022,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "google/apiclient", |             "name": "google/apiclient", | ||||||
|             "version": "v2.12.2", |             "version": "v2.12.4", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/googleapis/google-api-php-client.git", |                 "url": "https://github.com/googleapis/google-api-php-client.git", | ||||||
|                 "reference": "a18b0e1ef5618523c607c01a41ec137c7f9af3b1" |                 "reference": "702eed9ae7022ba20dc7118c8161060cb50ee9f8" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/a18b0e1ef5618523c607c01a41ec137c7f9af3b1", |                 "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/702eed9ae7022ba20dc7118c8161060cb50ee9f8", | ||||||
|                 "reference": "a18b0e1ef5618523c607c01a41ec137c7f9af3b1", |                 "reference": "702eed9ae7022ba20dc7118c8161060cb50ee9f8", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -1087,22 +1087,22 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/googleapis/google-api-php-client/issues", |                 "issues": "https://github.com/googleapis/google-api-php-client/issues", | ||||||
|                 "source": "https://github.com/googleapis/google-api-php-client/tree/v2.12.2" |                 "source": "https://github.com/googleapis/google-api-php-client/tree/v2.12.4" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-04-05T16:19:05+00:00" |             "time": "2022-04-20T16:44:03+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "google/apiclient-services", |             "name": "google/apiclient-services", | ||||||
|             "version": "v0.242.0", |             "version": "v0.246.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/googleapis/google-api-php-client-services.git", |                 "url": "https://github.com/googleapis/google-api-php-client-services.git", | ||||||
|                 "reference": "73d4c0ed4b241e7396699e0ee1d1cdebabac25e8" |                 "reference": "33aef1ccce34799a1124c39951fed8ad0b16aced" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/73d4c0ed4b241e7396699e0ee1d1cdebabac25e8", |                 "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/33aef1ccce34799a1124c39951fed8ad0b16aced", | ||||||
|                 "reference": "73d4c0ed4b241e7396699e0ee1d1cdebabac25e8", |                 "reference": "33aef1ccce34799a1124c39951fed8ad0b16aced", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -1131,30 +1131,30 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/googleapis/google-api-php-client-services/issues", |                 "issues": "https://github.com/googleapis/google-api-php-client-services/issues", | ||||||
|                 "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.242.0" |                 "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.246.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-04-03T01:24:10+00:00" |             "time": "2022-04-24T00:58:37+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "google/auth", |             "name": "google/auth", | ||||||
|             "version": "v1.19.0", |             "version": "v1.21.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/googleapis/google-auth-library-php.git", |                 "url": "https://github.com/googleapis/google-auth-library-php.git", | ||||||
|                 "reference": "31e5d24d5fa0eaf6adc7e596292dc4732f4b60c5" |                 "reference": "73392bad2eb6852eea9084b6bbdec752515cb849" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/31e5d24d5fa0eaf6adc7e596292dc4732f4b60c5", |                 "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/73392bad2eb6852eea9084b6bbdec752515cb849", | ||||||
|                 "reference": "31e5d24d5fa0eaf6adc7e596292dc4732f4b60c5", |                 "reference": "73392bad2eb6852eea9084b6bbdec752515cb849", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
|                 "firebase/php-jwt": "~5.0", |                 "firebase/php-jwt": "^5.5||^6.0", | ||||||
|                 "guzzlehttp/guzzle": "^6.2.1|^7.0", |                 "guzzlehttp/guzzle": "^6.2.1|^7.0", | ||||||
|                 "guzzlehttp/psr7": "^1.7|^2.0", |                 "guzzlehttp/psr7": "^1.7|^2.0", | ||||||
|                 "php": ">=5.6", |                 "php": "^7.1||^8.0", | ||||||
|                 "psr/cache": "^1.0|^2.0", |                 "psr/cache": "^1.0|^2.0|^3.0", | ||||||
|                 "psr/http-message": "^1.0" |                 "psr/http-message": "^1.0" | ||||||
|             }, |             }, | ||||||
|             "require-dev": { |             "require-dev": { | ||||||
| @@ -1162,7 +1162,7 @@ | |||||||
|                 "kelvinmo/simplejwt": "^0.2.5|^0.5.1", |                 "kelvinmo/simplejwt": "^0.2.5|^0.5.1", | ||||||
|                 "phpseclib/phpseclib": "^2.0.31", |                 "phpseclib/phpseclib": "^2.0.31", | ||||||
|                 "phpspec/prophecy-phpunit": "^1.1", |                 "phpspec/prophecy-phpunit": "^1.1", | ||||||
|                 "phpunit/phpunit": "^5.7||^8.5.13", |                 "phpunit/phpunit": "^7.5||^8.5", | ||||||
|                 "sebastian/comparator": ">=1.2.3", |                 "sebastian/comparator": ">=1.2.3", | ||||||
|                 "squizlabs/php_codesniffer": "^3.5" |                 "squizlabs/php_codesniffer": "^3.5" | ||||||
|             }, |             }, | ||||||
| @@ -1189,9 +1189,9 @@ | |||||||
|             "support": { |             "support": { | ||||||
|                 "docs": "https://googleapis.github.io/google-auth-library-php/main/", |                 "docs": "https://googleapis.github.io/google-auth-library-php/main/", | ||||||
|                 "issues": "https://github.com/googleapis/google-auth-library-php/issues", |                 "issues": "https://github.com/googleapis/google-auth-library-php/issues", | ||||||
|                 "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.19.0" |                 "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.21.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-03-24T21:22:45+00:00" |             "time": "2022-04-13T20:35:52+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "graham-campbell/result-type", |             "name": "graham-campbell/result-type", | ||||||
| @@ -1733,16 +1733,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/framework", |             "name": "laravel/framework", | ||||||
|             "version": "v9.7.0", |             "version": "v9.9.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/laravel/framework.git", |                 "url": "https://github.com/laravel/framework.git", | ||||||
|                 "reference": "54c9696ee3e558ab29317ed6e0cb16bb9db5aad4" |                 "reference": "4d5a07640891b772188d7737348886a0222737d8" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/laravel/framework/zipball/54c9696ee3e558ab29317ed6e0cb16bb9db5aad4", |                 "url": "https://api.github.com/repos/laravel/framework/zipball/4d5a07640891b772188d7737348886a0222737d8", | ||||||
|                 "reference": "54c9696ee3e558ab29317ed6e0cb16bb9db5aad4", |                 "reference": "4d5a07640891b772188d7737348886a0222737d8", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -1908,20 +1908,76 @@ | |||||||
|                 "issues": "https://github.com/laravel/framework/issues", |                 "issues": "https://github.com/laravel/framework/issues", | ||||||
|                 "source": "https://github.com/laravel/framework" |                 "source": "https://github.com/laravel/framework" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-04-05T15:07:51+00:00" |             "time": "2022-04-19T15:01:23+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/sanctum", |             "name": "laravel/helpers", | ||||||
|             "version": "v2.15.0", |             "version": "v1.5.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/laravel/sanctum.git", |                 "url": "https://github.com/laravel/helpers.git", | ||||||
|                 "reference": "5be160413b6f37dcf8758663edeab12d0e806f56" |                 "reference": "c28b0ccd799d58564c41a62395ac9511a1e72931" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/laravel/sanctum/zipball/5be160413b6f37dcf8758663edeab12d0e806f56", |                 "url": "https://api.github.com/repos/laravel/helpers/zipball/c28b0ccd799d58564c41a62395ac9511a1e72931", | ||||||
|                 "reference": "5be160413b6f37dcf8758663edeab12d0e806f56", |                 "reference": "c28b0ccd799d58564c41a62395ac9511a1e72931", | ||||||
|  |                 "shasum": "" | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "illuminate/support": "~5.8.0|^6.0|^7.0|^8.0|^9.0", | ||||||
|  |                 "php": "^7.1.3|^8.0" | ||||||
|  |             }, | ||||||
|  |             "require-dev": { | ||||||
|  |                 "phpunit/phpunit": "^7.0|^8.0|^9.0" | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "extra": { | ||||||
|  |                 "branch-alias": { | ||||||
|  |                     "dev-master": "1.x-dev" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "autoload": { | ||||||
|  |                 "files": [ | ||||||
|  |                     "src/helpers.php" | ||||||
|  |                 ] | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "MIT" | ||||||
|  |             ], | ||||||
|  |             "authors": [ | ||||||
|  |                 { | ||||||
|  |                     "name": "Taylor Otwell", | ||||||
|  |                     "email": "taylor@laravel.com" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "Dries Vints", | ||||||
|  |                     "email": "dries@laravel.com" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "description": "Provides backwards compatibility for helpers in the latest Laravel release.", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "helpers", | ||||||
|  |                 "laravel" | ||||||
|  |             ], | ||||||
|  |             "support": { | ||||||
|  |                 "source": "https://github.com/laravel/helpers/tree/v1.5.0" | ||||||
|  |             }, | ||||||
|  |             "time": "2022-01-12T15:58:51+00:00" | ||||||
|  |         }, | ||||||
|  |         { | ||||||
|  |             "name": "laravel/sanctum", | ||||||
|  |             "version": "v2.15.1", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/laravel/sanctum.git", | ||||||
|  |                 "reference": "31fbe6f85aee080c4dc2f9b03dc6dd5d0ee72473" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/laravel/sanctum/zipball/31fbe6f85aee080c4dc2f9b03dc6dd5d0ee72473", | ||||||
|  |                 "reference": "31fbe6f85aee080c4dc2f9b03dc6dd5d0ee72473", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -1973,7 +2029,7 @@ | |||||||
|                 "issues": "https://github.com/laravel/sanctum/issues", |                 "issues": "https://github.com/laravel/sanctum/issues", | ||||||
|                 "source": "https://github.com/laravel/sanctum" |                 "source": "https://github.com/laravel/sanctum" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-03-28T13:53:05+00:00" |             "time": "2022-04-08T13:39:49+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/serializable-closure", |             "name": "laravel/serializable-closure", | ||||||
| @@ -2105,16 +2161,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/telescope", |             "name": "laravel/telescope", | ||||||
|             "version": "v4.8.2", |             "version": "v4.8.3", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/laravel/telescope.git", |                 "url": "https://github.com/laravel/telescope.git", | ||||||
|                 "reference": "88e3ded3e1fc301a82403820b2f68ec5a9e092e3" |                 "reference": "bb23d58161032c8745d38348452afcbcd8adfc78" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/laravel/telescope/zipball/88e3ded3e1fc301a82403820b2f68ec5a9e092e3", |                 "url": "https://api.github.com/repos/laravel/telescope/zipball/bb23d58161032c8745d38348452afcbcd8adfc78", | ||||||
|                 "reference": "88e3ded3e1fc301a82403820b2f68ec5a9e092e3", |                 "reference": "bb23d58161032c8745d38348452afcbcd8adfc78", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -2167,9 +2223,9 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/laravel/telescope/issues", |                 "issues": "https://github.com/laravel/telescope/issues", | ||||||
|                 "source": "https://github.com/laravel/telescope/tree/v4.8.2" |                 "source": "https://github.com/laravel/telescope/tree/v4.8.3" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-04-01T14:27:12+00:00" |             "time": "2022-04-11T14:29:02+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/tinker", |             "name": "laravel/tinker", | ||||||
| @@ -2404,16 +2460,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/commonmark", |             "name": "league/commonmark", | ||||||
|             "version": "2.2.3", |             "version": "2.3.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/thephpleague/commonmark.git", |                 "url": "https://github.com/thephpleague/commonmark.git", | ||||||
|                 "reference": "47b015bc4e50fd4438c1ffef6139a1fb65d2ab71" |                 "reference": "32a49eb2b38fe5e5c417ab748a45d0beaab97955" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/47b015bc4e50fd4438c1ffef6139a1fb65d2ab71", |                 "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/32a49eb2b38fe5e5c417ab748a45d0beaab97955", | ||||||
|                 "reference": "47b015bc4e50fd4438c1ffef6139a1fb65d2ab71", |                 "reference": "32a49eb2b38fe5e5c417ab748a45d0beaab97955", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -2422,17 +2478,19 @@ | |||||||
|                 "php": "^7.4 || ^8.0", |                 "php": "^7.4 || ^8.0", | ||||||
|                 "psr/event-dispatcher": "^1.0", |                 "psr/event-dispatcher": "^1.0", | ||||||
|                 "symfony/deprecation-contracts": "^2.1 || ^3.0", |                 "symfony/deprecation-contracts": "^2.1 || ^3.0", | ||||||
|                 "symfony/polyfill-php80": "^1.15" |                 "symfony/polyfill-php80": "^1.16" | ||||||
|             }, |             }, | ||||||
|             "require-dev": { |             "require-dev": { | ||||||
|                 "cebe/markdown": "^1.0", |                 "cebe/markdown": "^1.0", | ||||||
|                 "commonmark/cmark": "0.30.0", |                 "commonmark/cmark": "0.30.0", | ||||||
|                 "commonmark/commonmark.js": "0.30.0", |                 "commonmark/commonmark.js": "0.30.0", | ||||||
|                 "composer/package-versions-deprecated": "^1.8", |                 "composer/package-versions-deprecated": "^1.8", | ||||||
|  |                 "embed/embed": "^4.4", | ||||||
|                 "erusev/parsedown": "^1.0", |                 "erusev/parsedown": "^1.0", | ||||||
|                 "ext-json": "*", |                 "ext-json": "*", | ||||||
|                 "github/gfm": "0.29.0", |                 "github/gfm": "0.29.0", | ||||||
|                 "michelf/php-markdown": "^1.4", |                 "michelf/php-markdown": "^1.4", | ||||||
|  |                 "nyholm/psr7": "^1.5", | ||||||
|                 "phpstan/phpstan": "^0.12.88 || ^1.0.0", |                 "phpstan/phpstan": "^0.12.88 || ^1.0.0", | ||||||
|                 "phpunit/phpunit": "^9.5.5", |                 "phpunit/phpunit": "^9.5.5", | ||||||
|                 "scrutinizer/ocular": "^1.8.1", |                 "scrutinizer/ocular": "^1.8.1", | ||||||
| @@ -2447,7 +2505,7 @@ | |||||||
|             "type": "library", |             "type": "library", | ||||||
|             "extra": { |             "extra": { | ||||||
|                 "branch-alias": { |                 "branch-alias": { | ||||||
|                     "dev-main": "2.3-dev" |                     "dev-main": "2.4-dev" | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             "autoload": { |             "autoload": { | ||||||
| @@ -2504,7 +2562,7 @@ | |||||||
|                     "type": "tidelift" |                     "type": "tidelift" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-02-26T21:24:45+00:00" |             "time": "2022-04-07T22:37:05+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/config", |             "name": "league/config", | ||||||
| @@ -2590,16 +2648,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/flysystem", |             "name": "league/flysystem", | ||||||
|             "version": "3.0.14", |             "version": "3.0.17", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/thephpleague/flysystem.git", |                 "url": "https://github.com/thephpleague/flysystem.git", | ||||||
|                 "reference": "46a5450352540e89cb8e7eb20c58b5b4aae481f6" |                 "reference": "29eb78cac0be0c22237c5e0f6f98234d97037d79" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/46a5450352540e89cb8e7eb20c58b5b4aae481f6", |                 "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/29eb78cac0be0c22237c5e0f6f98234d97037d79", | ||||||
|                 "reference": "46a5450352540e89cb8e7eb20c58b5b4aae481f6", |                 "reference": "29eb78cac0be0c22237c5e0f6f98234d97037d79", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -2660,7 +2718,7 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/thephpleague/flysystem/issues", |                 "issues": "https://github.com/thephpleague/flysystem/issues", | ||||||
|                 "source": "https://github.com/thephpleague/flysystem/tree/3.0.14" |                 "source": "https://github.com/thephpleague/flysystem/tree/3.0.17" | ||||||
|             }, |             }, | ||||||
|             "funding": [ |             "funding": [ | ||||||
|                 { |                 { | ||||||
| @@ -2676,20 +2734,20 @@ | |||||||
|                     "type": "tidelift" |                     "type": "tidelift" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-04-06T18:17:37+00:00" |             "time": "2022-04-14T14:57:13+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/mime-type-detection", |             "name": "league/mime-type-detection", | ||||||
|             "version": "1.9.0", |             "version": "1.11.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/thephpleague/mime-type-detection.git", |                 "url": "https://github.com/thephpleague/mime-type-detection.git", | ||||||
|                 "reference": "aa70e813a6ad3d1558fc927863d47309b4c23e69" |                 "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/aa70e813a6ad3d1558fc927863d47309b4c23e69", |                 "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd", | ||||||
|                 "reference": "aa70e813a6ad3d1558fc927863d47309b4c23e69", |                 "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -2720,7 +2778,7 @@ | |||||||
|             "description": "Mime-type detection for Flysystem", |             "description": "Mime-type detection for Flysystem", | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/thephpleague/mime-type-detection/issues", |                 "issues": "https://github.com/thephpleague/mime-type-detection/issues", | ||||||
|                 "source": "https://github.com/thephpleague/mime-type-detection/tree/1.9.0" |                 "source": "https://github.com/thephpleague/mime-type-detection/tree/1.11.0" | ||||||
|             }, |             }, | ||||||
|             "funding": [ |             "funding": [ | ||||||
|                 { |                 { | ||||||
| @@ -2732,20 +2790,20 @@ | |||||||
|                     "type": "tidelift" |                     "type": "tidelift" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2021-11-21T11:48:40+00:00" |             "time": "2022-04-17T13:12:02+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "league/oauth1-client", |             "name": "league/oauth1-client", | ||||||
|             "version": "v1.10.0", |             "version": "v1.10.1", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/thephpleague/oauth1-client.git", |                 "url": "https://github.com/thephpleague/oauth1-client.git", | ||||||
|                 "reference": "88dd16b0cff68eb9167bfc849707d2c40ad91ddc" |                 "reference": "d6365b901b5c287dd41f143033315e2f777e1167" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/88dd16b0cff68eb9167bfc849707d2c40ad91ddc", |                 "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167", | ||||||
|                 "reference": "88dd16b0cff68eb9167bfc849707d2c40ad91ddc", |                 "reference": "d6365b901b5c287dd41f143033315e2f777e1167", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -2806,22 +2864,22 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/thephpleague/oauth1-client/issues", |                 "issues": "https://github.com/thephpleague/oauth1-client/issues", | ||||||
|                 "source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.0" |                 "source": "https://github.com/thephpleague/oauth1-client/tree/v1.10.1" | ||||||
|             }, |             }, | ||||||
|             "time": "2021-08-15T23:05:49+00:00" |             "time": "2022-04-15T14:02:14+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "maatwebsite/excel", |             "name": "maatwebsite/excel", | ||||||
|             "version": "3.1.38", |             "version": "3.1.39", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/SpartnerNL/Laravel-Excel.git", |                 "url": "https://github.com/SpartnerNL/Laravel-Excel.git", | ||||||
|                 "reference": "dff132ce4d30b19863f4e84de1613fca99604992" |                 "reference": "5165334de44c6f7788a5818a1d019aa71a43e092" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/dff132ce4d30b19863f4e84de1613fca99604992", |                 "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/5165334de44c6f7788a5818a1d019aa71a43e092", | ||||||
|                 "reference": "dff132ce4d30b19863f4e84de1613fca99604992", |                 "reference": "5165334de44c6f7788a5818a1d019aa71a43e092", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -2874,7 +2932,7 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", |                 "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", | ||||||
|                 "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.38" |                 "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.39" | ||||||
|             }, |             }, | ||||||
|             "funding": [ |             "funding": [ | ||||||
|                 { |                 { | ||||||
| @@ -2886,7 +2944,7 @@ | |||||||
|                     "type": "github" |                     "type": "github" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-03-24T16:00:29+00:00" |             "time": "2022-04-23T11:44:18+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "maennchen/zipstream-php", |             "name": "maennchen/zipstream-php", | ||||||
| @@ -3118,16 +3176,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "monolog/monolog", |             "name": "monolog/monolog", | ||||||
|             "version": "2.4.0", |             "version": "2.5.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/Seldaek/monolog.git", |                 "url": "https://github.com/Seldaek/monolog.git", | ||||||
|                 "reference": "d7fd7450628561ba697b7097d86db72662f54aef" |                 "reference": "4192345e260f1d51b365536199744b987e160edc" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7fd7450628561ba697b7097d86db72662f54aef", |                 "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4192345e260f1d51b365536199744b987e160edc", | ||||||
|                 "reference": "d7fd7450628561ba697b7097d86db72662f54aef", |                 "reference": "4192345e260f1d51b365536199744b987e160edc", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -3201,7 +3259,7 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/Seldaek/monolog/issues", |                 "issues": "https://github.com/Seldaek/monolog/issues", | ||||||
|                 "source": "https://github.com/Seldaek/monolog/tree/2.4.0" |                 "source": "https://github.com/Seldaek/monolog/tree/2.5.0" | ||||||
|             }, |             }, | ||||||
|             "funding": [ |             "funding": [ | ||||||
|                 { |                 { | ||||||
| @@ -3213,7 +3271,7 @@ | |||||||
|                     "type": "tidelift" |                     "type": "tidelift" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-03-14T12:44:37+00:00" |             "time": "2022-04-08T15:43:54+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "myclabs/php-enum", |             "name": "myclabs/php-enum", | ||||||
| @@ -3856,16 +3914,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "phpoffice/phpspreadsheet", |             "name": "phpoffice/phpspreadsheet", | ||||||
|             "version": "1.22.0", |             "version": "1.23.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", |                 "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", | ||||||
|                 "reference": "3a9e29b4f386a08a151a33578e80ef1747037a48" |                 "reference": "21e4cf62699eebf007db28775f7d1554e612ed9e" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/3a9e29b4f386a08a151a33578e80ef1747037a48", |                 "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/21e4cf62699eebf007db28775f7d1554e612ed9e", | ||||||
|                 "reference": "3a9e29b4f386a08a151a33578e80ef1747037a48", |                 "reference": "21e4cf62699eebf007db28775f7d1554e612ed9e", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -3889,7 +3947,7 @@ | |||||||
|                 "php": "^7.3 || ^8.0", |                 "php": "^7.3 || ^8.0", | ||||||
|                 "psr/http-client": "^1.0", |                 "psr/http-client": "^1.0", | ||||||
|                 "psr/http-factory": "^1.0", |                 "psr/http-factory": "^1.0", | ||||||
|                 "psr/simple-cache": "^1.0" |                 "psr/simple-cache": "^1.0 || ^2.0" | ||||||
|             }, |             }, | ||||||
|             "require-dev": { |             "require-dev": { | ||||||
|                 "dealerdirect/phpcodesniffer-composer-installer": "dev-master", |                 "dealerdirect/phpcodesniffer-composer-installer": "dev-master", | ||||||
| @@ -3954,9 +4012,9 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", |                 "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", | ||||||
|                 "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.22.0" |                 "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.23.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-02-18T12:57:07+00:00" |             "time": "2022-04-24T13:53:10+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "phpoption/phpoption", |             "name": "phpoption/phpoption", | ||||||
| @@ -4140,16 +4198,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "psr/cache", |             "name": "psr/cache", | ||||||
|             "version": "2.0.0", |             "version": "3.0.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/php-fig/cache.git", |                 "url": "https://github.com/php-fig/cache.git", | ||||||
|                 "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b" |                 "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", |                 "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", | ||||||
|                 "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", |                 "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -4183,9 +4241,9 @@ | |||||||
|                 "psr-6" |                 "psr-6" | ||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "source": "https://github.com/php-fig/cache/tree/2.0.0" |                 "source": "https://github.com/php-fig/cache/tree/3.0.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2021-02-03T23:23:37+00:00" |             "time": "2021-02-03T23:26:27+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "psr/container", |             "name": "psr/container", | ||||||
| @@ -4502,25 +4560,25 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "psr/simple-cache", |             "name": "psr/simple-cache", | ||||||
|             "version": "1.0.1", |             "version": "2.0.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/php-fig/simple-cache.git", |                 "url": "https://github.com/php-fig/simple-cache.git", | ||||||
|                 "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" |                 "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", |                 "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/8707bf3cea6f710bf6ef05491234e3ab06f6432a", | ||||||
|                 "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", |                 "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
|                 "php": ">=5.3.0" |                 "php": ">=8.0.0" | ||||||
|             }, |             }, | ||||||
|             "type": "library", |             "type": "library", | ||||||
|             "extra": { |             "extra": { | ||||||
|                 "branch-alias": { |                 "branch-alias": { | ||||||
|                     "dev-master": "1.0.x-dev" |                     "dev-master": "2.0.x-dev" | ||||||
|                 } |                 } | ||||||
|             }, |             }, | ||||||
|             "autoload": { |             "autoload": { | ||||||
| @@ -4535,7 +4593,7 @@ | |||||||
|             "authors": [ |             "authors": [ | ||||||
|                 { |                 { | ||||||
|                     "name": "PHP-FIG", |                     "name": "PHP-FIG", | ||||||
|                     "homepage": "http://www.php-fig.org/" |                     "homepage": "https://www.php-fig.org/" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "description": "Common interfaces for simple caching", |             "description": "Common interfaces for simple caching", | ||||||
| @@ -4547,9 +4605,9 @@ | |||||||
|                 "simple-cache" |                 "simple-cache" | ||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "source": "https://github.com/php-fig/simple-cache/tree/master" |                 "source": "https://github.com/php-fig/simple-cache/tree/2.0.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2017-10-23T01:57:42+00:00" |             "time": "2021-10-29T13:22:09+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "psy/psysh", |             "name": "psy/psysh", | ||||||
| @@ -5040,16 +5098,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "spatie/laravel-model-states", |             "name": "spatie/laravel-model-states", | ||||||
|             "version": "2.2.0", |             "version": "2.3.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/spatie/laravel-model-states.git", |                 "url": "https://github.com/spatie/laravel-model-states.git", | ||||||
|                 "reference": "7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8" |                 "reference": "bfa12486558952eca4d6c81d4dd803b83f065297" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8", |                 "url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/bfa12486558952eca4d6c81d4dd803b83f065297", | ||||||
|                 "reference": "7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8", |                 "reference": "bfa12486558952eca4d6c81d4dd803b83f065297", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -5098,7 +5156,7 @@ | |||||||
|                 "state" |                 "state" | ||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "source": "https://github.com/spatie/laravel-model-states/tree/2.2.0" |                 "source": "https://github.com/spatie/laravel-model-states/tree/2.3.0" | ||||||
|             }, |             }, | ||||||
|             "funding": [ |             "funding": [ | ||||||
|                 { |                 { | ||||||
| @@ -5110,7 +5168,7 @@ | |||||||
|                     "type": "github" |                     "type": "github" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-03-03T11:22:16+00:00" |             "time": "2022-04-21T12:09:37+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "spatie/laravel-package-tools", |             "name": "spatie/laravel-package-tools", | ||||||
| @@ -5171,6 +5229,71 @@ | |||||||
|             ], |             ], | ||||||
|             "time": "2022-03-15T20:01:36+00:00" |             "time": "2022-03-15T20:01:36+00:00" | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             "name": "spatie/laravel-slack-slash-command", | ||||||
|  |             "version": "1.11.3", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/spatie/laravel-slack-slash-command.git", | ||||||
|  |                 "reference": "8e507653054ff08581b28d6ddf5bb4ce8c2e2335" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/spatie/laravel-slack-slash-command/zipball/8e507653054ff08581b28d6ddf5bb4ce8c2e2335", | ||||||
|  |                 "reference": "8e507653054ff08581b28d6ddf5bb4ce8c2e2335", | ||||||
|  |                 "shasum": "" | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "guzzlehttp/guzzle": "^7.0", | ||||||
|  |                 "illuminate/config": "~5.8.0|^6.0|^7.0|^8.0|^9.0", | ||||||
|  |                 "illuminate/queue": "~5.8.0|^6.0|^7.0|^8.0|^9.0", | ||||||
|  |                 "illuminate/routing": "~5.8.0|^6.0|^7.0|^8.0|^9.0", | ||||||
|  |                 "illuminate/support": "~5.8.0|^6.0|^7.0|^8.0|^9.0", | ||||||
|  |                 "laravel/helpers": "^1.0", | ||||||
|  |                 "php": "^7.3|^8.0" | ||||||
|  |             }, | ||||||
|  |             "require-dev": { | ||||||
|  |                 "mockery/mockery": "^1.0", | ||||||
|  |                 "orchestra/testbench": "~3.8.0|^4.0|^5.0|^6.0|^7.0", | ||||||
|  |                 "phpunit/phpunit": "^9.2" | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "extra": { | ||||||
|  |                 "laravel": { | ||||||
|  |                     "providers": [ | ||||||
|  |                         "Spatie\\SlashCommand\\SlashCommandServiceProvider" | ||||||
|  |                     ] | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "autoload": { | ||||||
|  |                 "psr-4": { | ||||||
|  |                     "Spatie\\SlashCommand\\": "src" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "MIT" | ||||||
|  |             ], | ||||||
|  |             "authors": [ | ||||||
|  |                 { | ||||||
|  |                     "name": "Freek Van der Herten", | ||||||
|  |                     "email": "freek@spatie.be", | ||||||
|  |                     "homepage": "https://spatie.be", | ||||||
|  |                     "role": "Developer" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "description": "Make a Laravel app respond to a slash command from Slack", | ||||||
|  |             "homepage": "https://github.com/spatie/laravel-slack-slash-command", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "laravel-slack", | ||||||
|  |                 "spatie" | ||||||
|  |             ], | ||||||
|  |             "support": { | ||||||
|  |                 "issues": "https://github.com/spatie/laravel-slack-slash-command/issues", | ||||||
|  |                 "source": "https://github.com/spatie/laravel-slack-slash-command/tree/1.11.3" | ||||||
|  |             }, | ||||||
|  |             "time": "2022-02-09T07:58:01+00:00" | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             "name": "symfony/console", |             "name": "symfony/console", | ||||||
|             "version": "v6.0.7", |             "version": "v6.0.7", | ||||||
| @@ -7529,21 +7652,21 @@ | |||||||
|     "packages-dev": [ |     "packages-dev": [ | ||||||
|         { |         { | ||||||
|             "name": "blumilksoftware/codestyle", |             "name": "blumilksoftware/codestyle", | ||||||
|             "version": "v1.0.1", |             "version": "v1.1.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/blumilksoftware/codestyle.git", |                 "url": "https://github.com/blumilksoftware/codestyle.git", | ||||||
|                 "reference": "e86ebcd5175bc435d9c8d4f83bf201a6f5a9fc60" |                 "reference": "3f2248859562afe7d7b2b16aa25e83dc73236fcc" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/e86ebcd5175bc435d9c8d4f83bf201a6f5a9fc60", |                 "url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/3f2248859562afe7d7b2b16aa25e83dc73236fcc", | ||||||
|                 "reference": "e86ebcd5175bc435d9c8d4f83bf201a6f5a9fc60", |                 "reference": "3f2248859562afe7d7b2b16aa25e83dc73236fcc", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
|                 "friendsofphp/php-cs-fixer": "^3.8.0", |                 "friendsofphp/php-cs-fixer": "^3.8.0", | ||||||
|                 "kubawerlos/php-cs-fixer-custom-fixers": "^3.7", |                 "kubawerlos/php-cs-fixer-custom-fixers": "^3.10.1", | ||||||
|                 "php": "^8.0" |                 "php": "^8.0" | ||||||
|             }, |             }, | ||||||
|             "require-dev": { |             "require-dev": { | ||||||
| @@ -7551,6 +7674,9 @@ | |||||||
|                 "phpunit/phpunit": "^9.5", |                 "phpunit/phpunit": "^9.5", | ||||||
|                 "symfony/console": "^6.0" |                 "symfony/console": "^6.0" | ||||||
|             }, |             }, | ||||||
|  |             "bin": [ | ||||||
|  |                 "bin/codestyle" | ||||||
|  |             ], | ||||||
|             "type": "library", |             "type": "library", | ||||||
|             "autoload": { |             "autoload": { | ||||||
|                 "psr-4": { |                 "psr-4": { | ||||||
| @@ -7570,9 +7696,9 @@ | |||||||
|             "description": "Blumilk codestyle configurator", |             "description": "Blumilk codestyle configurator", | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/blumilksoftware/codestyle/issues", |                 "issues": "https://github.com/blumilksoftware/codestyle/issues", | ||||||
|                 "source": "https://github.com/blumilksoftware/codestyle/tree/v1.0.1" |                 "source": "https://github.com/blumilksoftware/codestyle/tree/v1.1.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-04-04T06:25:21+00:00" |             "time": "2022-04-25T06:04:51+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "composer/pcre", |             "name": "composer/pcre", | ||||||
| @@ -8262,16 +8388,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/dusk", |             "name": "laravel/dusk", | ||||||
|             "version": "v6.22.3", |             "version": "v6.23.0", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/laravel/dusk.git", |                 "url": "https://github.com/laravel/dusk.git", | ||||||
|                 "reference": "f42844d5a7eace45d199d276bb2bc23fec788256" |                 "reference": "98901d49176977c96330fd8c2ca5460eee50a246" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/laravel/dusk/zipball/f42844d5a7eace45d199d276bb2bc23fec788256", |                 "url": "https://api.github.com/repos/laravel/dusk/zipball/98901d49176977c96330fd8c2ca5460eee50a246", | ||||||
|                 "reference": "f42844d5a7eace45d199d276bb2bc23fec788256", |                 "reference": "98901d49176977c96330fd8c2ca5460eee50a246", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -8329,9 +8455,9 @@ | |||||||
|             ], |             ], | ||||||
|             "support": { |             "support": { | ||||||
|                 "issues": "https://github.com/laravel/dusk/issues", |                 "issues": "https://github.com/laravel/dusk/issues", | ||||||
|                 "source": "https://github.com/laravel/dusk/tree/v6.22.3" |                 "source": "https://github.com/laravel/dusk/tree/v6.23.0" | ||||||
|             }, |             }, | ||||||
|             "time": "2022-04-04T15:12:34+00:00" |             "time": "2022-04-11T18:55:12+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "mockery/mockery", |             "name": "mockery/mockery", | ||||||
| @@ -10519,16 +10645,16 @@ | |||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "spatie/ignition", |             "name": "spatie/ignition", | ||||||
|             "version": "1.2.7", |             "version": "1.2.9", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/spatie/ignition.git", |                 "url": "https://github.com/spatie/ignition.git", | ||||||
|                 "reference": "2f059cf42b48f7c522efbba1c05ad59fc2c1a3f2" |                 "reference": "db25202fab2d5c14613b8914a1bb374998bbf870" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/spatie/ignition/zipball/2f059cf42b48f7c522efbba1c05ad59fc2c1a3f2", |                 "url": "https://api.github.com/repos/spatie/ignition/zipball/db25202fab2d5c14613b8914a1bb374998bbf870", | ||||||
|                 "reference": "2f059cf42b48f7c522efbba1c05ad59fc2c1a3f2", |                 "reference": "db25202fab2d5c14613b8914a1bb374998bbf870", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -10585,20 +10711,20 @@ | |||||||
|                     "type": "github" |                     "type": "github" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-03-29T08:48:34+00:00" |             "time": "2022-04-23T20:37:21+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "spatie/laravel-ignition", |             "name": "spatie/laravel-ignition", | ||||||
|             "version": "1.2.0", |             "version": "1.2.2", | ||||||
|             "source": { |             "source": { | ||||||
|                 "type": "git", |                 "type": "git", | ||||||
|                 "url": "https://github.com/spatie/laravel-ignition.git", |                 "url": "https://github.com/spatie/laravel-ignition.git", | ||||||
|                 "reference": "2b54c8c66f2d280f25e15064ebe3d5e3eda19820" |                 "reference": "924d1ae878874ad0bb49f63b69a9af759a34ee78" | ||||||
|             }, |             }, | ||||||
|             "dist": { |             "dist": { | ||||||
|                 "type": "zip", |                 "type": "zip", | ||||||
|                 "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2b54c8c66f2d280f25e15064ebe3d5e3eda19820", |                 "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/924d1ae878874ad0bb49f63b69a9af759a34ee78", | ||||||
|                 "reference": "2b54c8c66f2d280f25e15064ebe3d5e3eda19820", |                 "reference": "924d1ae878874ad0bb49f63b69a9af759a34ee78", | ||||||
|                 "shasum": "" |                 "shasum": "" | ||||||
|             }, |             }, | ||||||
|             "require": { |             "require": { | ||||||
| @@ -10675,7 +10801,7 @@ | |||||||
|                     "type": "github" |                     "type": "github" | ||||||
|                 } |                 } | ||||||
|             ], |             ], | ||||||
|             "time": "2022-04-01T21:01:58+00:00" |             "time": "2022-04-14T18:04:51+00:00" | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|             "name": "symfony/filesystem", |             "name": "symfony/filesystem", | ||||||
| @@ -10931,5 +11057,5 @@ | |||||||
|         "ext-redis": "*" |         "ext-redis": "*" | ||||||
|     }, |     }, | ||||||
|     "platform-dev": [], |     "platform-dev": [], | ||||||
|     "plugin-api-version": "2.1.0" |     "plugin-api-version": "2.2.0" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -37,12 +37,12 @@ return [ | |||||||
|         Illuminate\Translation\TranslationServiceProvider::class, |         Illuminate\Translation\TranslationServiceProvider::class, | ||||||
|         Illuminate\Validation\ValidationServiceProvider::class, |         Illuminate\Validation\ValidationServiceProvider::class, | ||||||
|         Illuminate\View\ViewServiceProvider::class, |         Illuminate\View\ViewServiceProvider::class, | ||||||
|  |         Barryvdh\DomPDF\ServiceProvider::class, | ||||||
|         Toby\Architecture\Providers\AppServiceProvider::class, |         Toby\Architecture\Providers\AppServiceProvider::class, | ||||||
|         Toby\Architecture\Providers\AuthServiceProvider::class, |         Toby\Architecture\Providers\AuthServiceProvider::class, | ||||||
|         Toby\Architecture\Providers\EventServiceProvider::class, |         Toby\Architecture\Providers\EventServiceProvider::class, | ||||||
|         Toby\Architecture\Providers\RouteServiceProvider::class, |         Toby\Architecture\Providers\RouteServiceProvider::class, | ||||||
|         Toby\Architecture\Providers\TelescopeServiceProvider::class, |         Toby\Architecture\Providers\TelescopeServiceProvider::class, | ||||||
|         Toby\Architecture\Providers\ObserverServiceProvider::class, |         Toby\Architecture\Providers\ObserverServiceProvider::class, | ||||||
|         Barryvdh\DomPDF\ServiceProvider::class, |  | ||||||
|     ], |     ], | ||||||
| ]; | ]; | ||||||
|   | |||||||
							
								
								
									
										24
									
								
								config/laravel-slack-slash-command.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								config/laravel-slack-slash-command.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\CatchAll; | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\DailySummary; | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\GiveKeysTo; | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\Help; | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\HomeOffice; | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\KeyList; | ||||||
|  | use Toby\Infrastructure\Slack\Handlers\TakeKeysFrom; | ||||||
|  |  | ||||||
|  | return [ | ||||||
|  |     "signing_secret" => env("SLACK_SIGNING_SECRET"), | ||||||
|  |     "handlers" => [ | ||||||
|  |         TakeKeysFrom::class, | ||||||
|  |         GiveKeysTo::class, | ||||||
|  |         KeyList::class, | ||||||
|  |         HomeOffice::class, | ||||||
|  |         DailySummary::class, | ||||||
|  |         Help::class, | ||||||
|  |         CatchAll::class, | ||||||
|  |     ], | ||||||
|  | ]; | ||||||
| @@ -8,4 +8,9 @@ return [ | |||||||
|         "client_secret" => env("GOOGLE_CLIENT_SECRET"), |         "client_secret" => env("GOOGLE_CLIENT_SECRET"), | ||||||
|         "redirect" => env("GOOGLE_REDIRECT"), |         "redirect" => env("GOOGLE_REDIRECT"), | ||||||
|     ], |     ], | ||||||
|  |     "slack" => [ | ||||||
|  |         "url" => "https://slack.com/api", | ||||||
|  |         "client_token" => env("SLACK_CLIENT_TOKEN"), | ||||||
|  |         "default_channel" => env("SLACK_DEFAULT_CHANNEL"), | ||||||
|  |     ], | ||||||
| ]; | ]; | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ class ProfileFactory extends Factory | |||||||
|             "employment_form" => $this->faker->randomElement(EmploymentForm::cases()), |             "employment_form" => $this->faker->randomElement(EmploymentForm::cases()), | ||||||
|             "position" => $this->faker->jobTitle(), |             "position" => $this->faker->jobTitle(), | ||||||
|             "employment_date" => Carbon::createFromInterface($this->faker->dateTimeBetween("2020-10-27"))->toDateString(), |             "employment_date" => Carbon::createFromInterface($this->faker->dateTimeBetween("2020-10-27"))->toDateString(), | ||||||
|  |             "birthday" => Carbon::createFromInterface($this->faker->dateTimeBetween("1970-01-01", "1998-01-01"))->toDateString(), | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,25 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | use Illuminate\Database\Migrations\Migration; | ||||||
|  | use Illuminate\Database\Schema\Blueprint; | ||||||
|  | use Illuminate\Support\Facades\Schema; | ||||||
|  |  | ||||||
|  | return new class() extends Migration { | ||||||
|  |     public function up(): void | ||||||
|  |     { | ||||||
|  |         Schema::table("profiles", function (Blueprint $table): void { | ||||||
|  |             $table->string("slack_id")->nullable(); | ||||||
|  |             $table->date("birthday")->nullable(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function down(): void | ||||||
|  |     { | ||||||
|  |         Schema::table("profiles", function (Blueprint $table): void { | ||||||
|  |             $table->dropColumn("slack_id"); | ||||||
|  |             $table->dropColumn("birthday"); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | }; | ||||||
| @@ -8,7 +8,7 @@ import HandHeartOutlineIcon from 'vue-material-design-icons/HandHeartOutline.vue | |||||||
| import CalendarCheckIcon from 'vue-material-design-icons/CalendarCheck.vue' | import CalendarCheckIcon from 'vue-material-design-icons/CalendarCheck.vue' | ||||||
| import MedicalBagIcon from 'vue-material-design-icons/MedicalBag.vue' | import MedicalBagIcon from 'vue-material-design-icons/MedicalBag.vue' | ||||||
| import CalendarRemoveIcon from 'vue-material-design-icons/CalendarRemove.vue' | import CalendarRemoveIcon from 'vue-material-design-icons/CalendarRemove.vue' | ||||||
| import LaptopIcon from 'vue-material-design-icons/Laptop.vue' | import HomeCityIcon from 'vue-material-design-icons/HomeCity.vue' | ||||||
|  |  | ||||||
| const types = [ | const types = [ | ||||||
|   { |   { | ||||||
| @@ -43,8 +43,8 @@ const types = [ | |||||||
|     text: 'Urlop szkoleniowy', |     text: 'Urlop szkoleniowy', | ||||||
|     value: 'training_vacation', |     value: 'training_vacation', | ||||||
|     icon: HumanMaleBoardIcon, |     icon: HumanMaleBoardIcon, | ||||||
|     color: 'text-blumilk-500', |     color: 'text-indigo-500', | ||||||
|     border: 'border-blumilk-500', |     border: 'border-indigo-500', | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     text: 'Urlop bezpłatny', |     text: 'Urlop bezpłatny', | ||||||
| @@ -84,9 +84,9 @@ const types = [ | |||||||
|   { |   { | ||||||
|     text: 'Praca zdalna', |     text: 'Praca zdalna', | ||||||
|     value: 'home_office', |     value: 'home_office', | ||||||
|     icon: LaptopIcon, |     icon: HomeCityIcon, | ||||||
|     color: 'text-fuchsia-500', |     color: 'text-blumilk-500', | ||||||
|     border: 'border-fuchsia-500', |     border: 'border-blumilk-500', | ||||||
|   }, |   }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -234,6 +234,52 @@ | |||||||
|           </p> |           </p> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|  |       <div class="items-center py-4 sm:grid sm:grid-cols-3"> | ||||||
|  |         <label | ||||||
|  |           for="slackId" | ||||||
|  |           class="block text-sm font-medium text-gray-700 sm:mt-px" | ||||||
|  |         > | ||||||
|  |           Slack ID | ||||||
|  |         </label> | ||||||
|  |         <div class="mt-1 sm:col-span-2 sm:mt-0"> | ||||||
|  |           <input | ||||||
|  |             id="position" | ||||||
|  |             v-model="form.slackId" | ||||||
|  |             type="text" | ||||||
|  |             class="block w-full max-w-lg rounded-md shadow-sm sm:text-sm" | ||||||
|  |             :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.slackId, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.slackId }" | ||||||
|  |           > | ||||||
|  |           <p | ||||||
|  |             v-if="form.errors.slackId" | ||||||
|  |             class="mt-2 text-sm text-red-600" | ||||||
|  |           > | ||||||
|  |             {{ form.errors.slackId }} | ||||||
|  |           </p> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       <div class="items-center py-4 sm:grid sm:grid-cols-3"> | ||||||
|  |         <label | ||||||
|  |           for="birthday" | ||||||
|  |           class="block text-sm font-medium text-gray-700 sm:mt-px" | ||||||
|  |         > | ||||||
|  |           Data urodzenia | ||||||
|  |         </label> | ||||||
|  |         <div class="mt-1 sm:col-span-2 sm:mt-0"> | ||||||
|  |           <FlatPickr | ||||||
|  |             id="birthday" | ||||||
|  |             v-model="form.birthday" | ||||||
|  |             placeholder="Wybierz datę" | ||||||
|  |             class="block w-full max-w-lg rounded-md shadow-sm sm:text-sm" | ||||||
|  |             :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.birthday, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.birthday }" | ||||||
|  |           /> | ||||||
|  |           <p | ||||||
|  |             v-if="form.errors.birthday" | ||||||
|  |             class="mt-2 text-sm text-red-600" | ||||||
|  |           > | ||||||
|  |             {{ form.errors.birthday }} | ||||||
|  |           </p> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|       <div class="flex justify-end py-3"> |       <div class="flex justify-end py-3"> | ||||||
|         <div class="space-x-3"> |         <div class="space-x-3"> | ||||||
|           <InertiaLink |           <InertiaLink | ||||||
| @@ -274,6 +320,8 @@ const form = useForm({ | |||||||
|   role: props.roles[0], |   role: props.roles[0], | ||||||
|   position: null, |   position: null, | ||||||
|   employmentDate: null, |   employmentDate: null, | ||||||
|  |   birthday: null, | ||||||
|  |   slackId: null, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| function createUser() { | function createUser() { | ||||||
|   | |||||||
| @@ -241,6 +241,52 @@ | |||||||
|           </p> |           </p> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|  |       <div class="items-center py-4 sm:grid sm:grid-cols-3"> | ||||||
|  |         <label | ||||||
|  |           for="birthday" | ||||||
|  |           class="block text-sm font-medium text-gray-700 sm:mt-px" | ||||||
|  |         > | ||||||
|  |           Data urodzenia | ||||||
|  |         </label> | ||||||
|  |         <div class="mt-1 sm:col-span-2 sm:mt-0"> | ||||||
|  |           <FlatPickr | ||||||
|  |             id="birthday" | ||||||
|  |             v-model="form.birthday" | ||||||
|  |             placeholder="Wybierz datę" | ||||||
|  |             class="block w-full max-w-lg rounded-md shadow-sm sm:text-sm" | ||||||
|  |             :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.birthday, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.birthday }" | ||||||
|  |           /> | ||||||
|  |           <p | ||||||
|  |             v-if="form.errors.birthday" | ||||||
|  |             class="mt-2 text-sm text-red-600" | ||||||
|  |           > | ||||||
|  |             {{ form.errors.birthday }} | ||||||
|  |           </p> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |       <div class="items-center py-4 sm:grid sm:grid-cols-3"> | ||||||
|  |         <label | ||||||
|  |           for="slackId" | ||||||
|  |           class="block text-sm font-medium text-gray-700 sm:mt-px" | ||||||
|  |         > | ||||||
|  |           Slack ID | ||||||
|  |         </label> | ||||||
|  |         <div class="mt-1 sm:col-span-2 sm:mt-0"> | ||||||
|  |           <input | ||||||
|  |             id="position" | ||||||
|  |             v-model="form.slackId" | ||||||
|  |             type="text" | ||||||
|  |             class="block w-full max-w-lg rounded-md shadow-sm sm:text-sm" | ||||||
|  |             :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors.slackId, 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors.slackId }" | ||||||
|  |           > | ||||||
|  |           <p | ||||||
|  |             v-if="form.errors.slackId" | ||||||
|  |             class="mt-2 text-sm text-red-600" | ||||||
|  |           > | ||||||
|  |             {{ form.errors.slackId }} | ||||||
|  |           </p> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|       <div class="flex justify-end py-3"> |       <div class="flex justify-end py-3"> | ||||||
|         <div class="space-x-3"> |         <div class="space-x-3"> | ||||||
|           <InertiaLink |           <InertiaLink | ||||||
| @@ -282,6 +328,8 @@ const form = useForm({ | |||||||
|   position: props.user.position, |   position: props.user.position, | ||||||
|   employmentForm: props.employmentForms.find(form => form.value === props.user.employmentForm), |   employmentForm: props.employmentForms.find(form => form.value === props.user.employmentForm), | ||||||
|   employmentDate: props.user.employmentDate, |   employmentDate: props.user.employmentDate, | ||||||
|  |   birthday: props.user.birthday, | ||||||
|  |   slackId: props.user.slackId, | ||||||
| }) | }) | ||||||
|  |  | ||||||
| function editUser() { | function editUser() { | ||||||
|   | |||||||
| @@ -23,11 +23,11 @@ | |||||||
|   "cancelled": "anulowany", |   "cancelled": "anulowany", | ||||||
|   "rejected": "odrzucony", |   "rejected": "odrzucony", | ||||||
|   "approved": "zatwierdzony", |   "approved": "zatwierdzony", | ||||||
|   "You have pending vacation request in this range.": "Masz oczekujący 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 urlopowy 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 limit has been exceeded.": "Limit urlopu został przekroczony.", | ||||||
|   "Vacation needs minimum one day.": "Urlop musi być co najmniej na jeden dzień.", |   "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 created.": "Użytkownik został utworzony.", | ||||||
|   "User has been updated.": "Użytkownik został zaktualizowany.", |   "User has been updated.": "Użytkownik został zaktualizowany.", | ||||||
|   "User has been deleted.": "Użytkownik został usunięty.", |   "User has been deleted.": "Użytkownik został usunięty.", | ||||||
| @@ -37,11 +37,11 @@ | |||||||
|   "Holiday has been deleted.": "Dzień wolny został usunięty.", |   "Holiday has been deleted.": "Dzień wolny został usunięty.", | ||||||
|   "Selected year period has been changed.": "Wybrany rok został zmieniony.", |   "Selected year period has been changed.": "Wybrany rok został zmieniony.", | ||||||
|   "Vacation limits have been updated.": "Limity urlopów zostały zaktualizowane.", |   "Vacation limits have been updated.": "Limity urlopów zostały zaktualizowane.", | ||||||
|   "Vacation request has been created.": "Wniosek urlopowy został utworzony.", |   "Vacation request has been created.": "Wniosek został utworzony.", | ||||||
|   "Vacation request has been accepted.": "Wniosek urlopowy został zaakceptowany.", |   "Vacation request has been accepted.": "Wniosek został zaakceptowany.", | ||||||
|   "Vacation request has been approved.": "Wniosek urlopowy został zatwierdzony.", |   "Vacation request has been approved.": "Wniosek został zatwierdzony.", | ||||||
|   "Vacation request has been rejected.": "Wniosek urlopowy został odrzucony.", |   "Vacation request has been rejected.": "Wniosek został odrzucony.", | ||||||
|   "Vacation request has been cancelled.": "Wniosek urlopowy został anulowany.", |   "Vacation request has been cancelled.": "Wniosek został anulowany.", | ||||||
|   "Sum:": "Suma:", |   "Sum:": "Suma:", | ||||||
|   "Date": "Data", |   "Date": "Data", | ||||||
|   "Day of week": "Dzień tygodnia", |   "Day of week": "Dzień tygodnia", | ||||||
| @@ -56,7 +56,7 @@ | |||||||
|   "All rights reserved.": "Wszelkie prawa zastrzeżone", |   "All rights reserved.": "Wszelkie prawa zastrzeżone", | ||||||
|   "Show vacation request": "Pokaż wniosek", |   "Show vacation request": "Pokaż wniosek", | ||||||
|   "Vacation request :title has been created" : "Wniosek :title został utworzony", |   "Vacation request :title has been created" : "Wniosek :title został utworzony", | ||||||
|   "The vacation request :title has been created correctly in the :appName.": "W systemie :appName został poprawnie utworzony wniosek urlopowy :title.", |   "The vacation request :title from user :requester has been created successfully.": "Wniosek :title użytkownika :requester został utworzony pomyślnie.", | ||||||
|   "Vacation type: :type": "Rodzaj wniosku: :type", |   "Vacation type: :type": "Rodzaj wniosku: :type", | ||||||
|   "From :from to :to (number of days: :days)": "Od :from do :to (liczba dni: :days)", |   "From :from to :to (number of days: :days)": "Od :from do :to (liczba dni: :days)", | ||||||
|   "Click here for details": "Kliknij, aby zobaczyć szczegóły", |   "Click here for details": "Kliknij, aby zobaczyć szczegóły", | ||||||
| @@ -67,9 +67,11 @@ | |||||||
|   "Vacation request :title has been :status": "Wniosek :title został :status", |   "Vacation request :title has been :status": "Wniosek :title został :status", | ||||||
|   "The vacation request :title from user :requester has been :status.": "Wniosek urlopowy :title użytkownika :requester został :status.", |   "The vacation request :title from user :requester has been :status.": "Wniosek urlopowy :title użytkownika :requester został :status.", | ||||||
|   "Vacation request :title has been created on your behalf": "Wniosek urlopowy :title został utworzony w Twoim imieniu", |   "Vacation request :title has been created on your behalf": "Wniosek urlopowy :title został utworzony w Twoim imieniu", | ||||||
|   "The vacation request :title has been created correctly by user :creator on your behalf in the :appName.": "W systemie :appName został poprawnie utworzony wniosek urlopowy :title w Twoim imieniu przez użytkownika :creator.", |   "The vacation request :title has been created successfully by user :creator on your behalf.": "Wniosek urlopowy :title został pomyślnie utworzony w Twoim imieniu przez użytkownika :creator.", | ||||||
|   "Key no :number has been created.": "Klucz nr :number został utworzony.", |   "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 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 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" | ||||||
| } | } | ||||||
|   | |||||||
| @@ -7,6 +7,9 @@ use Toby\Infrastructure\Http\Controllers\Api\CalculateUserUnavailableDaysControl | |||||||
| use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController; | use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController; | ||||||
| use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController; | use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController; | ||||||
| use Toby\Infrastructure\Http\Controllers\Api\GetAvailableVacationTypesController; | use Toby\Infrastructure\Http\Controllers\Api\GetAvailableVacationTypesController; | ||||||
|  | use Toby\Infrastructure\Slack\Controller as SlackController; | ||||||
|  |  | ||||||
|  | Route::post("slack", [SlackController::class, "getResponse"]); | ||||||
|  |  | ||||||
| Route::middleware("auth:sanctum")->group(function (): void { | Route::middleware("auth:sanctum")->group(function (): void { | ||||||
|     Route::post("vacation/calculate-days", CalculateVacationDaysController::class); |     Route::post("vacation/calculate-days", CalculateVacationDaysController::class); | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ declare(strict_types=1); | |||||||
| namespace Tests\Feature; | namespace Tests\Feature; | ||||||
|  |  | ||||||
| use Illuminate\Foundation\Testing\DatabaseMigrations; | use Illuminate\Foundation\Testing\DatabaseMigrations; | ||||||
|  | use Illuminate\Support\Facades\Notification; | ||||||
| use Inertia\Testing\AssertableInertia as Assert; | use Inertia\Testing\AssertableInertia as Assert; | ||||||
| use Tests\FeatureTestCase; | use Tests\FeatureTestCase; | ||||||
| use Toby\Eloquent\Models\Key; | use Toby\Eloquent\Models\Key; | ||||||
| @@ -14,6 +15,13 @@ class KeyTest extends FeatureTestCase | |||||||
| { | { | ||||||
|     use DatabaseMigrations; |     use DatabaseMigrations; | ||||||
|  |  | ||||||
|  |     protected function setUp(): void | ||||||
|  |     { | ||||||
|  |         parent::setUp(); | ||||||
|  |  | ||||||
|  |         Notification::fake(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public function testUserCanSeeKeyList(): void |     public function testUserCanSeeKeyList(): void | ||||||
|     { |     { | ||||||
|         Key::factory()->count(10)->create(); |         Key::factory()->count(10)->create(); | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								tests/Unit/SendDailySummaryToSlackTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								tests/Unit/SendDailySummaryToSlackTest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Tests\Unit; | ||||||
|  |  | ||||||
|  | use Illuminate\Foundation\Testing\RefreshDatabase; | ||||||
|  | use Illuminate\Support\Carbon; | ||||||
|  | use Illuminate\Support\Facades\Http; | ||||||
|  | use Tests\TestCase; | ||||||
|  | use Tests\Traits\InteractsWithYearPeriods; | ||||||
|  | use Toby\Eloquent\Models\Holiday; | ||||||
|  | use Toby\Infrastructure\Console\Commands\SendDailySummaryToSlack; | ||||||
|  |  | ||||||
|  | class SendDailySummaryToSlackTest extends TestCase | ||||||
|  | { | ||||||
|  |     use RefreshDatabase; | ||||||
|  |     use InteractsWithYearPeriods; | ||||||
|  |  | ||||||
|  |     protected function setUp(): void | ||||||
|  |     { | ||||||
|  |         parent::setUp(); | ||||||
|  |  | ||||||
|  |         Http::fake(); | ||||||
|  |         $this->createCurrentYearPeriod(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function testCommandSendsMessageToSlackIfWeekday(): void | ||||||
|  |     { | ||||||
|  |         $weekDay = Carbon::create(2022, 4, 22); | ||||||
|  |         $this->assertTrue($weekDay->isWeekday()); | ||||||
|  |  | ||||||
|  |         $this->travelTo($weekDay); | ||||||
|  |  | ||||||
|  |         $this->artisan(SendDailySummaryToSlack::class) | ||||||
|  |             ->execute(); | ||||||
|  |  | ||||||
|  |         Http::assertSentCount(1); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function testCommandDoesntSendMessageIfWeekend(): void | ||||||
|  |     { | ||||||
|  |         $weekend = Carbon::create(2022, 4, 23); | ||||||
|  |         $this->assertTrue($weekend->isWeekend()); | ||||||
|  |  | ||||||
|  |         $this->travelTo($weekend); | ||||||
|  |  | ||||||
|  |         $this->artisan(SendDailySummaryToSlack::class) | ||||||
|  |             ->execute(); | ||||||
|  |  | ||||||
|  |         Http::assertNothingSent(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function testCommandDoesntSendMessageIfHoliday(): void | ||||||
|  |     { | ||||||
|  |         $holiday = Holiday::factory(["date" => Carbon::create(2022, 4, 22)])->create(); | ||||||
|  |  | ||||||
|  |         $this->assertDatabaseHas("holidays", [ | ||||||
|  |             "date" => $holiday->date->toDateString(), | ||||||
|  |         ]); | ||||||
|  |  | ||||||
|  |         $this->travelTo(Carbon::create(2022, 4, 22)); | ||||||
|  |  | ||||||
|  |         $this->artisan(SendDailySummaryToSlack::class) | ||||||
|  |             ->execute(); | ||||||
|  |  | ||||||
|  |         Http::assertNothingSent(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function testCommandForceSendsMessageEvenIsWeekendOrHoliday(): void | ||||||
|  |     { | ||||||
|  |         $weekend = Carbon::create(2022, 4, 23); | ||||||
|  |         $this->assertTrue($weekend->isWeekend()); | ||||||
|  |  | ||||||
|  |         $this->travelTo($weekend); | ||||||
|  |  | ||||||
|  |         $this->artisan(SendDailySummaryToSlack::class, ["--force" => true]) | ||||||
|  |             ->execute(); | ||||||
|  |  | ||||||
|  |         Http::assertSentCount(1); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user