From c69866bb52b7e0b26806fc8883d1e7e6e2b22b42 Mon Sep 17 00:00:00 2001 From: Adrian Hopek Date: Wed, 27 Apr 2022 09:57:13 +0200 Subject: [PATCH 1/9] #116 - integration with slack (#129) * 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 * #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 Co-authored-by: Krzysztof Rewak Co-authored-by: Ewelina Lasowy <56546832+EwelinaLasowy@users.noreply.github.com> --- app/Architecture/ExceptionHandler.php | 1 - .../Providers/AppServiceProvider.php | 13 +- .../Providers/AuthServiceProvider.php | 10 +- .../Providers/RouteServiceProvider.php | 2 +- .../Actions/VacationRequest/CreateAction.php | 1 - app/Domain/CalendarGenerator.php | 2 +- app/Domain/DailySummaryRetriever.php | 49 +++ app/Domain/Enums/EmploymentForm.php | 2 +- app/Domain/Enums/Role.php | 2 +- app/Domain/Enums/VacationType.php | 2 +- app/Domain/Notifications/Channels.php | 11 + .../KeyHasBeenGivenNotification.php | 42 ++ .../KeyHasBeenTakenNotification.php | 42 ++ app/Domain/Notifications/Notifiable.php | 10 + .../VacationRequestCreatedNotification.php | 20 +- ...cationRequestStatusChangedNotification.php | 43 +- ...ionRequestWaitsForApprovalNotification.php | 13 +- app/Domain/PolishHolidaysRetriever.php | 2 +- app/Domain/TimesheetExport.php | 2 +- app/Domain/TimesheetPerUserSheet.php | 4 +- app/Domain/UserVacationStatsRetriever.php | 8 +- app/Domain/VacationDaysCalculator.php | 3 +- .../Rules/DoesNotExceedLimitRule.php | 4 +- .../Rules/MinimumOneVacationDayRule.php | 2 +- .../Validation/Rules/VacationRequestRule.php | 1 + .../Rules/VacationTypeCanBeSelected.php | 2 +- app/Eloquent/Helpers/YearPeriodRetriever.php | 2 +- app/Eloquent/Models/Holiday.php | 1 - app/Eloquent/Models/Key.php | 10 +- app/Eloquent/Models/Profile.php | 4 +- app/Eloquent/Models/User.php | 13 +- app/Eloquent/Models/VacationRequest.php | 1 - .../Models/VacationRequestActivity.php | 1 - .../Commands/SendDailySummaryToSlack.php | 79 ++++ .../Api/CalculateVacationDaysController.php | 4 +- .../GetAvailableVacationTypesController.php | 4 +- .../Http/Controllers/DashboardController.php | 19 +- .../Http/Controllers/KeysController.php | 6 + .../Http/Controllers/TimesheetController.php | 6 +- .../Controllers/VacationLimitController.php | 2 +- app/Infrastructure/Http/Kernel.php | 2 - .../Http/Middleware/HandleInertiaRequests.php | 4 +- .../Http/Requests/UserRequest.php | 4 + .../Http/Resources/UserFormDataResource.php | 2 + .../Slack/Channels/SlackApiChannel.php | 36 ++ app/Infrastructure/Slack/Controller.php | 56 +++ .../Slack/Elements/AbsencesAttachment.php | 22 + .../Slack/Elements/Attachment.php | 12 + .../Slack/Elements/BirthdaysAttachment.php | 22 + .../Slack/Elements/KeysAttachment.php | 21 + .../Slack/Elements/ListAttachment.php | 36 ++ .../Slack/Elements/RemotesAttachment.php | 22 + .../Exceptions/UserNotFoundException.php | 11 + .../Slack/Handlers/CatchAll.php | 35 ++ .../Slack/Handlers/DailySummary.php | 36 ++ .../Slack/Handlers/GiveKeysTo.php | 71 ++++ app/Infrastructure/Slack/Handlers/Help.php | 33 ++ .../Slack/Handlers/HomeOffice.php | 45 ++ app/Infrastructure/Slack/Handlers/KeyList.php | 26 ++ .../Slack/Handlers/SignatureHandler.php | 26 ++ .../Slack/Handlers/TakeKeysFrom.php | 70 +++ .../Slack/Rules/SlackUserExistsRule.php | 24 ++ .../Slack/Traits/FindsUserBySlackId.php | 43 ++ .../Slack/Traits/ListsHandlers.php | 46 ++ composer.json | 6 +- composer.lock | 402 ++++++++++++------ config/app.php | 2 +- config/laravel-slack-slash-command.php | 24 ++ config/services.php | 5 + database/factories/ProfileFactory.php | 1 + ...and_birthday_columns_in_profiles_table.php | 25 ++ resources/js/Composables/vacationTypeInfo.js | 12 +- resources/js/Pages/Users/Create.vue | 48 +++ resources/js/Pages/Users/Edit.vue | 48 +++ resources/lang/pl.json | 24 +- routes/api.php | 3 + tests/Feature/KeyTest.php | 8 + tests/Unit/SendDailySummaryToSlackTest.php | 82 ++++ 78 files changed, 1597 insertions(+), 243 deletions(-) create mode 100644 app/Domain/DailySummaryRetriever.php create mode 100644 app/Domain/Notifications/Channels.php create mode 100644 app/Domain/Notifications/KeyHasBeenGivenNotification.php create mode 100644 app/Domain/Notifications/KeyHasBeenTakenNotification.php create mode 100644 app/Domain/Notifications/Notifiable.php create mode 100644 app/Infrastructure/Console/Commands/SendDailySummaryToSlack.php create mode 100644 app/Infrastructure/Slack/Channels/SlackApiChannel.php create mode 100644 app/Infrastructure/Slack/Controller.php create mode 100644 app/Infrastructure/Slack/Elements/AbsencesAttachment.php create mode 100644 app/Infrastructure/Slack/Elements/Attachment.php create mode 100644 app/Infrastructure/Slack/Elements/BirthdaysAttachment.php create mode 100644 app/Infrastructure/Slack/Elements/KeysAttachment.php create mode 100644 app/Infrastructure/Slack/Elements/ListAttachment.php create mode 100644 app/Infrastructure/Slack/Elements/RemotesAttachment.php create mode 100644 app/Infrastructure/Slack/Exceptions/UserNotFoundException.php create mode 100644 app/Infrastructure/Slack/Handlers/CatchAll.php create mode 100644 app/Infrastructure/Slack/Handlers/DailySummary.php create mode 100644 app/Infrastructure/Slack/Handlers/GiveKeysTo.php create mode 100644 app/Infrastructure/Slack/Handlers/Help.php create mode 100644 app/Infrastructure/Slack/Handlers/HomeOffice.php create mode 100644 app/Infrastructure/Slack/Handlers/KeyList.php create mode 100644 app/Infrastructure/Slack/Handlers/SignatureHandler.php create mode 100644 app/Infrastructure/Slack/Handlers/TakeKeysFrom.php create mode 100644 app/Infrastructure/Slack/Rules/SlackUserExistsRule.php create mode 100644 app/Infrastructure/Slack/Traits/FindsUserBySlackId.php create mode 100644 app/Infrastructure/Slack/Traits/ListsHandlers.php create mode 100644 config/laravel-slack-slash-command.php create mode 100644 database/migrations/2022_04_21_101027_add_slack_id_and_birthday_columns_in_profiles_table.php create mode 100644 tests/Unit/SendDailySummaryToSlackTest.php diff --git a/app/Architecture/ExceptionHandler.php b/app/Architecture/ExceptionHandler.php index b286bd1..a43fcab 100644 --- a/app/Architecture/ExceptionHandler.php +++ b/app/Architecture/ExceptionHandler.php @@ -16,7 +16,6 @@ class ExceptionHandler extends Handler "password", "password_confirmation", ]; - protected array $handleByInertia = [ Response::HTTP_INTERNAL_SERVER_ERROR, Response::HTTP_SERVICE_UNAVAILABLE, diff --git a/app/Architecture/Providers/AppServiceProvider.php b/app/Architecture/Providers/AppServiceProvider.php index ce611b9..fbfe920 100644 --- a/app/Architecture/Providers/AppServiceProvider.php +++ b/app/Architecture/Providers/AppServiceProvider.php @@ -4,13 +4,24 @@ declare(strict_types=1); namespace Toby\Architecture\Providers; +use Illuminate\Contracts\Foundation\Application; +use Illuminate\Notifications\ChannelManager; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Notification; use Illuminate\Support\ServiceProvider; +use Toby\Infrastructure\Slack\Channels\SlackApiChannel; 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 { - Carbon::macro("toDisplayString", fn() => $this->translatedFormat("d.m.Y")); + Carbon::macro("toDisplayString", fn(): string => $this->translatedFormat("d.m.Y")); } } diff --git a/app/Architecture/Providers/AuthServiceProvider.php b/app/Architecture/Providers/AuthServiceProvider.php index cb5b112..62d21c7 100644 --- a/app/Architecture/Providers/AuthServiceProvider.php +++ b/app/Architecture/Providers/AuthServiceProvider.php @@ -30,10 +30,10 @@ class AuthServiceProvider extends ServiceProvider } }); - Gate::define("manageUsers", fn(User $user) => $user->role === Role::AdministrativeApprover); - Gate::define("manageHolidays", fn(User $user) => $user->role === Role::AdministrativeApprover); - Gate::define("manageVacationLimits", fn(User $user) => $user->role === Role::AdministrativeApprover); - Gate::define("generateTimesheet", fn(User $user) => $user->role === Role::AdministrativeApprover); - Gate::define("listMonthlyUsage", fn(User $user) => $user->role === Role::AdministrativeApprover); + Gate::define("manageUsers", fn(User $user): bool => $user->role === Role::AdministrativeApprover); + Gate::define("manageHolidays", fn(User $user): bool => $user->role === Role::AdministrativeApprover); + Gate::define("manageVacationLimits", fn(User $user): bool => $user->role === Role::AdministrativeApprover); + Gate::define("generateTimesheet", fn(User $user): bool => $user->role === Role::AdministrativeApprover); + Gate::define("listMonthlyUsage", fn(User $user): bool => $user->role === Role::AdministrativeApprover); } } diff --git a/app/Architecture/Providers/RouteServiceProvider.php b/app/Architecture/Providers/RouteServiceProvider.php index 2412290..ffd9a41 100644 --- a/app/Architecture/Providers/RouteServiceProvider.php +++ b/app/Architecture/Providers/RouteServiceProvider.php @@ -28,6 +28,6 @@ class RouteServiceProvider extends ServiceProvider 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())); } } diff --git a/app/Domain/Actions/VacationRequest/CreateAction.php b/app/Domain/Actions/VacationRequest/CreateAction.php index 8a823e3..1bb8a7a 100644 --- a/app/Domain/Actions/VacationRequest/CreateAction.php +++ b/app/Domain/Actions/VacationRequest/CreateAction.php @@ -53,7 +53,6 @@ class CreateAction $vacationRequest->save(); $days = $this->vacationDaysCalculator->calculateDays( - $vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to, ); diff --git a/app/Domain/CalendarGenerator.php b/app/Domain/CalendarGenerator.php index 30d42b7..b1c6c0f 100644 --- a/app/Domain/CalendarGenerator.php +++ b/app/Domain/CalendarGenerator.php @@ -57,6 +57,6 @@ class CalendarGenerator ->approved() ->with("vacationRequest") ->get() - ->groupBy(fn(Vacation $vacation) => $vacation->date->toDateString()); + ->groupBy(fn(Vacation $vacation): string => $vacation->date->toDateString()); } } diff --git a/app/Domain/DailySummaryRetriever.php b/app/Domain/DailySummaryRetriever.php new file mode 100644 index 0000000..a2482ef --- /dev/null +++ b/app/Domain/DailySummaryRetriever.php @@ -0,0 +1,49 @@ +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(); + } +} diff --git a/app/Domain/Enums/EmploymentForm.php b/app/Domain/Enums/EmploymentForm.php index daf671d..c3d1767 100644 --- a/app/Domain/Enums/EmploymentForm.php +++ b/app/Domain/Enums/EmploymentForm.php @@ -21,7 +21,7 @@ enum EmploymentForm: string $cases = collect(EmploymentForm::cases()); return $cases->map( - fn(EmploymentForm $enum) => [ + fn(EmploymentForm $enum): array => [ "label" => $enum->label(), "value" => $enum->value, ], diff --git a/app/Domain/Enums/Role.php b/app/Domain/Enums/Role.php index f4be8b9..bd2485c 100644 --- a/app/Domain/Enums/Role.php +++ b/app/Domain/Enums/Role.php @@ -21,7 +21,7 @@ enum Role: string $cases = collect(Role::cases()); return $cases->map( - fn(Role $enum) => [ + fn(Role $enum): array => [ "label" => $enum->label(), "value" => $enum->value, ], diff --git a/app/Domain/Enums/VacationType.php b/app/Domain/Enums/VacationType.php index a93ca3d..7940107 100644 --- a/app/Domain/Enums/VacationType.php +++ b/app/Domain/Enums/VacationType.php @@ -30,7 +30,7 @@ enum VacationType: string $cases = VacationType::all(); return $cases->map( - fn(VacationType $enum) => [ + fn(VacationType $enum): array => [ "label" => $enum->label(), "value" => $enum->value, ], diff --git a/app/Domain/Notifications/Channels.php b/app/Domain/Notifications/Channels.php new file mode 100644 index 0000000..b12d14b --- /dev/null +++ b/app/Domain/Notifications/Channels.php @@ -0,0 +1,11 @@ + $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; + } +} diff --git a/app/Domain/Notifications/KeyHasBeenTakenNotification.php b/app/Domain/Notifications/KeyHasBeenTakenNotification.php new file mode 100644 index 0000000..71e8b7b --- /dev/null +++ b/app/Domain/Notifications/KeyHasBeenTakenNotification.php @@ -0,0 +1,42 @@ + $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; + } +} diff --git a/app/Domain/Notifications/Notifiable.php b/app/Domain/Notifications/Notifiable.php new file mode 100644 index 0000000..99fef2f --- /dev/null +++ b/app/Domain/Notifications/Notifiable.php @@ -0,0 +1,10 @@ + $this->vacationRequest->id]); + + return implode("\n", [ + $this->buildDescription(), + "<${url}|Zobacz szczegóły>", + ]); } /** @@ -80,18 +90,16 @@ class VacationRequestCreatedNotification extends Notification protected function buildDescription(): string { $name = $this->vacationRequest->name; - $appName = config("app.name"); 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, - "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, - "appName" => $appName, "creator" => $this->vacationRequest->creator->profile->full_name, ]); } diff --git a/app/Domain/Notifications/VacationRequestStatusChangedNotification.php b/app/Domain/Notifications/VacationRequestStatusChangedNotification.php index 11594a1..746e3a0 100644 --- a/app/Domain/Notifications/VacationRequestStatusChangedNotification.php +++ b/app/Domain/Notifications/VacationRequestStatusChangedNotification.php @@ -22,7 +22,17 @@ class VacationRequestStatusChangedNotification extends Notification 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 { $user = $this->user->profile->first_name; - $title = $this->vacationRequest->name; $type = $this->vacationRequest->type->label(); - $status = $this->vacationRequest->state->label(); $from = $this->vacationRequest->from->toDisplayString(); $to = $this->vacationRequest->to->toDisplayString(); $days = $this->vacationRequest->vacations()->count(); - $requester = $this->vacationRequest->user->profile->full_name; return (new MailMessage()) ->greeting(__("Hi :user!", [ "user" => $user, ])) - ->subject(__("Vacation request :title has been :status", [ - "title" => $title, - "status" => $status, - ])) - ->line(__("The vacation request :title from user :requester has been :status.", [ - "title" => $title, - "requester" => $requester, - "status" => $status, - ])) + ->subject($this->buildSubject()) + ->line($this->buildDescription()) ->line(__("Vacation type: :type", [ "type" => $type, ])) @@ -74,4 +74,21 @@ class VacationRequestStatusChangedNotification extends Notification ])) ->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(), + ]); + } } diff --git a/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php b/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php index 109eef9..63ea770 100644 --- a/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php +++ b/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php @@ -23,7 +23,17 @@ class VacationRequestWaitsForApprovalNotification extends Notification 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 ]); } } - diff --git a/app/Domain/PolishHolidaysRetriever.php b/app/Domain/PolishHolidaysRetriever.php index db574a4..f8709d3 100644 --- a/app/Domain/PolishHolidaysRetriever.php +++ b/app/Domain/PolishHolidaysRetriever.php @@ -26,7 +26,7 @@ class PolishHolidaysRetriever 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]), "date" => Carbon::createFromTimestamp($holiday->getTimestamp()), ])->values(); diff --git a/app/Domain/TimesheetExport.php b/app/Domain/TimesheetExport.php index 8d764d0..47c258d 100644 --- a/app/Domain/TimesheetExport.php +++ b/app/Domain/TimesheetExport.php @@ -18,7 +18,7 @@ class TimesheetExport implements WithMultipleSheets public function sheets(): array { 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(); } diff --git a/app/Domain/TimesheetPerUserSheet.php b/app/Domain/TimesheetPerUserSheet.php index 8547a5e..891ca34 100644 --- a/app/Domain/TimesheetPerUserSheet.php +++ b/app/Domain/TimesheetPerUserSheet.php @@ -193,8 +193,8 @@ class TimesheetPerUserSheet implements WithTitle, WithHeadings, WithEvents, With ->get() ->groupBy( [ - fn(Vacation $vacation) => $vacation->date->toDateString(), - fn(Vacation $vacation) => $vacation->vacationRequest->type->value, + fn(Vacation $vacation): string => $vacation->date->toDateString(), + fn(Vacation $vacation): string => $vacation->vacationRequest->type->value, ], ); } diff --git a/app/Domain/UserVacationStatsRetriever.php b/app/Domain/UserVacationStatsRetriever.php index 7c11a29..42fdf50 100644 --- a/app/Domain/UserVacationStatsRetriever.php +++ b/app/Domain/UserVacationStatsRetriever.php @@ -42,8 +42,8 @@ class UserVacationStatsRetriever ->states(VacationRequestStatesRetriever::successStates()), ) ->get() - ->groupBy(fn(Vacation $vacation) => strtolower($vacation->date->englishMonth)) - ->map(fn(Collection $items) => $items->count()); + ->groupBy(fn(Vacation $vacation): string => strtolower($vacation->date->englishMonth)) + ->map(fn(Collection $items): int => $items->count()); } public function getPendingVacationDays(User $user, YearPeriod $yearPeriod): int @@ -107,13 +107,13 @@ class UserVacationStatsRetriever { $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 { $types = VacationType::all(); - return $types->filter(fn(VacationType $type) => !$this->configRetriever->hasLimit($type)); + return $types->filter(fn(VacationType $type): bool => !$this->configRetriever->hasLimit($type)); } } diff --git a/app/Domain/VacationDaysCalculator.php b/app/Domain/VacationDaysCalculator.php index 0e41a4a..2d3227e 100644 --- a/app/Domain/VacationDaysCalculator.php +++ b/app/Domain/VacationDaysCalculator.php @@ -11,9 +11,10 @@ use Toby\Eloquent\Models\YearPeriod; 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); + $yearPeriod = YearPeriod::findByYear($from->year); $holidays = $yearPeriod->holidays()->pluck("date"); $validDays = new Collection(); diff --git a/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php b/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php index 3fd5429..3b53892 100644 --- a/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php +++ b/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php @@ -29,7 +29,7 @@ class DoesNotExceedLimitRule implements VacationRequestRule $limit = $this->getUserVacationLimit($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); } @@ -64,6 +64,6 @@ class DoesNotExceedLimitRule implements VacationRequestRule { $types = VacationType::all(); - return $types->filter(fn(VacationType $type) => $this->configRetriever->hasLimit($type)); + return $types->filter(fn(VacationType $type): bool => $this->configRetriever->hasLimit($type)); } } diff --git a/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php b/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php index ae9f58b..4968d4d 100644 --- a/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php +++ b/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php @@ -16,7 +16,7 @@ class MinimumOneVacationDayRule implements VacationRequestRule public function check(VacationRequest $vacationRequest): bool { return $this->vacationDaysCalculator - ->calculateDays($vacationRequest->yearPeriod, $vacationRequest->from, $vacationRequest->to) + ->calculateDays($vacationRequest->from, $vacationRequest->to) ->isNotEmpty(); } diff --git a/app/Domain/Validation/Rules/VacationRequestRule.php b/app/Domain/Validation/Rules/VacationRequestRule.php index 07af8d2..f7e3c6d 100644 --- a/app/Domain/Validation/Rules/VacationRequestRule.php +++ b/app/Domain/Validation/Rules/VacationRequestRule.php @@ -9,5 +9,6 @@ use Toby\Eloquent\Models\VacationRequest; interface VacationRequestRule { public function check(VacationRequest $vacationRequest): bool; + public function errorMessage(): string; } diff --git a/app/Domain/Validation/Rules/VacationTypeCanBeSelected.php b/app/Domain/Validation/Rules/VacationTypeCanBeSelected.php index 2a7050f..a62d675 100644 --- a/app/Domain/Validation/Rules/VacationTypeCanBeSelected.php +++ b/app/Domain/Validation/Rules/VacationTypeCanBeSelected.php @@ -19,7 +19,7 @@ class VacationTypeCanBeSelected implements VacationRequestRule $employmentForm = $vacationRequest->user->profile->employment_form; $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); } diff --git a/app/Eloquent/Helpers/YearPeriodRetriever.php b/app/Eloquent/Helpers/YearPeriodRetriever.php index cf512cb..d248501 100644 --- a/app/Eloquent/Helpers/YearPeriodRetriever.php +++ b/app/Eloquent/Helpers/YearPeriodRetriever.php @@ -35,7 +35,7 @@ class YearPeriodRetriever $years = YearPeriod::all(); - $navigation = $years->map(fn(YearPeriod $yearPeriod) => $this->toNavigation($yearPeriod)); + $navigation = $years->map(fn(YearPeriod $yearPeriod): array => $this->toNavigation($yearPeriod)); return [ "current" => $this->toNavigation($current), diff --git a/app/Eloquent/Models/Holiday.php b/app/Eloquent/Models/Holiday.php index be8ae49..466065c 100644 --- a/app/Eloquent/Models/Holiday.php +++ b/app/Eloquent/Models/Holiday.php @@ -21,7 +21,6 @@ class Holiday extends Model use HasFactory; protected $guarded = []; - protected $casts = [ "date" => "date", ]; diff --git a/app/Eloquent/Models/Key.php b/app/Eloquent/Models/Key.php index cb7ee23..cb7fc6f 100644 --- a/app/Eloquent/Models/Key.php +++ b/app/Eloquent/Models/Key.php @@ -8,14 +8,17 @@ use Database\Factories\KeyFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Notifications\Notifiable; +use Toby\Domain\Notifications\Notifiable as NotifiableInterface; /** * @property int $id * @property User $user */ -class Key extends Model +class Key extends Model implements NotifiableInterface { use HasFactory; + use Notifiable; protected $guarded = []; @@ -24,6 +27,11 @@ class Key extends Model return $this->belongsTo(User::class); } + public function routeNotificationForSlack(): string + { + return config("services.slack.default_channel"); + } + protected static function newFactory(): KeyFactory { return KeyFactory::new(); diff --git a/app/Eloquent/Models/Profile.php b/app/Eloquent/Models/Profile.php index df237e9..a64b272 100644 --- a/app/Eloquent/Models/Profile.php +++ b/app/Eloquent/Models/Profile.php @@ -19,6 +19,7 @@ use Toby\Eloquent\Helpers\ColorGenerator; * @property string $position * @property EmploymentForm $employment_form * @property Carbon $employment_date + * @property Carbon $birthday */ class Profile extends Model { @@ -26,12 +27,11 @@ class Profile extends Model use HasAvatar; protected $primaryKey = "user_id"; - protected $guarded = []; - protected $casts = [ "employment_form" => EmploymentForm::class, "employment_date" => "date", + "birthday" => "date", ]; public function user(): BelongsTo diff --git a/app/Eloquent/Models/User.php b/app/Eloquent/Models/User.php index 4bf2891..dcd3941 100644 --- a/app/Eloquent/Models/User.php +++ b/app/Eloquent/Models/User.php @@ -15,6 +15,7 @@ use Illuminate\Notifications\Notifiable; use Illuminate\Support\Collection; use Toby\Domain\Enums\EmploymentForm; use Toby\Domain\Enums\Role; +use Toby\Domain\Notifications\Notifiable as NotifiableInterface; /** * @property int $id @@ -26,25 +27,22 @@ use Toby\Domain\Enums\Role; * @property Collection $vacationRequests * @property Collection $vacations */ -class User extends Authenticatable +class User extends Authenticatable implements NotifiableInterface { use HasFactory; use Notifiable; use SoftDeletes; protected $guarded = []; - protected $casts = [ "role" => Role::class, "last_active_at" => "datetime", "employment_form" => EmploymentForm::class, "employment_date" => "date", ]; - protected $hidden = [ "remember_token", ]; - protected $with = [ "profile", ]; @@ -102,7 +100,7 @@ class User extends Authenticatable ->where("email", "ILIKE", "%{$text}%") ->orWhereRelation( "profile", - fn(Builder $query) => $query + fn(Builder $query): Builder => $query ->where("first_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 { return UserFactory::new(); diff --git a/app/Eloquent/Models/VacationRequest.php b/app/Eloquent/Models/VacationRequest.php index 46bd084..97f94b7 100644 --- a/app/Eloquent/Models/VacationRequest.php +++ b/app/Eloquent/Models/VacationRequest.php @@ -41,7 +41,6 @@ class VacationRequest extends Model use HasStates; protected $guarded = []; - protected $casts = [ "type" => VacationType::class, "state" => VacationRequestState::class, diff --git a/app/Eloquent/Models/VacationRequestActivity.php b/app/Eloquent/Models/VacationRequestActivity.php index 942bb96..2064e9e 100644 --- a/app/Eloquent/Models/VacationRequestActivity.php +++ b/app/Eloquent/Models/VacationRequestActivity.php @@ -22,7 +22,6 @@ class VacationRequestActivity extends Model use HasFactory; protected $guarded = []; - protected $casts = [ "from" => VacationRequestState::class, "to" => VacationRequestState::class, diff --git a/app/Infrastructure/Console/Commands/SendDailySummaryToSlack.php b/app/Infrastructure/Console/Commands/SendDailySummaryToSlack.php new file mode 100644 index 0000000..1c2a5b6 --- /dev/null +++ b/app/Infrastructure/Console/Commands/SendDailySummaryToSlack.php @@ -0,0 +1,79 @@ +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"); + } +} diff --git a/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php b/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php index c204be1..3f3caa5 100644 --- a/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php +++ b/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php @@ -14,8 +14,8 @@ class CalculateVacationDaysController extends Controller { 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()); } } diff --git a/app/Infrastructure/Http/Controllers/Api/GetAvailableVacationTypesController.php b/app/Infrastructure/Http/Controllers/Api/GetAvailableVacationTypesController.php index 22a5f33..48a92a2 100644 --- a/app/Infrastructure/Http/Controllers/Api/GetAvailableVacationTypesController.php +++ b/app/Infrastructure/Http/Controllers/Api/GetAvailableVacationTypesController.php @@ -21,8 +21,8 @@ class GetAvailableVacationTypesController extends Controller $user = User::query()->find($request->get("user")); $types = VacationType::all() - ->filter(fn(VacationType $type) => $configRetriever->isAvailableFor($type, $user->profile->employment_form)) - ->map(fn(VacationType $type) => [ + ->filter(fn(VacationType $type): bool => $configRetriever->isAvailableFor($type, $user->profile->employment_form)) + ->map(fn(VacationType $type): array => [ "label" => $type->label(), "value" => $type->value, ]) diff --git a/app/Infrastructure/Http/Controllers/DashboardController.php b/app/Infrastructure/Http/Controllers/DashboardController.php index 33bf1aa..9f164a9 100644 --- a/app/Infrastructure/Http/Controllers/DashboardController.php +++ b/app/Infrastructure/Http/Controllers/DashboardController.php @@ -7,12 +7,11 @@ namespace Toby\Infrastructure\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Inertia\Response; -use Toby\Domain\Enums\VacationType; +use Toby\Domain\DailySummaryRetriever; use Toby\Domain\UserVacationStatsRetriever; use Toby\Domain\VacationRequestStatesRetriever; use Toby\Domain\VacationTypeConfigRetriever; use Toby\Eloquent\Helpers\YearPeriodRetriever; -use Toby\Eloquent\Models\Vacation; use Toby\Eloquent\Models\VacationRequest; use Toby\Infrastructure\Http\Resources\HolidayResource; use Toby\Infrastructure\Http\Resources\VacationRequestResource; @@ -25,24 +24,14 @@ class DashboardController extends Controller YearPeriodRetriever $yearPeriodRetriever, UserVacationStatsRetriever $vacationStatsRetriever, VacationTypeConfigRetriever $configRetriever, + DailySummaryRetriever $dailySummaryRetriever, ): Response { $user = $request->user(); $now = Carbon::now(); $yearPeriod = $yearPeriodRetriever->selected(); - $absences = Vacation::query() - ->with(["user", "vacationRequest"]) - ->whereDate("date", $now) - ->approved() - ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => $configRetriever->isVacation($type))) - ->get(); - - $remoteDays = Vacation::query() - ->with(["user", "vacationRequest"]) - ->whereDate("date", $now) - ->approved() - ->whereTypes(VacationType::all()->filter(fn(VacationType $type) => !$configRetriever->isVacation($type))) - ->get(); + $absences = $dailySummaryRetriever->getAbsences($now); + $remoteDays = $dailySummaryRetriever->getRemoteDays($now); if ($user->can("listAll", VacationRequest::class)) { $vacationRequests = $yearPeriod->vacationRequests() diff --git a/app/Infrastructure/Http/Controllers/KeysController.php b/app/Infrastructure/Http/Controllers/KeysController.php index 096e540..d71c177 100644 --- a/app/Infrastructure/Http/Controllers/KeysController.php +++ b/app/Infrastructure/Http/Controllers/KeysController.php @@ -8,6 +8,8 @@ use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Http\Request; use Inertia\Response; use Symfony\Component\HttpFoundation\RedirectResponse; +use Toby\Domain\Notifications\KeyHasBeenGivenNotification; +use Toby\Domain\Notifications\KeyHasBeenTakenNotification; use Toby\Eloquent\Models\Key; use Toby\Eloquent\Models\User; use Toby\Infrastructure\Http\Requests\GiveKeyRequest; @@ -60,6 +62,8 @@ class KeysController extends Controller $key->save(); + $key->notify(new KeyHasBeenTakenNotification($request->user(), $previousUser)); + return redirect() ->back() ->with("success", __("Key no :number has been taken from :user.", [ @@ -81,6 +85,8 @@ class KeysController extends Controller $key->save(); + $key->notify(new KeyHasBeenGivenNotification($request->user(), $recipient)); + return redirect() ->back() ->with("success", __("Key no :number has been given to :user.", [ diff --git a/app/Infrastructure/Http/Controllers/TimesheetController.php b/app/Infrastructure/Http/Controllers/TimesheetController.php index 16af5f6..2404889 100644 --- a/app/Infrastructure/Http/Controllers/TimesheetController.php +++ b/app/Infrastructure/Http/Controllers/TimesheetController.php @@ -35,8 +35,10 @@ class TimesheetController extends Controller $types = VacationType::all() ->filter( - fn(VacationType $type) => $configRetriever->isAvailableFor($type, EmploymentForm::EmploymentContract) - && $configRetriever->isVacation($type), + fn(VacationType $type): bool => $configRetriever->isAvailableFor( + $type, + EmploymentForm::EmploymentContract, + ) && $configRetriever->isVacation($type), ); $filename = "{$carbonMonth->translatedFormat("F Y")}.xlsx"; diff --git a/app/Infrastructure/Http/Controllers/VacationLimitController.php b/app/Infrastructure/Http/Controllers/VacationLimitController.php index 29c333e..31a7d80 100644 --- a/app/Infrastructure/Http/Controllers/VacationLimitController.php +++ b/app/Infrastructure/Http/Controllers/VacationLimitController.php @@ -30,7 +30,7 @@ class VacationLimitController extends Controller ->sortBy(fn(VacationLimit $limit): string => "{$limit->user->profile->last_name} {$limit->user->profile->first_name}") ->values(); - $limitsResource = $limits->map(fn(VacationLimit $limit) => [ + $limitsResource = $limits->map(fn(VacationLimit $limit): array => [ "id" => $limit->id, "user" => new UserResource($limit->user), "hasVacation" => $limit->hasVacation(), diff --git a/app/Infrastructure/Http/Kernel.php b/app/Infrastructure/Http/Kernel.php index 5c6a238..5b1e42f 100644 --- a/app/Infrastructure/Http/Kernel.php +++ b/app/Infrastructure/Http/Kernel.php @@ -40,7 +40,6 @@ class Kernel extends HttpKernel TrimStrings::class, ConvertEmptyStringsToNull::class, ]; - protected $middlewareGroups = [ "web" => [ EncryptCookies::class, @@ -58,7 +57,6 @@ class Kernel extends HttpKernel SubstituteBindings::class, ], ]; - protected $routeMiddleware = [ "auth" => Authenticate::class, "auth.basic" => AuthenticateWithBasicAuth::class, diff --git a/app/Infrastructure/Http/Middleware/HandleInertiaRequests.php b/app/Infrastructure/Http/Middleware/HandleInertiaRequests.php index 7344b7f..15cb0dd 100644 --- a/app/Infrastructure/Http/Middleware/HandleInertiaRequests.php +++ b/app/Infrastructure/Http/Middleware/HandleInertiaRequests.php @@ -32,7 +32,7 @@ class HandleInertiaRequests extends Middleware { $user = $request->user(); - return fn() => [ + return fn(): array => [ "user" => $user ? new UserResource($user) : null, "can" => [ "manageVacationLimits" => $user ? $user->can("manageVacationLimits") : false, @@ -45,7 +45,7 @@ class HandleInertiaRequests extends Middleware protected function getFlashData(Request $request): Closure { - return fn() => [ + return fn(): array => [ "success" => $request->session()->get("success"), "error" => $request->session()->get("error"), "info" => $request->session()->get("info"), diff --git a/app/Infrastructure/Http/Requests/UserRequest.php b/app/Infrastructure/Http/Requests/UserRequest.php index d3f094f..8b74657 100644 --- a/app/Infrastructure/Http/Requests/UserRequest.php +++ b/app/Infrastructure/Http/Requests/UserRequest.php @@ -22,6 +22,8 @@ class UserRequest extends FormRequest "position" => ["required"], "employmentForm" => ["required", new Enum(EmploymentForm::class)], "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"), "employment_form" => $this->get("employmentForm"), "employment_date" => $this->get("employmentDate"), + "birthday" => $this->get("birthday"), + "slack_id" => $this->get("slackId"), ]; } } diff --git a/app/Infrastructure/Http/Resources/UserFormDataResource.php b/app/Infrastructure/Http/Resources/UserFormDataResource.php index 219a2c9..83fd4e9 100644 --- a/app/Infrastructure/Http/Resources/UserFormDataResource.php +++ b/app/Infrastructure/Http/Resources/UserFormDataResource.php @@ -21,6 +21,8 @@ class UserFormDataResource extends JsonResource "position" => $this->profile->position, "employmentForm" => $this->profile->employment_form, "employmentDate" => $this->profile->employment_date->toDateString(), + "birthday" => $this->profile->birthday?->toDateString(), + "slackId" => $this->profile->slack_id, ]; } } diff --git a/app/Infrastructure/Slack/Channels/SlackApiChannel.php b/app/Infrastructure/Slack/Channels/SlackApiChannel.php new file mode 100644 index 0000000..d790555 --- /dev/null +++ b/app/Infrastructure/Slack/Channels/SlackApiChannel.php @@ -0,0 +1,36 @@ +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"); + } +} diff --git a/app/Infrastructure/Slack/Controller.php b/app/Infrastructure/Slack/Controller.php new file mode 100644 index 0000000..a3467bb --- /dev/null +++ b/app/Infrastructure/Slack/Controller.php @@ -0,0 +1,56 @@ +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()); + } +} diff --git a/app/Infrastructure/Slack/Elements/AbsencesAttachment.php b/app/Infrastructure/Slack/Elements/AbsencesAttachment.php new file mode 100644 index 0000000..3f34fac --- /dev/null +++ b/app/Infrastructure/Slack/Elements/AbsencesAttachment.php @@ -0,0 +1,22 @@ +setTitle("Nieobecności :palm_tree:") + ->setColor("#eab308") + ->setItems($absences->map(fn(Vacation $vacation): string => $vacation->user->profile->full_name)) + ->setEmptyText("Wszyscy dzisiaj pracują :muscle:"); + } +} diff --git a/app/Infrastructure/Slack/Elements/Attachment.php b/app/Infrastructure/Slack/Elements/Attachment.php new file mode 100644 index 0000000..9b223ec --- /dev/null +++ b/app/Infrastructure/Slack/Elements/Attachment.php @@ -0,0 +1,12 @@ +setTitle("Urodziny :birthday:") + ->setColor("#3c5f97") + ->setItems($birthdays->map(fn(User $user): string => $user->profile->full_name)) + ->setEmptyText("Dzisiaj nikt nie ma urodzin :cry:"); + } +} diff --git a/app/Infrastructure/Slack/Elements/KeysAttachment.php b/app/Infrastructure/Slack/Elements/KeysAttachment.php new file mode 100644 index 0000000..80819d3 --- /dev/null +++ b/app/Infrastructure/Slack/Elements/KeysAttachment.php @@ -0,0 +1,21 @@ +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"); + } +} diff --git a/app/Infrastructure/Slack/Elements/ListAttachment.php b/app/Infrastructure/Slack/Elements/ListAttachment.php new file mode 100644 index 0000000..3e3dfab --- /dev/null +++ b/app/Infrastructure/Slack/Elements/ListAttachment.php @@ -0,0 +1,36 @@ +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, + ]); + } +} diff --git a/app/Infrastructure/Slack/Elements/RemotesAttachment.php b/app/Infrastructure/Slack/Elements/RemotesAttachment.php new file mode 100644 index 0000000..2f39ad4 --- /dev/null +++ b/app/Infrastructure/Slack/Elements/RemotesAttachment.php @@ -0,0 +1,22 @@ +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:"); + } +} diff --git a/app/Infrastructure/Slack/Exceptions/UserNotFoundException.php b/app/Infrastructure/Slack/Exceptions/UserNotFoundException.php new file mode 100644 index 0000000..94a3948 --- /dev/null +++ b/app/Infrastructure/Slack/Exceptions/UserNotFoundException.php @@ -0,0 +1,11 @@ +findAvailableHandlers(); + $attachmentFields = $this->mapHandlersToAttachments($handlers); + + return $this->respondToSlack(":x: Nie rozpoznaję polecenia. Lista wszystkich poleceń:") + ->withAttachment( + Attachment::create() + ->setColor("danger") + ->useMarkdown() + ->setFields($attachmentFields), + ); + } +} diff --git a/app/Infrastructure/Slack/Handlers/DailySummary.php b/app/Infrastructure/Slack/Handlers/DailySummary.php new file mode 100644 index 0000000..5a941ee --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/DailySummary.php @@ -0,0 +1,36 @@ +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()); + } +} diff --git a/app/Infrastructure/Slack/Handlers/GiveKeysTo.php b/app/Infrastructure/Slack/Handlers/GiveKeysTo.php new file mode 100644 index 0000000..7925844 --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/GiveKeysTo.php @@ -0,0 +1,71 @@ + $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", + ]; + } +} diff --git a/app/Infrastructure/Slack/Handlers/Help.php b/app/Infrastructure/Slack/Handlers/Help.php new file mode 100644 index 0000000..e5e7ca2 --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/Help.php @@ -0,0 +1,33 @@ +findAvailableHandlers(); + + $attachmentFields = $this->mapHandlersToAttachments($handlers); + + return $this->respondToSlack("Dostępne polecenia:") + ->withAttachment( + Attachment::create() + ->setColor("good") + ->useMarkdown() + ->setFields($attachmentFields), + ); + } +} diff --git a/app/Infrastructure/Slack/Handlers/HomeOffice.php b/app/Infrastructure/Slack/Handlers/HomeOffice.php new file mode 100644 index 0000000..7674539 --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/HomeOffice.php @@ -0,0 +1,45 @@ +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); + } +} diff --git a/app/Infrastructure/Slack/Handlers/KeyList.php b/app/Infrastructure/Slack/Handlers/KeyList.php new file mode 100644 index 0000000..87ef123 --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/KeyList.php @@ -0,0 +1,26 @@ +orderBy("id") + ->get(); + + return $this->respondToSlack("Lista kluczy :key:") + ->withAttachment(new KeysAttachment($keys)); + } +} diff --git a/app/Infrastructure/Slack/Handlers/SignatureHandler.php b/app/Infrastructure/Slack/Handlers/SignatureHandler.php new file mode 100644 index 0000000..56af5da --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/SignatureHandler.php @@ -0,0 +1,26 @@ +getArguments(), $this->getRules(), $this->getMessages()); + } + + protected function getRules(): array + { + return []; + } + + protected function getMessages(): array + { + return []; + } +} diff --git a/app/Infrastructure/Slack/Handlers/TakeKeysFrom.php b/app/Infrastructure/Slack/Handlers/TakeKeysFrom.php new file mode 100644 index 0000000..5d89eed --- /dev/null +++ b/app/Infrastructure/Slack/Handlers/TakeKeysFrom.php @@ -0,0 +1,70 @@ + $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", + ]; + } +} diff --git a/app/Infrastructure/Slack/Rules/SlackUserExistsRule.php b/app/Infrastructure/Slack/Rules/SlackUserExistsRule.php new file mode 100644 index 0000000..500c295 --- /dev/null +++ b/app/Infrastructure/Slack/Rules/SlackUserExistsRule.php @@ -0,0 +1,24 @@ +where("slack_id", $slackId)->exists(); + } + + public function message(): string + { + return "Użytkownik :input nie istnieje w tobym"; + } +} diff --git a/app/Infrastructure/Slack/Traits/FindsUserBySlackId.php b/app/Infrastructure/Slack/Traits/FindsUserBySlackId.php new file mode 100644 index 0000000..b3f1bae --- /dev/null +++ b/app/Infrastructure/Slack/Traits/FindsUserBySlackId.php @@ -0,0 +1,43 @@ +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, "<@", "|"); + } +} diff --git a/app/Infrastructure/Slack/Traits/ListsHandlers.php b/app/Infrastructure/Slack/Traits/ListsHandlers.php new file mode 100644 index 0000000..0ec2d1f --- /dev/null +++ b/app/Infrastructure/Slack/Traits/ListsHandlers.php @@ -0,0 +1,46 @@ +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(); + } +} diff --git a/composer.json b/composer.json index 82145dd..36d9d98 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,8 @@ "maatwebsite/excel": "^3.1", "rackbeat/laravel-ui-avatars": "^1.0", "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": { "blumilksoftware/codestyle": "^1.0.0", @@ -61,7 +62,8 @@ "extra": { "laravel": { "dont-discover": [ - "laravel/telescope" + "laravel/telescope", + "spatie/laravel-slack-slash-command" ] } }, diff --git a/composer.lock b/composer.lock index 8dd0196..498daa4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "414a1fc13e0731e59605248bd4e39de6", + "content-hash": "24a1b3a5dd7c4d4f50d521dda4b6654e", "packages": [ { "name": "asm89/stack-cors", @@ -815,23 +815,23 @@ }, { "name": "firebase/php-jwt", - "version": "v5.5.1", + "version": "v6.1.2", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "83b609028194aa042ea33b5af2d41a7427de80e6" + "reference": "c297139da7c6873dbd67cbd1093f09ec0bbd0c50" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/83b609028194aa042ea33b5af2d41a7427de80e6", - "reference": "83b609028194aa042ea33b5af2d41a7427de80e6", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/c297139da7c6873dbd67cbd1093f09ec0bbd0c50", + "reference": "c297139da7c6873dbd67cbd1093f09ec0bbd0c50", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.1||^8.0" }, "require-dev": { - "phpunit/phpunit": ">=4.8 <=9" + "phpunit/phpunit": "^7.5||9.5" }, "suggest": { "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" @@ -866,9 +866,9 @@ ], "support": { "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", @@ -1022,16 +1022,16 @@ }, { "name": "google/apiclient", - "version": "v2.12.2", + "version": "v2.12.4", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "a18b0e1ef5618523c607c01a41ec137c7f9af3b1" + "reference": "702eed9ae7022ba20dc7118c8161060cb50ee9f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/a18b0e1ef5618523c607c01a41ec137c7f9af3b1", - "reference": "a18b0e1ef5618523c607c01a41ec137c7f9af3b1", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/702eed9ae7022ba20dc7118c8161060cb50ee9f8", + "reference": "702eed9ae7022ba20dc7118c8161060cb50ee9f8", "shasum": "" }, "require": { @@ -1087,22 +1087,22 @@ ], "support": { "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", - "version": "v0.242.0", + "version": "v0.246.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "73d4c0ed4b241e7396699e0ee1d1cdebabac25e8" + "reference": "33aef1ccce34799a1124c39951fed8ad0b16aced" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/73d4c0ed4b241e7396699e0ee1d1cdebabac25e8", - "reference": "73d4c0ed4b241e7396699e0ee1d1cdebabac25e8", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/33aef1ccce34799a1124c39951fed8ad0b16aced", + "reference": "33aef1ccce34799a1124c39951fed8ad0b16aced", "shasum": "" }, "require": { @@ -1131,30 +1131,30 @@ ], "support": { "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", - "version": "v1.19.0", + "version": "v1.21.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "31e5d24d5fa0eaf6adc7e596292dc4732f4b60c5" + "reference": "73392bad2eb6852eea9084b6bbdec752515cb849" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/31e5d24d5fa0eaf6adc7e596292dc4732f4b60c5", - "reference": "31e5d24d5fa0eaf6adc7e596292dc4732f4b60c5", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/73392bad2eb6852eea9084b6bbdec752515cb849", + "reference": "73392bad2eb6852eea9084b6bbdec752515cb849", "shasum": "" }, "require": { - "firebase/php-jwt": "~5.0", + "firebase/php-jwt": "^5.5||^6.0", "guzzlehttp/guzzle": "^6.2.1|^7.0", "guzzlehttp/psr7": "^1.7|^2.0", - "php": ">=5.6", - "psr/cache": "^1.0|^2.0", + "php": "^7.1||^8.0", + "psr/cache": "^1.0|^2.0|^3.0", "psr/http-message": "^1.0" }, "require-dev": { @@ -1162,7 +1162,7 @@ "kelvinmo/simplejwt": "^0.2.5|^0.5.1", "phpseclib/phpseclib": "^2.0.31", "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^5.7||^8.5.13", + "phpunit/phpunit": "^7.5||^8.5", "sebastian/comparator": ">=1.2.3", "squizlabs/php_codesniffer": "^3.5" }, @@ -1189,9 +1189,9 @@ "support": { "docs": "https://googleapis.github.io/google-auth-library-php/main/", "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", @@ -1733,16 +1733,16 @@ }, { "name": "laravel/framework", - "version": "v9.7.0", + "version": "v9.9.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "54c9696ee3e558ab29317ed6e0cb16bb9db5aad4" + "reference": "4d5a07640891b772188d7737348886a0222737d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/54c9696ee3e558ab29317ed6e0cb16bb9db5aad4", - "reference": "54c9696ee3e558ab29317ed6e0cb16bb9db5aad4", + "url": "https://api.github.com/repos/laravel/framework/zipball/4d5a07640891b772188d7737348886a0222737d8", + "reference": "4d5a07640891b772188d7737348886a0222737d8", "shasum": "" }, "require": { @@ -1908,20 +1908,76 @@ "issues": "https://github.com/laravel/framework/issues", "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", - "version": "v2.15.0", + "name": "laravel/helpers", + "version": "v1.5.0", "source": { "type": "git", - "url": "https://github.com/laravel/sanctum.git", - "reference": "5be160413b6f37dcf8758663edeab12d0e806f56" + "url": "https://github.com/laravel/helpers.git", + "reference": "c28b0ccd799d58564c41a62395ac9511a1e72931" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/5be160413b6f37dcf8758663edeab12d0e806f56", - "reference": "5be160413b6f37dcf8758663edeab12d0e806f56", + "url": "https://api.github.com/repos/laravel/helpers/zipball/c28b0ccd799d58564c41a62395ac9511a1e72931", + "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": "" }, "require": { @@ -1973,7 +2029,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "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", @@ -2105,16 +2161,16 @@ }, { "name": "laravel/telescope", - "version": "v4.8.2", + "version": "v4.8.3", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "88e3ded3e1fc301a82403820b2f68ec5a9e092e3" + "reference": "bb23d58161032c8745d38348452afcbcd8adfc78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/88e3ded3e1fc301a82403820b2f68ec5a9e092e3", - "reference": "88e3ded3e1fc301a82403820b2f68ec5a9e092e3", + "url": "https://api.github.com/repos/laravel/telescope/zipball/bb23d58161032c8745d38348452afcbcd8adfc78", + "reference": "bb23d58161032c8745d38348452afcbcd8adfc78", "shasum": "" }, "require": { @@ -2167,9 +2223,9 @@ ], "support": { "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", @@ -2404,16 +2460,16 @@ }, { "name": "league/commonmark", - "version": "2.2.3", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "47b015bc4e50fd4438c1ffef6139a1fb65d2ab71" + "reference": "32a49eb2b38fe5e5c417ab748a45d0beaab97955" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/47b015bc4e50fd4438c1ffef6139a1fb65d2ab71", - "reference": "47b015bc4e50fd4438c1ffef6139a1fb65d2ab71", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/32a49eb2b38fe5e5c417ab748a45d0beaab97955", + "reference": "32a49eb2b38fe5e5c417ab748a45d0beaab97955", "shasum": "" }, "require": { @@ -2422,17 +2478,19 @@ "php": "^7.4 || ^8.0", "psr/event-dispatcher": "^1.0", "symfony/deprecation-contracts": "^2.1 || ^3.0", - "symfony/polyfill-php80": "^1.15" + "symfony/polyfill-php80": "^1.16" }, "require-dev": { "cebe/markdown": "^1.0", "commonmark/cmark": "0.30.0", "commonmark/commonmark.js": "0.30.0", "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", "erusev/parsedown": "^1.0", "ext-json": "*", "github/gfm": "0.29.0", "michelf/php-markdown": "^1.4", + "nyholm/psr7": "^1.5", "phpstan/phpstan": "^0.12.88 || ^1.0.0", "phpunit/phpunit": "^9.5.5", "scrutinizer/ocular": "^1.8.1", @@ -2447,7 +2505,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.3-dev" + "dev-main": "2.4-dev" } }, "autoload": { @@ -2504,7 +2562,7 @@ "type": "tidelift" } ], - "time": "2022-02-26T21:24:45+00:00" + "time": "2022-04-07T22:37:05+00:00" }, { "name": "league/config", @@ -2590,16 +2648,16 @@ }, { "name": "league/flysystem", - "version": "3.0.14", + "version": "3.0.17", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "46a5450352540e89cb8e7eb20c58b5b4aae481f6" + "reference": "29eb78cac0be0c22237c5e0f6f98234d97037d79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/46a5450352540e89cb8e7eb20c58b5b4aae481f6", - "reference": "46a5450352540e89cb8e7eb20c58b5b4aae481f6", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/29eb78cac0be0c22237c5e0f6f98234d97037d79", + "reference": "29eb78cac0be0c22237c5e0f6f98234d97037d79", "shasum": "" }, "require": { @@ -2660,7 +2718,7 @@ ], "support": { "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": [ { @@ -2676,20 +2734,20 @@ "type": "tidelift" } ], - "time": "2022-04-06T18:17:37+00:00" + "time": "2022-04-14T14:57:13+00:00" }, { "name": "league/mime-type-detection", - "version": "1.9.0", + "version": "1.11.0", "source": { "type": "git", "url": "https://github.com/thephpleague/mime-type-detection.git", - "reference": "aa70e813a6ad3d1558fc927863d47309b4c23e69" + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/aa70e813a6ad3d1558fc927863d47309b4c23e69", - "reference": "aa70e813a6ad3d1558fc927863d47309b4c23e69", + "url": "https://api.github.com/repos/thephpleague/mime-type-detection/zipball/ff6248ea87a9f116e78edd6002e39e5128a0d4dd", + "reference": "ff6248ea87a9f116e78edd6002e39e5128a0d4dd", "shasum": "" }, "require": { @@ -2720,7 +2778,7 @@ "description": "Mime-type detection for Flysystem", "support": { "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": [ { @@ -2732,20 +2790,20 @@ "type": "tidelift" } ], - "time": "2021-11-21T11:48:40+00:00" + "time": "2022-04-17T13:12:02+00:00" }, { "name": "league/oauth1-client", - "version": "v1.10.0", + "version": "v1.10.1", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth1-client.git", - "reference": "88dd16b0cff68eb9167bfc849707d2c40ad91ddc" + "reference": "d6365b901b5c287dd41f143033315e2f777e1167" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/88dd16b0cff68eb9167bfc849707d2c40ad91ddc", - "reference": "88dd16b0cff68eb9167bfc849707d2c40ad91ddc", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/d6365b901b5c287dd41f143033315e2f777e1167", + "reference": "d6365b901b5c287dd41f143033315e2f777e1167", "shasum": "" }, "require": { @@ -2806,22 +2864,22 @@ ], "support": { "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", - "version": "3.1.38", + "version": "3.1.39", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "dff132ce4d30b19863f4e84de1613fca99604992" + "reference": "5165334de44c6f7788a5818a1d019aa71a43e092" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/dff132ce4d30b19863f4e84de1613fca99604992", - "reference": "dff132ce4d30b19863f4e84de1613fca99604992", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/5165334de44c6f7788a5818a1d019aa71a43e092", + "reference": "5165334de44c6f7788a5818a1d019aa71a43e092", "shasum": "" }, "require": { @@ -2874,7 +2932,7 @@ ], "support": { "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": [ { @@ -2886,7 +2944,7 @@ "type": "github" } ], - "time": "2022-03-24T16:00:29+00:00" + "time": "2022-04-23T11:44:18+00:00" }, { "name": "maennchen/zipstream-php", @@ -3118,16 +3176,16 @@ }, { "name": "monolog/monolog", - "version": "2.4.0", + "version": "2.5.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "d7fd7450628561ba697b7097d86db72662f54aef" + "reference": "4192345e260f1d51b365536199744b987e160edc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/d7fd7450628561ba697b7097d86db72662f54aef", - "reference": "d7fd7450628561ba697b7097d86db72662f54aef", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/4192345e260f1d51b365536199744b987e160edc", + "reference": "4192345e260f1d51b365536199744b987e160edc", "shasum": "" }, "require": { @@ -3201,7 +3259,7 @@ ], "support": { "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": [ { @@ -3213,7 +3271,7 @@ "type": "tidelift" } ], - "time": "2022-03-14T12:44:37+00:00" + "time": "2022-04-08T15:43:54+00:00" }, { "name": "myclabs/php-enum", @@ -3856,16 +3914,16 @@ }, { "name": "phpoffice/phpspreadsheet", - "version": "1.22.0", + "version": "1.23.0", "source": { "type": "git", "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", - "reference": "3a9e29b4f386a08a151a33578e80ef1747037a48" + "reference": "21e4cf62699eebf007db28775f7d1554e612ed9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/3a9e29b4f386a08a151a33578e80ef1747037a48", - "reference": "3a9e29b4f386a08a151a33578e80ef1747037a48", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/21e4cf62699eebf007db28775f7d1554e612ed9e", + "reference": "21e4cf62699eebf007db28775f7d1554e612ed9e", "shasum": "" }, "require": { @@ -3889,7 +3947,7 @@ "php": "^7.3 || ^8.0", "psr/http-client": "^1.0", "psr/http-factory": "^1.0", - "psr/simple-cache": "^1.0" + "psr/simple-cache": "^1.0 || ^2.0" }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "dev-master", @@ -3954,9 +4012,9 @@ ], "support": { "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", @@ -4140,16 +4198,16 @@ }, { "name": "psr/cache", - "version": "2.0.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/cache.git", - "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b" + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/cache/zipball/213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", - "reference": "213f9dbc5b9bfbc4f8db86d2838dc968752ce13b", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", "shasum": "" }, "require": { @@ -4183,9 +4241,9 @@ "psr-6" ], "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", @@ -4502,25 +4560,25 @@ }, { "name": "psr/simple-cache", - "version": "1.0.1", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", - "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/8707bf3cea6f710bf6ef05491234e3ab06f6432a", + "reference": "8707bf3cea6f710bf6ef05491234e3ab06f6432a", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=8.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -4535,7 +4593,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -4547,9 +4605,9 @@ "simple-cache" ], "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", @@ -5040,16 +5098,16 @@ }, { "name": "spatie/laravel-model-states", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-model-states.git", - "reference": "7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8" + "reference": "bfa12486558952eca4d6c81d4dd803b83f065297" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8", - "reference": "7b31a63c0bd8b33d7dc5e12e6b16d2535d9b31a8", + "url": "https://api.github.com/repos/spatie/laravel-model-states/zipball/bfa12486558952eca4d6c81d4dd803b83f065297", + "reference": "bfa12486558952eca4d6c81d4dd803b83f065297", "shasum": "" }, "require": { @@ -5098,7 +5156,7 @@ "state" ], "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": [ { @@ -5110,7 +5168,7 @@ "type": "github" } ], - "time": "2022-03-03T11:22:16+00:00" + "time": "2022-04-21T12:09:37+00:00" }, { "name": "spatie/laravel-package-tools", @@ -5171,6 +5229,71 @@ ], "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", "version": "v6.0.7", @@ -7529,21 +7652,21 @@ "packages-dev": [ { "name": "blumilksoftware/codestyle", - "version": "v1.0.1", + "version": "v1.1.0", "source": { "type": "git", "url": "https://github.com/blumilksoftware/codestyle.git", - "reference": "e86ebcd5175bc435d9c8d4f83bf201a6f5a9fc60" + "reference": "3f2248859562afe7d7b2b16aa25e83dc73236fcc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/e86ebcd5175bc435d9c8d4f83bf201a6f5a9fc60", - "reference": "e86ebcd5175bc435d9c8d4f83bf201a6f5a9fc60", + "url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/3f2248859562afe7d7b2b16aa25e83dc73236fcc", + "reference": "3f2248859562afe7d7b2b16aa25e83dc73236fcc", "shasum": "" }, "require": { "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" }, "require-dev": { @@ -7551,6 +7674,9 @@ "phpunit/phpunit": "^9.5", "symfony/console": "^6.0" }, + "bin": [ + "bin/codestyle" + ], "type": "library", "autoload": { "psr-4": { @@ -7570,9 +7696,9 @@ "description": "Blumilk codestyle configurator", "support": { "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", @@ -8262,16 +8388,16 @@ }, { "name": "laravel/dusk", - "version": "v6.22.3", + "version": "v6.23.0", "source": { "type": "git", "url": "https://github.com/laravel/dusk.git", - "reference": "f42844d5a7eace45d199d276bb2bc23fec788256" + "reference": "98901d49176977c96330fd8c2ca5460eee50a246" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/dusk/zipball/f42844d5a7eace45d199d276bb2bc23fec788256", - "reference": "f42844d5a7eace45d199d276bb2bc23fec788256", + "url": "https://api.github.com/repos/laravel/dusk/zipball/98901d49176977c96330fd8c2ca5460eee50a246", + "reference": "98901d49176977c96330fd8c2ca5460eee50a246", "shasum": "" }, "require": { @@ -8329,9 +8455,9 @@ ], "support": { "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", @@ -10519,16 +10645,16 @@ }, { "name": "spatie/ignition", - "version": "1.2.7", + "version": "1.2.9", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "2f059cf42b48f7c522efbba1c05ad59fc2c1a3f2" + "reference": "db25202fab2d5c14613b8914a1bb374998bbf870" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/2f059cf42b48f7c522efbba1c05ad59fc2c1a3f2", - "reference": "2f059cf42b48f7c522efbba1c05ad59fc2c1a3f2", + "url": "https://api.github.com/repos/spatie/ignition/zipball/db25202fab2d5c14613b8914a1bb374998bbf870", + "reference": "db25202fab2d5c14613b8914a1bb374998bbf870", "shasum": "" }, "require": { @@ -10585,20 +10711,20 @@ "type": "github" } ], - "time": "2022-03-29T08:48:34+00:00" + "time": "2022-04-23T20:37:21+00:00" }, { "name": "spatie/laravel-ignition", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "2b54c8c66f2d280f25e15064ebe3d5e3eda19820" + "reference": "924d1ae878874ad0bb49f63b69a9af759a34ee78" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2b54c8c66f2d280f25e15064ebe3d5e3eda19820", - "reference": "2b54c8c66f2d280f25e15064ebe3d5e3eda19820", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/924d1ae878874ad0bb49f63b69a9af759a34ee78", + "reference": "924d1ae878874ad0bb49f63b69a9af759a34ee78", "shasum": "" }, "require": { @@ -10675,7 +10801,7 @@ "type": "github" } ], - "time": "2022-04-01T21:01:58+00:00" + "time": "2022-04-14T18:04:51+00:00" }, { "name": "symfony/filesystem", @@ -10931,5 +11057,5 @@ "ext-redis": "*" }, "platform-dev": [], - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.2.0" } diff --git a/config/app.php b/config/app.php index a5d12a9..6ef5b69 100644 --- a/config/app.php +++ b/config/app.php @@ -37,12 +37,12 @@ return [ Illuminate\Translation\TranslationServiceProvider::class, Illuminate\Validation\ValidationServiceProvider::class, Illuminate\View\ViewServiceProvider::class, + Barryvdh\DomPDF\ServiceProvider::class, Toby\Architecture\Providers\AppServiceProvider::class, Toby\Architecture\Providers\AuthServiceProvider::class, Toby\Architecture\Providers\EventServiceProvider::class, Toby\Architecture\Providers\RouteServiceProvider::class, Toby\Architecture\Providers\TelescopeServiceProvider::class, Toby\Architecture\Providers\ObserverServiceProvider::class, - Barryvdh\DomPDF\ServiceProvider::class, ], ]; diff --git a/config/laravel-slack-slash-command.php b/config/laravel-slack-slash-command.php new file mode 100644 index 0000000..b4f8cfb --- /dev/null +++ b/config/laravel-slack-slash-command.php @@ -0,0 +1,24 @@ + env("SLACK_SIGNING_SECRET"), + "handlers" => [ + TakeKeysFrom::class, + GiveKeysTo::class, + KeyList::class, + HomeOffice::class, + DailySummary::class, + Help::class, + CatchAll::class, + ], +]; diff --git a/config/services.php b/config/services.php index e535c9e..8940ddd 100644 --- a/config/services.php +++ b/config/services.php @@ -8,4 +8,9 @@ return [ "client_secret" => env("GOOGLE_CLIENT_SECRET"), "redirect" => env("GOOGLE_REDIRECT"), ], + "slack" => [ + "url" => "https://slack.com/api", + "client_token" => env("SLACK_CLIENT_TOKEN"), + "default_channel" => env("SLACK_DEFAULT_CHANNEL"), + ], ]; diff --git a/database/factories/ProfileFactory.php b/database/factories/ProfileFactory.php index 706df10..ba96c86 100644 --- a/database/factories/ProfileFactory.php +++ b/database/factories/ProfileFactory.php @@ -23,6 +23,7 @@ class ProfileFactory extends Factory "employment_form" => $this->faker->randomElement(EmploymentForm::cases()), "position" => $this->faker->jobTitle(), "employment_date" => Carbon::createFromInterface($this->faker->dateTimeBetween("2020-10-27"))->toDateString(), + "birthday" => Carbon::createFromInterface($this->faker->dateTimeBetween("1970-01-01", "1998-01-01"))->toDateString(), ]; } } diff --git a/database/migrations/2022_04_21_101027_add_slack_id_and_birthday_columns_in_profiles_table.php b/database/migrations/2022_04_21_101027_add_slack_id_and_birthday_columns_in_profiles_table.php new file mode 100644 index 0000000..893b4ef --- /dev/null +++ b/database/migrations/2022_04_21_101027_add_slack_id_and_birthday_columns_in_profiles_table.php @@ -0,0 +1,25 @@ +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"); + }); + } +}; diff --git a/resources/js/Composables/vacationTypeInfo.js b/resources/js/Composables/vacationTypeInfo.js index 3ed7591..65ec983 100644 --- a/resources/js/Composables/vacationTypeInfo.js +++ b/resources/js/Composables/vacationTypeInfo.js @@ -8,7 +8,7 @@ import HandHeartOutlineIcon from 'vue-material-design-icons/HandHeartOutline.vue import CalendarCheckIcon from 'vue-material-design-icons/CalendarCheck.vue' import MedicalBagIcon from 'vue-material-design-icons/MedicalBag.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 = [ { @@ -43,8 +43,8 @@ const types = [ text: 'Urlop szkoleniowy', value: 'training_vacation', icon: HumanMaleBoardIcon, - color: 'text-blumilk-500', - border: 'border-blumilk-500', + color: 'text-indigo-500', + border: 'border-indigo-500', }, { text: 'Urlop bezpłatny', @@ -84,9 +84,9 @@ const types = [ { text: 'Praca zdalna', value: 'home_office', - icon: LaptopIcon, - color: 'text-fuchsia-500', - border: 'border-fuchsia-500', + icon: HomeCityIcon, + color: 'text-blumilk-500', + border: 'border-blumilk-500', }, ] diff --git a/resources/js/Pages/Users/Create.vue b/resources/js/Pages/Users/Create.vue index 4959b47..5caadf9 100644 --- a/resources/js/Pages/Users/Create.vue +++ b/resources/js/Pages/Users/Create.vue @@ -234,6 +234,52 @@

+
+ +
+ +

+ {{ form.errors.slackId }} +

+
+
+
+ +
+ +

+ {{ form.errors.birthday }} +

+
+
+
+ +
+ +

+ {{ form.errors.birthday }} +

+
+
+
+ +
+ +

+ {{ form.errors.slackId }} +

+
+
form.value === props.user.employmentForm), employmentDate: props.user.employmentDate, + birthday: props.user.birthday, + slackId: props.user.slackId, }) function editUser() { diff --git a/resources/lang/pl.json b/resources/lang/pl.json index d792d41..8485773 100644 --- a/resources/lang/pl.json +++ b/resources/lang/pl.json @@ -23,11 +23,11 @@ "cancelled": "anulowany", "rejected": "odrzucony", "approved": "zatwierdzony", - "You have pending vacation request in this range.": "Masz oczekujący wniosek urlopowy w tym zakresie dat.", - "You have approved vacation request in this range.": "Masz zaakceptowany wniosek urlopowy w tym zakresie dat.", + "You have pending vacation request in this range.": "Masz oczekujący wniosek w tym zakresie dat.", + "You have approved vacation request in this range.": "Masz zaakceptowany wniosek w tym zakresie dat.", "Vacation limit has been exceeded.": "Limit urlopu został przekroczony.", "Vacation needs minimum one day.": "Urlop musi być co najmniej na jeden dzień.", - "The vacation request cannot be created at the turn of the year.": "Wniosek urlopowy nie może zostać złożony na przełomie roku.", + "The vacation request cannot be created at the turn of the year.": "Wniosek nie może zostać złożony na przełomie roku.", "User has been created.": "Użytkownik został utworzony.", "User has been updated.": "Użytkownik został zaktualizowany.", "User has been deleted.": "Użytkownik został usunięty.", @@ -37,11 +37,11 @@ "Holiday has been deleted.": "Dzień wolny został usunięty.", "Selected year period has been changed.": "Wybrany rok został zmieniony.", "Vacation limits have been updated.": "Limity urlopów zostały zaktualizowane.", - "Vacation request has been created.": "Wniosek urlopowy został utworzony.", - "Vacation request has been accepted.": "Wniosek urlopowy został zaakceptowany.", - "Vacation request has been approved.": "Wniosek urlopowy został zatwierdzony.", - "Vacation request has been rejected.": "Wniosek urlopowy został odrzucony.", - "Vacation request has been cancelled.": "Wniosek urlopowy został anulowany.", + "Vacation request has been created.": "Wniosek został utworzony.", + "Vacation request has been accepted.": "Wniosek został zaakceptowany.", + "Vacation request has been approved.": "Wniosek został zatwierdzony.", + "Vacation request has been rejected.": "Wniosek został odrzucony.", + "Vacation request has been cancelled.": "Wniosek został anulowany.", "Sum:": "Suma:", "Date": "Data", "Day of week": "Dzień tygodnia", @@ -56,7 +56,7 @@ "All rights reserved.": "Wszelkie prawa zastrzeżone", "Show vacation request": "Pokaż wniosek", "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", "From :from to :to (number of days: :days)": "Od :from do :to (liczba dni: :days)", "Click here for details": "Kliknij, aby zobaczyć szczegóły", @@ -67,9 +67,11 @@ "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.", "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 deleted.": "Klucz nr :number został usunięty.", "Key no :number has been taken from :user.": "Klucz nr :number został zabrany użytkownikowi :user.", - "Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user." + "Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user.", + ":sender gives key no :key to :recipient": ":sender przekazuje klucz nr :key :recipient", + ":recipient takes key no :key from :sender": ":recipient zabiera klucz nr :key :sender" } diff --git a/routes/api.php b/routes/api.php index d76094c..3220d19 100644 --- a/routes/api.php +++ b/routes/api.php @@ -7,6 +7,9 @@ use Toby\Infrastructure\Http\Controllers\Api\CalculateUserUnavailableDaysControl use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController; use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController; 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::post("vacation/calculate-days", CalculateVacationDaysController::class); diff --git a/tests/Feature/KeyTest.php b/tests/Feature/KeyTest.php index e9c3ddc..2b1c329 100644 --- a/tests/Feature/KeyTest.php +++ b/tests/Feature/KeyTest.php @@ -5,6 +5,7 @@ declare(strict_types=1); namespace Tests\Feature; use Illuminate\Foundation\Testing\DatabaseMigrations; +use Illuminate\Support\Facades\Notification; use Inertia\Testing\AssertableInertia as Assert; use Tests\FeatureTestCase; use Toby\Eloquent\Models\Key; @@ -14,6 +15,13 @@ class KeyTest extends FeatureTestCase { use DatabaseMigrations; + protected function setUp(): void + { + parent::setUp(); + + Notification::fake(); + } + public function testUserCanSeeKeyList(): void { Key::factory()->count(10)->create(); diff --git a/tests/Unit/SendDailySummaryToSlackTest.php b/tests/Unit/SendDailySummaryToSlackTest.php new file mode 100644 index 0000000..93be6bf --- /dev/null +++ b/tests/Unit/SendDailySummaryToSlackTest.php @@ -0,0 +1,82 @@ +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); + } +} From 6b2556c1da6fbc61be1a14036dc5a409baef836f Mon Sep 17 00:00:00 2001 From: Adrian Hopek Date: Wed, 27 Apr 2022 15:26:55 +0200 Subject: [PATCH 2/9] #126 - vacation request reminders (#130) * #126 - vacation request reminders * #126 - fix workdays * #126 - changes * #126 - cs fix * #5 - bump codestyle * #126 - fix * #126 - fix * #126 - fix * #126 - fix * #126 - tests * #126 - fix * #126 - fix * #126 - fix seeders * #126 - fix * #126 - tests Co-authored-by: EwelinaLasowy --- .env.example | 5 + .../Actions/VacationRequest/CreateAction.php | 9 +- .../KeyHasBeenGivenNotification.php | 14 +- .../KeyHasBeenTakenNotification.php | 14 +- .../VacationRequestCreatedNotification.php | 37 ++--- ...cationRequestStatusChangedNotification.php | 9 +- ...ionRequestWaitsForApprovalNotification.php | 9 +- .../VacationRequestsSummaryNotification.php | 70 ++++++++++ .../Rules/DoesNotExceedLimitRule.php | 8 +- .../Rules/MinimumOneVacationDayRule.php | 6 +- ...sCalculator.php => WorkDaysCalculator.php} | 2 +- app/Eloquent/Models/VacationRequest.php | 8 ++ ...endVacationRequestSummariesToApprovers.php | 36 +++++ .../Api/CalculateVacationDaysController.php | 4 +- .../Slack/Channels/SlackApiChannel.php | 7 +- .../Slack/Elements/SlackMessage.php | 53 +++++++ .../Elements/VacationRequestsAttachment.php | 33 +++++ database/seeders/DatabaseSeeder.php | 5 +- database/seeders/DemoSeeder.php | 11 +- resources/js/Pages/VacationRequest/Show.vue | 2 +- routes/api.php | 4 +- .../Unit/SendVacationRequestSummariesTest.php | 130 ++++++++++++++++++ 22 files changed, 407 insertions(+), 69 deletions(-) create mode 100644 app/Domain/Notifications/VacationRequestsSummaryNotification.php rename app/Domain/{VacationDaysCalculator.php => WorkDaysCalculator.php} (97%) create mode 100644 app/Infrastructure/Console/Commands/SendVacationRequestSummariesToApprovers.php create mode 100644 app/Infrastructure/Slack/Elements/SlackMessage.php create mode 100644 app/Infrastructure/Slack/Elements/VacationRequestsAttachment.php create mode 100644 tests/Unit/SendVacationRequestSummariesTest.php diff --git a/.env.example b/.env.example index fe3a597..0689964 100644 --- a/.env.example +++ b/.env.example @@ -60,3 +60,8 @@ GOOGLE_CLIENT_SECRET= GOOGLE_REDIRECT=http://localhost/login/google/end GOOGLE_CALENDAR_ID= LOCAL_EMAIL_FOR_LOGIN_VIA_GOOGLE= + +SLACK_URL=https://slack.com/api +SLACK_CLIENT_TOKEN= +SLACK_SIGNING_SECRET= +SLACK_DEFAULT_CHANNEL="#general" diff --git a/app/Domain/Actions/VacationRequest/CreateAction.php b/app/Domain/Actions/VacationRequest/CreateAction.php index 1bb8a7a..b569954 100644 --- a/app/Domain/Actions/VacationRequest/CreateAction.php +++ b/app/Domain/Actions/VacationRequest/CreateAction.php @@ -6,10 +6,10 @@ namespace Toby\Domain\Actions\VacationRequest; use Illuminate\Validation\ValidationException; use Toby\Domain\Notifications\VacationRequestCreatedNotification; -use Toby\Domain\VacationDaysCalculator; use Toby\Domain\VacationRequestStateManager; use Toby\Domain\VacationTypeConfigRetriever; use Toby\Domain\Validation\VacationRequestValidator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; @@ -19,7 +19,7 @@ class CreateAction protected VacationRequestStateManager $stateManager, protected VacationRequestValidator $vacationRequestValidator, protected VacationTypeConfigRetriever $configRetriever, - protected VacationDaysCalculator $vacationDaysCalculator, + protected WorkDaysCalculator $workDaysCalculator, protected WaitForTechApprovalAction $waitForTechApprovalAction, protected WaitForAdminApprovalAction $waitForAdminApprovalAction, protected ApproveAction $approveAction, @@ -52,10 +52,7 @@ class CreateAction $vacationRequest->save(); - $days = $this->vacationDaysCalculator->calculateDays( - $vacationRequest->from, - $vacationRequest->to, - ); + $days = $this->workDaysCalculator->calculateDays($vacationRequest->from, $vacationRequest->to); foreach ($days as $day) { $vacationRequest->vacations()->create([ diff --git a/app/Domain/Notifications/KeyHasBeenGivenNotification.php b/app/Domain/Notifications/KeyHasBeenGivenNotification.php index 977f5bf..2759396 100644 --- a/app/Domain/Notifications/KeyHasBeenGivenNotification.php +++ b/app/Domain/Notifications/KeyHasBeenGivenNotification.php @@ -7,6 +7,7 @@ namespace Toby\Domain\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Toby\Eloquent\Models\User; +use Toby\Infrastructure\Slack\Elements\SlackMessage; class KeyHasBeenGivenNotification extends Notification { @@ -22,13 +23,14 @@ class KeyHasBeenGivenNotification extends Notification return [Channels::SLACK]; } - public function toSlack(Notifiable $notifiable): string + public function toSlack(Notifiable $notifiable): SlackMessage { - return __(":sender gives key no :key to :recipient", [ - "sender" => $this->getName($this->sender), - "recipient" => $this->getName($this->recipient), - "key" => $notifiable->id, - ]); + return (new SlackMessage()) + ->text(__(":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 diff --git a/app/Domain/Notifications/KeyHasBeenTakenNotification.php b/app/Domain/Notifications/KeyHasBeenTakenNotification.php index 71e8b7b..435fc02 100644 --- a/app/Domain/Notifications/KeyHasBeenTakenNotification.php +++ b/app/Domain/Notifications/KeyHasBeenTakenNotification.php @@ -7,6 +7,7 @@ namespace Toby\Domain\Notifications; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Notification; use Toby\Eloquent\Models\User; +use Toby\Infrastructure\Slack\Elements\SlackMessage; class KeyHasBeenTakenNotification extends Notification { @@ -22,13 +23,14 @@ class KeyHasBeenTakenNotification extends Notification return [Channels::SLACK]; } - public function toSlack(Notifiable $notifiable): string + public function toSlack(Notifiable $notifiable): SlackMessage { - return __(":recipient takes key no :key from :sender", [ - "recipient" => $this->getName($this->recipient), - "sender" => $this->getName($this->sender), - "key" => $notifiable->id, - ]); + return (new SlackMessage()) + ->text(__(":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 diff --git a/app/Domain/Notifications/VacationRequestCreatedNotification.php b/app/Domain/Notifications/VacationRequestCreatedNotification.php index 9a352c6..187ee45 100644 --- a/app/Domain/Notifications/VacationRequestCreatedNotification.php +++ b/app/Domain/Notifications/VacationRequestCreatedNotification.php @@ -9,6 +9,7 @@ use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; use InvalidArgumentException; use Toby\Eloquent\Models\VacationRequest; +use Toby\Infrastructure\Slack\Elements\SlackMessage; class VacationRequestCreatedNotification extends Notification { @@ -23,14 +24,12 @@ class VacationRequestCreatedNotification extends Notification return [Channels::MAIL, Channels::SLACK]; } - public function toSlack(): string + public function toSlack(): SlackMessage { $url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]); - return implode("\n", [ - $this->buildDescription(), - "<${url}|Zobacz szczegóły>", - ]); + return (new SlackMessage()) + ->text("{$this->buildDescription()}\n <${url}|Zobacz szczegóły>"); } /** @@ -56,19 +55,25 @@ class VacationRequestCreatedNotification extends Notification $days = $this->vacationRequest->vacations()->count(); return (new MailMessage()) - ->greeting(__("Hi :user!", [ - "user" => $user, - ])) + ->greeting( + __("Hi :user!", [ + "user" => $user, + ]), + ) ->subject($this->buildSubject()) ->line($this->buildDescription()) - ->line(__("Vacation type: :type", [ - "type" => $type, - ])) - ->line(__("From :from to :to (number of days: :days)", [ - "from" => $from, - "to" => $to, - "days" => $days, - ])) + ->line( + __("Vacation type: :type", [ + "type" => $type, + ]), + ) + ->line( + __("From :from to :to (number of days: :days)", [ + "from" => $from, + "to" => $to, + "days" => $days, + ]), + ) ->action(__("Click here for details"), $url); } diff --git a/app/Domain/Notifications/VacationRequestStatusChangedNotification.php b/app/Domain/Notifications/VacationRequestStatusChangedNotification.php index 746e3a0..cacd1e4 100644 --- a/app/Domain/Notifications/VacationRequestStatusChangedNotification.php +++ b/app/Domain/Notifications/VacationRequestStatusChangedNotification.php @@ -10,6 +10,7 @@ use Illuminate\Notifications\Notification; use InvalidArgumentException; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; +use Toby\Infrastructure\Slack\Elements\SlackMessage; class VacationRequestStatusChangedNotification extends Notification { @@ -25,14 +26,12 @@ class VacationRequestStatusChangedNotification extends Notification return [Channels::MAIL, Channels::SLACK]; } - public function toSlack(): string + public function toSlack(): SlackMessage { $url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]); - return implode("\n", [ - $this->buildDescription(), - "<${url}|Zobacz szczegóły>", - ]); + return (new SlackMessage()) + ->text("{$this->buildDescription()}\n <${url}|Zobacz szczegóły>"); } /** diff --git a/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php b/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php index 63ea770..b4033ad 100644 --- a/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php +++ b/app/Domain/Notifications/VacationRequestWaitsForApprovalNotification.php @@ -11,6 +11,7 @@ use InvalidArgumentException; use Toby\Domain\States\VacationRequest\WaitingForTechnical; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; +use Toby\Infrastructure\Slack\Elements\SlackMessage; class VacationRequestWaitsForApprovalNotification extends Notification { @@ -26,14 +27,12 @@ class VacationRequestWaitsForApprovalNotification extends Notification return [Channels::MAIL, Channels::SLACK]; } - public function toSlack(): string + public function toSlack(): SlackMessage { $url = route("vacation.requests.show", ["vacationRequest" => $this->vacationRequest->id]); - return implode("\n", [ - $this->buildDescription(), - "<${url}|Zobacz szczegóły>", - ]); + return (new SlackMessage()) + ->text("{$this->buildDescription()}\n <${url}|Zobacz szczegóły>"); } /** diff --git a/app/Domain/Notifications/VacationRequestsSummaryNotification.php b/app/Domain/Notifications/VacationRequestsSummaryNotification.php new file mode 100644 index 0000000..1865b1b --- /dev/null +++ b/app/Domain/Notifications/VacationRequestsSummaryNotification.php @@ -0,0 +1,70 @@ +text("Wnioski oczekujące na Twoją akcję - stan na dzień {$this->day->toDisplayString()}:") + ->withAttachment(new VacationRequestsAttachment($this->vacationRequests)); + } + + public function toMail(Notifiable $notifiable): MailMessage + { + $url = route( + "vacation.requests.indexForApprovers", + [ + "status" => "waiting_for_action", + ], + ); + + return $this->buildMailMessage($notifiable, $url); + } + + protected function buildMailMessage(Notifiable $notifiable, string $url): MailMessage + { + $user = $notifiable->profile->first_name; + + $message = (new MailMessage()) + ->greeting( + __("Hi :user!", [ + "user" => $user, + ]), + ) + ->line("Lista wniosków oczekujących na Twoją akcję - stan na dzień {$this->day->toDisplayString()}:") + ->subject("Wnioski oczekujące na akcje - stan na dzień {$this->day->toDisplayString()}"); + + foreach ($this->vacationRequests as $request) { + $message->line( + "Wniosek nr {$request->name} użytkownika {$request->user->profile->full_name} ({$request->from->toDisplayString()} - {$request->to->toDisplayString()})", + ); + } + + return $message + ->action("Przejdź do wniosków", $url); + } +} diff --git a/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php b/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php index 3b53892..c0ec8df 100644 --- a/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php +++ b/app/Domain/Validation/Rules/DoesNotExceedLimitRule.php @@ -7,9 +7,9 @@ namespace Toby\Domain\Validation\Rules; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; use Toby\Domain\Enums\VacationType; -use Toby\Domain\VacationDaysCalculator; use Toby\Domain\VacationRequestStatesRetriever; use Toby\Domain\VacationTypeConfigRetriever; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationRequest; use Toby\Eloquent\Models\YearPeriod; @@ -18,7 +18,7 @@ class DoesNotExceedLimitRule implements VacationRequestRule { public function __construct( protected VacationTypeConfigRetriever $configRetriever, - protected VacationDaysCalculator $vacationDaysCalculator, + protected WorkDaysCalculator $workDaysCalculator, ) {} public function check(VacationRequest $vacationRequest): bool @@ -29,7 +29,9 @@ class DoesNotExceedLimitRule implements VacationRequestRule $limit = $this->getUserVacationLimit($vacationRequest->user, $vacationRequest->yearPeriod); $vacationDays = $this->getVacationDaysWithLimit($vacationRequest->user, $vacationRequest->yearPeriod); - $estimatedDays = $this->vacationDaysCalculator->calculateDays($vacationRequest->from, $vacationRequest->to)->count(); + $estimatedDays = $this->workDaysCalculator + ->calculateDays($vacationRequest->from, $vacationRequest->to) + ->count(); return $limit >= ($vacationDays + $estimatedDays); } diff --git a/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php b/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php index 4968d4d..5e78a75 100644 --- a/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php +++ b/app/Domain/Validation/Rules/MinimumOneVacationDayRule.php @@ -4,18 +4,18 @@ declare(strict_types=1); namespace Toby\Domain\Validation\Rules; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\VacationRequest; class MinimumOneVacationDayRule implements VacationRequestRule { public function __construct( - protected VacationDaysCalculator $vacationDaysCalculator, + protected WorkDaysCalculator $workDaysCalculator, ) {} public function check(VacationRequest $vacationRequest): bool { - return $this->vacationDaysCalculator + return $this->workDaysCalculator ->calculateDays($vacationRequest->from, $vacationRequest->to) ->isNotEmpty(); } diff --git a/app/Domain/VacationDaysCalculator.php b/app/Domain/WorkDaysCalculator.php similarity index 97% rename from app/Domain/VacationDaysCalculator.php rename to app/Domain/WorkDaysCalculator.php index 2d3227e..3dd3c5f 100644 --- a/app/Domain/VacationDaysCalculator.php +++ b/app/Domain/WorkDaysCalculator.php @@ -9,7 +9,7 @@ use Carbon\CarbonPeriod; use Illuminate\Support\Collection; use Toby\Eloquent\Models\YearPeriod; -class VacationDaysCalculator +class WorkDaysCalculator { public function calculateDays(CarbonInterface $from, CarbonInterface $to): Collection { diff --git a/app/Eloquent/Models/VacationRequest.php b/app/Eloquent/Models/VacationRequest.php index 97f94b7..cb77f1c 100644 --- a/app/Eloquent/Models/VacationRequest.php +++ b/app/Eloquent/Models/VacationRequest.php @@ -11,6 +11,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Spatie\ModelStates\HasStates; @@ -84,6 +85,13 @@ class VacationRequest extends Model return $query->whereNotState("state", $states); } + public function scopeType(Builder $query, VacationType|array $types): Builder + { + $types = Arr::wrap($types); + + return $query->whereIn("type", $types); + } + public function scopeOverlapsWith(Builder $query, self $vacationRequest): Builder { return $query->where("from", "<=", $vacationRequest->to) diff --git a/app/Infrastructure/Console/Commands/SendVacationRequestSummariesToApprovers.php b/app/Infrastructure/Console/Commands/SendVacationRequestSummariesToApprovers.php new file mode 100644 index 0000000..9437021 --- /dev/null +++ b/app/Infrastructure/Console/Commands/SendVacationRequestSummariesToApprovers.php @@ -0,0 +1,36 @@ +whereIn("role", [Role::AdministrativeApprover, Role::TechnicalApprover, Role::Administrator]) + ->get(); + + foreach ($users as $user) { + $vacationRequests = VacationRequest::query() + ->states(VacationRequestStatesRetriever::waitingForUserActionStates($user)) + ->get(); + + if ($vacationRequests->isNotEmpty()) { + $user->notify(new VacationRequestsSummaryNotification(Carbon::today(), $vacationRequests)); + } + } + } +} diff --git a/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php b/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php index 3f3caa5..be7348c 100644 --- a/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php +++ b/app/Infrastructure/Http/Controllers/Api/CalculateVacationDaysController.php @@ -6,13 +6,13 @@ namespace Toby\Infrastructure\Http\Controllers\Api; use Illuminate\Http\JsonResponse; use Illuminate\Support\Carbon; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Infrastructure\Http\Controllers\Controller; use Toby\Infrastructure\Http\Requests\Api\CalculateVacationDaysRequest; class CalculateVacationDaysController extends Controller { - public function __invoke(CalculateVacationDaysRequest $request, VacationDaysCalculator $calculator): JsonResponse + public function __invoke(CalculateVacationDaysRequest $request, WorkDaysCalculator $calculator): JsonResponse { $days = $calculator->calculateDays($request->from(), $request->to()); diff --git a/app/Infrastructure/Slack/Channels/SlackApiChannel.php b/app/Infrastructure/Slack/Channels/SlackApiChannel.php index d790555..b8a9e67 100644 --- a/app/Infrastructure/Slack/Channels/SlackApiChannel.php +++ b/app/Infrastructure/Slack/Channels/SlackApiChannel.php @@ -17,11 +17,12 @@ class SlackApiChannel $url = "{$baseUrl}/chat.postMessage"; $channel = $notifiable->routeNotificationFor("slack", $notification); + $message = $notification->toSlack($notifiable); + return Http::withToken($this->getClientToken()) - ->post($url, [ + ->post($url, array_merge($message->getPayload(), [ "channel" => $channel, - "text" => $notification->toSlack($notifiable), - ]); + ])); } protected function getClientToken(): string diff --git a/app/Infrastructure/Slack/Elements/SlackMessage.php b/app/Infrastructure/Slack/Elements/SlackMessage.php new file mode 100644 index 0000000..05d8e1b --- /dev/null +++ b/app/Infrastructure/Slack/Elements/SlackMessage.php @@ -0,0 +1,53 @@ +attachments = new Collection(); + } + + public function text(string $text): static + { + $this->text = $text; + + return $this; + } + + public function withAttachment(Attachment $attachment): static + { + $this->attachments->push($attachment); + + return $this; + } + + public function withAttachments(Collection $attachments): static + { + foreach ($attachments as $attachment) { + $this->withAttachment($attachment); + } + + return $this; + } + + public function getPayload(): array + { + return [ + "text" => $this->text, + "link_names" => true, + "unfurl_links" => true, + "unfurl_media" => true, + "mrkdwn" => true, + "attachments" => $this->attachments->toArray(), + ]; + } +} diff --git a/app/Infrastructure/Slack/Elements/VacationRequestsAttachment.php b/app/Infrastructure/Slack/Elements/VacationRequestsAttachment.php new file mode 100644 index 0000000..933b8fb --- /dev/null +++ b/app/Infrastructure/Slack/Elements/VacationRequestsAttachment.php @@ -0,0 +1,33 @@ +setColor("#527aba") + ->setItems($this->mapVacationRequests($vacationRequests)); + } + + protected function mapVacationRequests(Collection $vacationRequests): Collection + { + return $vacationRequests->map(function (VacationRequest $request): string { + $url = route("vacation.requests.show", ["vacationRequest" => $request->id]); + + $date = $request->from->equalTo($request->to) + ? "{$request->from->toDisplayString()}" + : "{$request->from->toDisplayString()} - {$request->to->toDisplayString()}"; + + return "<{$url}|Wniosek nr {$request->name}> użytkownika {$request->user->profile->full_name} ({$date})"; + }); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index f5e0e51..ea21c71 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -7,7 +7,7 @@ namespace Database\Seeders; use Illuminate\Database\Seeder; use Illuminate\Support\Carbon; use Toby\Domain\PolishHolidaysRetriever; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\Key; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationLimit; @@ -70,8 +70,7 @@ class DatabaseSeeder extends Seeder "year_period_id" => $yearPeriods->random()->id, ]) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( - $vacationRequest->yearPeriod, + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->from, $vacationRequest->to, ); diff --git a/database/seeders/DemoSeeder.php b/database/seeders/DemoSeeder.php index 41470ba..5d321ab 100644 --- a/database/seeders/DemoSeeder.php +++ b/database/seeders/DemoSeeder.php @@ -18,7 +18,7 @@ use Toby\Domain\States\VacationRequest\Created; use Toby\Domain\States\VacationRequest\Rejected; use Toby\Domain\States\VacationRequest\WaitingForAdministrative; use Toby\Domain\States\VacationRequest\WaitingForTechnical; -use Toby\Domain\VacationDaysCalculator; +use Toby\Domain\WorkDaysCalculator; use Toby\Eloquent\Models\Key; use Toby\Eloquent\Models\User; use Toby\Eloquent\Models\VacationLimit; @@ -164,8 +164,7 @@ class DemoSeeder extends Seeder ->for($user, "creator") ->for($currentYearPeriod) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( - $vacationRequest->yearPeriod, + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->from, $vacationRequest->to, ); @@ -234,8 +233,7 @@ class DemoSeeder extends Seeder ->for($user, "creator") ->for($currentYearPeriod) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( - $vacationRequest->yearPeriod, + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->from, $vacationRequest->to, ); @@ -291,8 +289,7 @@ class DemoSeeder extends Seeder ->for($user, "creator") ->for($currentYearPeriod) ->afterCreating(function (VacationRequest $vacationRequest): void { - $days = app(VacationDaysCalculator::class)->calculateDays( - $vacationRequest->yearPeriod, + $days = app(WorkDaysCalculator::class)->calculateDays( $vacationRequest->from, $vacationRequest->to, ); diff --git a/resources/js/Pages/VacationRequest/Show.vue b/resources/js/Pages/VacationRequest/Show.vue index ad58a1e..a606539 100644 --- a/resources/js/Pages/VacationRequest/Show.vue +++ b/resources/js/Pages/VacationRequest/Show.vue @@ -77,7 +77,7 @@
{{ request.comment }}
diff --git a/routes/api.php b/routes/api.php index 3220d19..7fa9ef1 100644 --- a/routes/api.php +++ b/routes/api.php @@ -7,9 +7,9 @@ use Toby\Infrastructure\Http\Controllers\Api\CalculateUserUnavailableDaysControl use Toby\Infrastructure\Http\Controllers\Api\CalculateUserVacationStatsController; use Toby\Infrastructure\Http\Controllers\Api\CalculateVacationDaysController; use Toby\Infrastructure\Http\Controllers\Api\GetAvailableVacationTypesController; -use Toby\Infrastructure\Slack\Controller as SlackController; +use Toby\Infrastructure\Slack\Controller as SlackCommandController; -Route::post("slack", [SlackController::class, "getResponse"]); +Route::post("slack", [SlackCommandController::class, "getResponse"]); Route::middleware("auth:sanctum")->group(function (): void { Route::post("vacation/calculate-days", CalculateVacationDaysController::class); diff --git a/tests/Unit/SendVacationRequestSummariesTest.php b/tests/Unit/SendVacationRequestSummariesTest.php new file mode 100644 index 0000000..97370bd --- /dev/null +++ b/tests/Unit/SendVacationRequestSummariesTest.php @@ -0,0 +1,130 @@ +createCurrentYearPeriod(); + } + + public function testSummariesAreSentOnlyToProperApprovers(): void + { + $currentYearPeriod = YearPeriod::current(); + + $user = User::factory([ + "role" => Role::Employee, + ])->create(); + $technicalApprover = User::factory([ + "role" => Role::TechnicalApprover, + ])->create(); + $administrativeApprover = User::factory([ + "role" => Role::AdministrativeApprover, + ])->create(); + $admin = User::factory([ + "role" => Role::Administrator, + ])->create(); + + VacationRequest::factory() + ->for($user) + ->for($currentYearPeriod) + ->create(["state" => WaitingForTechnical::class]); + + $this->artisan(SendVacationRequestSummariesToApprovers::class) + ->execute(); + + Notification::assertSentTo([$technicalApprover, $admin], VacationRequestsSummaryNotification::class); + Notification::assertNotSentTo([$user, $administrativeApprover], VacationRequestsSummaryNotification::class); + } + + public function testSummariesAreSentOnlyIfVacationRequestWaitingForActionExists(): void + { + $currentYearPeriod = YearPeriod::current(); + + $user = User::factory([ + "role" => Role::Employee, + ])->create(); + $technicalApprover = User::factory([ + "role" => Role::TechnicalApprover, + ])->create(); + $admin = User::factory([ + "role" => Role::Administrator, + ])->create(); + + VacationRequest::factory() + ->for($user) + ->for($currentYearPeriod) + ->create(["state" => WaitingForTechnical::class]); + + $this->artisan(SendVacationRequestSummariesToApprovers::class) + ->execute(); + + Notification::assertSentTo([$technicalApprover, $admin], VacationRequestsSummaryNotification::class); + Notification::assertNotSentTo([$user], VacationRequestsSummaryNotification::class); + } + + public function testSummariesAreNotSentIfThereAreNoWaitingForActionVacationRequests(): void + { + $currentYearPeriod = YearPeriod::current(); + + $user = User::factory([ + "role" => Role::Employee, + ])->create(); + $technicalApprover = User::factory([ + "role" => Role::TechnicalApprover, + ])->create(); + $admin = User::factory([ + "role" => Role::Administrator, + ])->create(); + + VacationRequest::factory() + ->for($user) + ->for($currentYearPeriod) + ->create(["state" => Approved::class]); + + VacationRequest::factory() + ->for($user) + ->for($currentYearPeriod) + ->create(["state" => Cancelled::class]); + + VacationRequest::factory() + ->for($user) + ->for($currentYearPeriod) + ->create(["state" => Rejected::class]); + + VacationRequest::factory() + ->for($user) + ->for($currentYearPeriod) + ->create(["state" => Created::class]); + + $this->artisan(SendVacationRequestSummariesToApprovers::class) + ->execute(); + + Notification::assertNotSentTo([$user, $technicalApprover, $admin], VacationRequestsSummaryNotification::class); + } +} From 06863b854aeea9736ceca475d6a877d85110c59b Mon Sep 17 00:00:00 2001 From: Adrian Hopek Date: Fri, 29 Apr 2022 09:22:02 +0200 Subject: [PATCH 3/9] #138 - fix tables on safari (#139) --- resources/js/Pages/VacationRequest/Index.vue | 10 ++++------ .../js/Pages/VacationRequest/IndexForApprovers.vue | 12 +++++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/resources/js/Pages/VacationRequest/Index.vue b/resources/js/Pages/VacationRequest/Index.vue index 38427ff..9db138d 100644 --- a/resources/js/Pages/VacationRequest/Index.vue +++ b/resources/js/Pages/VacationRequest/Index.vue @@ -132,9 +132,11 @@ - @@ -167,12 +169,8 @@ >
- - + - - - + Date: Fri, 29 Apr 2022 09:22:41 +0200 Subject: [PATCH 4/9] - bump async from 2.6.3 to 2.6.4 (#137) Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 085c8b5..f87723e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2642,9 +2642,9 @@ } }, "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "dependencies": { "lodash": "^4.17.14" } @@ -11311,9 +11311,9 @@ } }, "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", "requires": { "lodash": "^4.17.14" } From 3404bf1da875ba2c91907e6536513d5162fa78eb Mon Sep 17 00:00:00 2001 From: Krzysztof Rewak Date: Fri, 29 Apr 2022 09:35:47 +0200 Subject: [PATCH 5/9] #115 - Heroku deploy in GitHub Actions (#136) --- .github/workflows/deploy.yml | 17 +++++++++++++++++ composer.json | 2 +- composer.lock | 14 +++++++------- 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..1e43ede --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,17 @@ +name: Deploy + +on: + push: + tags: + - v* + +jobs: + deploy: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - uses: akhileshns/heroku-deploy@v3.12.12 + with: + heroku_api_key: ${{secrets.HEROKU_API_KEY}} + heroku_app_name: ${{secrets.HEROKU_APP_NAME}} + heroku_email: ${{secrets.HEROKU_EMAIL}} diff --git a/composer.json b/composer.json index 36d9d98..155b43e 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "spatie/laravel-slack-slash-command": "^1.11" }, "require-dev": { - "blumilksoftware/codestyle": "^1.0.0", + "blumilksoftware/codestyle": "^1.2.0", "fakerphp/faker": "^1.19", "laravel/dusk": "^6.21", "mockery/mockery": "^1.4.4", diff --git a/composer.lock b/composer.lock index 498daa4..1de54b9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "24a1b3a5dd7c4d4f50d521dda4b6654e", + "content-hash": "572998c0dff042cc8ddf65cb1b7348c9", "packages": [ { "name": "asm89/stack-cors", @@ -7652,16 +7652,16 @@ "packages-dev": [ { "name": "blumilksoftware/codestyle", - "version": "v1.1.0", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/blumilksoftware/codestyle.git", - "reference": "3f2248859562afe7d7b2b16aa25e83dc73236fcc" + "reference": "124c55f0374d8f6952675011e359cb54f40f4090" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/3f2248859562afe7d7b2b16aa25e83dc73236fcc", - "reference": "3f2248859562afe7d7b2b16aa25e83dc73236fcc", + "url": "https://api.github.com/repos/blumilksoftware/codestyle/zipball/124c55f0374d8f6952675011e359cb54f40f4090", + "reference": "124c55f0374d8f6952675011e359cb54f40f4090", "shasum": "" }, "require": { @@ -7696,9 +7696,9 @@ "description": "Blumilk codestyle configurator", "support": { "issues": "https://github.com/blumilksoftware/codestyle/issues", - "source": "https://github.com/blumilksoftware/codestyle/tree/v1.1.0" + "source": "https://github.com/blumilksoftware/codestyle/tree/v1.2.0" }, - "time": "2022-04-25T06:04:51+00:00" + "time": "2022-04-27T10:13:34+00:00" }, { "name": "composer/pcre", From e1f449fb52fb35e45e6bfaded2f8418c381a4d1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 08:34:03 +0200 Subject: [PATCH 6/9] #5 - (js) Bump @vue/compiler-sfc from 3.2.31 to 3.2.33 (#141) * #5 - (js) Bump @vue/compiler-sfc from 3.2.31 to 3.2.33 Bumps [@vue/compiler-sfc](https://github.com/vuejs/core/tree/HEAD/packages/compiler-sfc) from 3.2.31 to 3.2.33. - [Release notes](https://github.com/vuejs/core/releases) - [Changelog](https://github.com/vuejs/core/blob/main/CHANGELOG.md) - [Commits](https://github.com/vuejs/core/commits/v3.2.33/packages/compiler-sfc) --- updated-dependencies: - dependency-name: "@vue/compiler-sfc" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * #5 - May 2022 npm packages update * #5 - disabled multi-word-component-names Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: EwelinaLasowy --- .eslintrc.js | 1 + package-lock.json | 616 ++++++++++++++++++++++++++-------------------- package.json | 28 +-- 3 files changed, 358 insertions(+), 287 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index ba5b8c0..53abb81 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,5 +21,6 @@ module.exports = { 'tailwindcss/enforces-shorthand': 'error', 'tailwindcss/no-arbitrary-value': 'error', 'tailwindcss/no-contradicting-classname': 'error', + 'vue/multi-word-component-names': 0, }, } diff --git a/package-lock.json b/package-lock.json index f87723e..c40541b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,42 +1,42 @@ { - "name": "toby", + "name": "application", "lockfileVersion": 2, "requires": true, "packages": { "": { "hasInstallScript": true, "dependencies": { - "@headlessui/vue": "^1.5.0", + "@headlessui/vue": "^1.6.1", "@heroicons/vue": "^1.0.6", "@inertiajs/inertia": "^0.11.0", "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/progress": "^0.2.7", - "@tailwindcss/forms": "^0.5.0", - "@tailwindcss/line-clamp": "^0.3.1", + "@tailwindcss/forms": "^0.5.1", + "@tailwindcss/line-clamp": "^0.4.0", "@tailwindcss/typography": "^0.5.2", - "@vue/compiler-sfc": "^3.2.31", - "autoprefixer": "^10.4.4", - "axios": "^0.26.1", + "@vue/compiler-sfc": "^3.2.33", + "autoprefixer": "^10.4.7", + "axios": "^0.27.2", "echarts": "^5.3.2", "eslit": "^6.0.0", - "flatpickr": "^4.6.11", + "flatpickr": "^4.6.13", "laravel-mix": "^6.0.43", "lodash": "^4.17.21", - "luxon": "^2.3.1", - "postcss": "^8.4.12", - "tailwindcss": "^3.0.23", - "vue": "^3.2.31", + "luxon": "^2.3.2", + "postcss": "^8.4.13", + "tailwindcss": "^3.0.24", + "vue": "^3.2.33", "vue-echarts": "^6.0.2", - "vue-flatpickr-component": "^9.0.5", + "vue-flatpickr-component": "^9.0.6", "vue-loader": "^17.0.0", "vue-material-design-icons": "^5.0.0", "vue-toastification": "^2.0.0-rc.5", "vue3-popper": "^1.4.2" }, "devDependencies": { - "eslint": "^8.12.0", + "eslint": "^8.14.0", "eslint-plugin-tailwindcss": "^3.5.0", - "eslint-plugin-vue": "^8.5.0" + "eslint-plugin-vue": "^8.7.1" } }, "node_modules/@ampproject/remapping": { @@ -1662,9 +1662,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz", + "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -1682,9 +1682,9 @@ } }, "node_modules/@headlessui/vue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.5.0.tgz", - "integrity": "sha512-jAp6XYpqdEv32xhszaj5ejvjaX5qhu20sCbxu7lplePEfZL+4ffabivJBBTZAiPWczqAXmnZWNWG5DOyqjRa4w==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.6.1.tgz", + "integrity": "sha512-fccGN1hsFvS0P73NplZoOdX1rhyaH5jIQE9IUKNaaJC72mQjR3lVvZldo+iiLF5X1bqgl6pDixWdqS2kMGfFxA==", "engines": { "node": ">=10" }, @@ -1831,9 +1831,9 @@ } }, "node_modules/@tailwindcss/forms": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.0.tgz", - "integrity": "sha512-KzWugryEBFkmoaYcBE18rs6gthWCFHHO7cAZm2/hv3hwD67AzwP7udSCa22E7R1+CEJL/FfhYsJWrc0b1aeSzw==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.1.tgz", + "integrity": "sha512-QSwsFORnC2BAP0lRzQkz1pw+EzIiiPdk4e27vGQjyXkwJPeC7iLIRVndJzf9CJVbcrrIcirb/TfxF3gRTyFEVA==", "dependencies": { "mini-svg-data-uri": "^1.2.3" }, @@ -1842,9 +1842,9 @@ } }, "node_modules/@tailwindcss/line-clamp": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz", - "integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz", + "integrity": "sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw==", "peerDependencies": { "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" } @@ -2131,36 +2131,36 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", - "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.33.tgz", + "integrity": "sha512-AAmr52ji3Zhk7IKIuigX2osWWsb2nQE5xsdFYjdnmtQ4gymmqXbjLvkSE174+fF3A3kstYrTgGkqgOEbsdLDpw==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.31", + "@vue/shared": "3.2.33", "estree-walker": "^2.0.2", "source-map": "^0.6.1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", - "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.33.tgz", + "integrity": "sha512-GhiG1C8X98Xz9QUX/RlA6/kgPBWJkjq0Rq6//5XTAGSYrTMBgcLpP9+CnlUg1TFxnnCVughAG+KZl28XJqw8uQ==", "dependencies": { - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-core": "3.2.33", + "@vue/shared": "3.2.33" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", - "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.33.tgz", + "integrity": "sha512-H8D0WqagCr295pQjUYyO8P3IejM3vEzeCO1apzByAEaAR/WimhMYczHfZVvlCE/9yBaEu/eu9RdiWr0kF8b71Q==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/compiler-dom": "3.2.31", - "@vue/compiler-ssr": "3.2.31", - "@vue/reactivity-transform": "3.2.31", - "@vue/shared": "3.2.31", + "@vue/compiler-core": "3.2.33", + "@vue/compiler-dom": "3.2.33", + "@vue/compiler-ssr": "3.2.33", + "@vue/reactivity-transform": "3.2.33", + "@vue/shared": "3.2.33", "estree-walker": "^2.0.2", "magic-string": "^0.25.7", "postcss": "^8.1.10", @@ -2168,69 +2168,69 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", - "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.33.tgz", + "integrity": "sha512-XQh1Xdk3VquDpXsnoCd7JnMoWec9CfAzQDQsaMcSU79OrrO2PNR0ErlIjm/mGq3GmBfkQjzZACV+7GhfRB8xMQ==", "dependencies": { - "@vue/compiler-dom": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-dom": "3.2.33", + "@vue/shared": "3.2.33" } }, "node_modules/@vue/reactivity": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.31.tgz", - "integrity": "sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.33.tgz", + "integrity": "sha512-62Sq0mp9/0bLmDuxuLD5CIaMG2susFAGARLuZ/5jkU1FCf9EDbwUuF+BO8Ub3Rbodx0ziIecM/NsmyjardBxfQ==", "dependencies": { - "@vue/shared": "3.2.31" + "@vue/shared": "3.2.33" } }, "node_modules/@vue/reactivity-transform": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", - "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.33.tgz", + "integrity": "sha512-4UL5KOIvSQb254aqenW4q34qMXbfZcmEsV/yVidLUgvwYQQ/D21bGX3DlgPUGI3c4C+iOnNmDCkIxkILoX/Pyw==", "dependencies": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31", + "@vue/compiler-core": "3.2.33", + "@vue/shared": "3.2.33", "estree-walker": "^2.0.2", "magic-string": "^0.25.7" } }, "node_modules/@vue/runtime-core": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.31.tgz", - "integrity": "sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.33.tgz", + "integrity": "sha512-N2D2vfaXsBPhzCV3JsXQa2NECjxP3eXgZlFqKh4tgakp3iX6LCGv76DLlc+IfFZq+TW10Y8QUfeihXOupJ1dGw==", "dependencies": { - "@vue/reactivity": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/reactivity": "3.2.33", + "@vue/shared": "3.2.33" } }, "node_modules/@vue/runtime-dom": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.31.tgz", - "integrity": "sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz", + "integrity": "sha512-LSrJ6W7CZTSUygX5s8aFkraDWlO6K4geOwA3quFF2O+hC3QuAMZt/0Xb7JKE3C4JD4pFwCSO7oCrZmZ0BIJUnw==", "dependencies": { - "@vue/runtime-core": "3.2.31", - "@vue/shared": "3.2.31", + "@vue/runtime-core": "3.2.33", + "@vue/shared": "3.2.33", "csstype": "^2.6.8" } }, "node_modules/@vue/server-renderer": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.31.tgz", - "integrity": "sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.33.tgz", + "integrity": "sha512-4jpJHRD4ORv8PlbYi+/MfP8ec1okz6rybe36MdpkDrGIdEItHEUyaHSKvz+ptNEyQpALmmVfRteHkU9F8vxOew==", "dependencies": { - "@vue/compiler-ssr": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-ssr": "3.2.33", + "@vue/shared": "3.2.33" }, "peerDependencies": { - "vue": "3.2.31" + "vue": "3.2.33" } }, "node_modules/@vue/shared": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", - "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==" + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.33.tgz", + "integrity": "sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==" }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", @@ -2649,10 +2649,15 @@ "lodash": "^4.17.14" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "node_modules/autoprefixer": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", - "integrity": "sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==", + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", "funding": [ { "type": "opencollective", @@ -2664,8 +2669,8 @@ } ], "dependencies": { - "browserslist": "^4.20.2", - "caniuse-lite": "^1.0.30001317", + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -2682,11 +2687,12 @@ } }, "node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "dependencies": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, "node_modules/babel-loader": { @@ -3002,9 +3008,9 @@ } }, "node_modules/browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", "funding": [ { "type": "opencollective", @@ -3016,10 +3022,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", "escalade": "^3.1.1", - "node-releases": "^2.0.2", + "node-releases": "^2.0.3", "picocolors": "^1.0.0" }, "bin": { @@ -3111,9 +3117,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001325", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz", - "integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==", + "version": "1.0.30001335", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", + "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==", "funding": [ { "type": "opencollective", @@ -3290,6 +3296,17 @@ "node": ">=0.1.90" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -3849,6 +3866,14 @@ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -4081,9 +4106,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "node_modules/electron-to-chromium": { - "version": "1.4.104", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.104.tgz", - "integrity": "sha512-2kjoAyiG7uMyGRM9mx25s3HAzmQG2ayuYXxsFmYugHSDcwxREgLtscZvbL1JcW9S/OemeQ3f/SG6JhDwpnCclQ==" + "version": "1.4.132", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.132.tgz", + "integrity": "sha512-JYdZUw/1068NWN+SwXQ7w6Ue0bWYGihvSUNNQwurvcDV/SM7vSiGZ3NuFvFgoEiCs4kB8xs3cX2an3wB7d4TBw==" }, "node_modules/elliptic": { "version": "6.5.4", @@ -4195,12 +4220,12 @@ } }, "node_modules/eslint": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", - "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz", + "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.2.1", + "@eslint/eslintrc": "^1.2.2", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -4261,13 +4286,15 @@ } }, "node_modules/eslint-plugin-vue": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.6.0.tgz", - "integrity": "sha512-abXiF2J18n/7ZPy9foSlJyouKf54IqpKlNvNmzhM93N0zs3QUxZG/oBd3tVPOJTKg7SlhBUtPxugpqzNbgGpQQ==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", + "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", "dev": true, "dependencies": { "eslint-utils": "^3.0.0", "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", "semver": "^7.3.5", "vue-eslint-parser": "^8.0.1" }, @@ -4743,9 +4770,9 @@ } }, "node_modules/flatpickr": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.11.tgz", - "integrity": "sha512-/rnbE/hu5I5zndLEyYfYvqE4vPDvI5At0lFcQA5eOPfjquZLcQ0HMKTL7rv5/+DvbPM3/vJcXpXjB/DjBh+1jw==" + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==" }, "node_modules/flatted": { "version": "3.2.5", @@ -4772,6 +4799,19 @@ } } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -5914,9 +5954,9 @@ } }, "node_modules/luxon": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.3.1.tgz", - "integrity": "sha512-I8vnjOmhXsMSlNMZlMkSOvgrxKJl0uOsEzdGgGNZuZPaS9KlefpE9KV95QFftlJSC+1UyCC9/I69R02cz/zcCA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.3.2.tgz", + "integrity": "sha512-MlAQQVMFhGk4WUA6gpfsy0QycnKP0+NlCBJRVRNPxxSIbjrCbQ65nrpJD3FVyJNZLuJ0uoqL57ye6BmDYgHaSw==", "engines": { "node": ">=12" } @@ -6188,9 +6228,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz", - "integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -6278,9 +6318,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -6345,9 +6385,9 @@ } }, "node_modules/object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "engines": { "node": ">= 6" } @@ -6707,9 +6747,9 @@ } }, "node_modules/postcss": { - "version": "8.4.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", - "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", + "version": "8.4.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", + "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", "funding": [ { "type": "opencollective", @@ -6721,7 +6761,7 @@ } ], "dependencies": { - "nanoid": "^3.3.1", + "nanoid": "^3.3.3", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -8263,28 +8303,28 @@ } }, "node_modules/tailwindcss": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz", - "integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==", + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", + "integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==", "dependencies": { "arg": "^5.0.1", - "chalk": "^4.1.2", "chokidar": "^3.5.3", "color-name": "^1.1.4", - "cosmiconfig": "^7.0.1", "detective": "^5.2.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.11", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", "normalize-path": "^3.0.0", - "object-hash": "^2.2.0", - "postcss": "^8.4.6", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.12", "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.0", + "postcss-load-config": "^3.1.4", "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.9", + "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.0" @@ -8297,7 +8337,6 @@ "node": ">=12.13.0" }, "peerDependencies": { - "autoprefixer": "^10.0.2", "postcss": "^8.0.9" } }, @@ -8625,15 +8664,15 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, "node_modules/vue": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.31.tgz", - "integrity": "sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.33.tgz", + "integrity": "sha512-si1ExAlDUrLSIg/V7D/GgA4twJwfsfgG+t9w10z38HhL/HA07132pUQ2KuwAo8qbCyMJ9e6OqrmWrOCr+jW7ZQ==", "dependencies": { - "@vue/compiler-dom": "3.2.31", - "@vue/compiler-sfc": "3.2.31", - "@vue/runtime-dom": "3.2.31", - "@vue/server-renderer": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-dom": "3.2.33", + "@vue/compiler-sfc": "3.2.33", + "@vue/runtime-dom": "3.2.33", + "@vue/server-renderer": "3.2.33", + "@vue/shared": "3.2.33" } }, "node_modules/vue-echarts": { @@ -8706,9 +8745,9 @@ } }, "node_modules/vue-flatpickr-component": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-9.0.5.tgz", - "integrity": "sha512-fKuz/D4ePQKi+jPo4xjYRgBCLTWrTsCoKbx8nam63x4kTDtSqvFOjNwLvy0QgwC0lC+aFpUWa1dNYTH0hgUcCA==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-9.0.6.tgz", + "integrity": "sha512-U3355po5WPejAagvDig+MA7v8NWr0+Dbx3a1pds19hx4i9CeXuBSpD7vl0fxKhk+Hfu3T+DN2aOR69HIwSJh1A==", "dependencies": { "flatpickr": "^4.6.9" }, @@ -10445,9 +10484,9 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.2.tgz", + "integrity": "sha512-lTVWHs7O2hjBFZunXTZYnYqtB9GakA1lnxIf+gKq2nY5gxkkNi/lQvveW6t8gFdOHTg6nG50Xs95PrLqVpcaLg==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -10462,9 +10501,9 @@ } }, "@headlessui/vue": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.5.0.tgz", - "integrity": "sha512-jAp6XYpqdEv32xhszaj5ejvjaX5qhu20sCbxu7lplePEfZL+4ffabivJBBTZAiPWczqAXmnZWNWG5DOyqjRa4w==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@headlessui/vue/-/vue-1.6.1.tgz", + "integrity": "sha512-fccGN1hsFvS0P73NplZoOdX1rhyaH5jIQE9IUKNaaJC72mQjR3lVvZldo+iiLF5X1bqgl6pDixWdqS2kMGfFxA==", "requires": {} }, "@heroicons/vue": { @@ -10580,17 +10619,17 @@ "integrity": "sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw==" }, "@tailwindcss/forms": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.0.tgz", - "integrity": "sha512-KzWugryEBFkmoaYcBE18rs6gthWCFHHO7cAZm2/hv3hwD67AzwP7udSCa22E7R1+CEJL/FfhYsJWrc0b1aeSzw==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.1.tgz", + "integrity": "sha512-QSwsFORnC2BAP0lRzQkz1pw+EzIiiPdk4e27vGQjyXkwJPeC7iLIRVndJzf9CJVbcrrIcirb/TfxF3gRTyFEVA==", "requires": { "mini-svg-data-uri": "^1.2.3" } }, "@tailwindcss/line-clamp": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.3.1.tgz", - "integrity": "sha512-pNr0T8LAc3TUx/gxCfQZRe9NB2dPEo/cedPHzUGIPxqDMhgjwNm6jYxww4W5l0zAsAddxr+XfZcqttGiFDgrGg==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@tailwindcss/line-clamp/-/line-clamp-0.4.0.tgz", + "integrity": "sha512-HQZo6gfx1D0+DU3nWlNLD5iA6Ef4JAXh0LeD8lOGrJwEDBwwJNKQza6WoXhhY1uQrxOuU8ROxV7CqiQV4CoiLw==", "requires": {} }, "@tailwindcss/typography": { @@ -10869,36 +10908,36 @@ } }, "@vue/compiler-core": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.31.tgz", - "integrity": "sha512-aKno00qoA4o+V/kR6i/pE+aP+esng5siNAVQ422TkBNM6qA4veXiZbSe8OTXHXquEi/f6Akc+nLfB4JGfe4/WQ==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.33.tgz", + "integrity": "sha512-AAmr52ji3Zhk7IKIuigX2osWWsb2nQE5xsdFYjdnmtQ4gymmqXbjLvkSE174+fF3A3kstYrTgGkqgOEbsdLDpw==", "requires": { "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.31", + "@vue/shared": "3.2.33", "estree-walker": "^2.0.2", "source-map": "^0.6.1" } }, "@vue/compiler-dom": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.31.tgz", - "integrity": "sha512-60zIlFfzIDf3u91cqfqy9KhCKIJgPeqxgveH2L+87RcGU/alT6BRrk5JtUso0OibH3O7NXuNOQ0cDc9beT0wrg==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.33.tgz", + "integrity": "sha512-GhiG1C8X98Xz9QUX/RlA6/kgPBWJkjq0Rq6//5XTAGSYrTMBgcLpP9+CnlUg1TFxnnCVughAG+KZl28XJqw8uQ==", "requires": { - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-core": "3.2.33", + "@vue/shared": "3.2.33" } }, "@vue/compiler-sfc": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.31.tgz", - "integrity": "sha512-748adc9msSPGzXgibHiO6T7RWgfnDcVQD+VVwYgSsyyY8Ans64tALHZANrKtOzvkwznV/F4H7OAod/jIlp/dkQ==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.33.tgz", + "integrity": "sha512-H8D0WqagCr295pQjUYyO8P3IejM3vEzeCO1apzByAEaAR/WimhMYczHfZVvlCE/9yBaEu/eu9RdiWr0kF8b71Q==", "requires": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/compiler-dom": "3.2.31", - "@vue/compiler-ssr": "3.2.31", - "@vue/reactivity-transform": "3.2.31", - "@vue/shared": "3.2.31", + "@vue/compiler-core": "3.2.33", + "@vue/compiler-dom": "3.2.33", + "@vue/compiler-ssr": "3.2.33", + "@vue/reactivity-transform": "3.2.33", + "@vue/shared": "3.2.33", "estree-walker": "^2.0.2", "magic-string": "^0.25.7", "postcss": "^8.1.10", @@ -10906,66 +10945,66 @@ } }, "@vue/compiler-ssr": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.31.tgz", - "integrity": "sha512-mjN0rqig+A8TVDnsGPYJM5dpbjlXeHUm2oZHZwGyMYiGT/F4fhJf/cXy8QpjnLQK4Y9Et4GWzHn9PS8AHUnSkw==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.33.tgz", + "integrity": "sha512-XQh1Xdk3VquDpXsnoCd7JnMoWec9CfAzQDQsaMcSU79OrrO2PNR0ErlIjm/mGq3GmBfkQjzZACV+7GhfRB8xMQ==", "requires": { - "@vue/compiler-dom": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-dom": "3.2.33", + "@vue/shared": "3.2.33" } }, "@vue/reactivity": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.31.tgz", - "integrity": "sha512-HVr0l211gbhpEKYr2hYe7hRsV91uIVGFYNHj73njbARVGHQvIojkImKMaZNDdoDZOIkMsBc9a1sMqR+WZwfSCw==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.33.tgz", + "integrity": "sha512-62Sq0mp9/0bLmDuxuLD5CIaMG2susFAGARLuZ/5jkU1FCf9EDbwUuF+BO8Ub3Rbodx0ziIecM/NsmyjardBxfQ==", "requires": { - "@vue/shared": "3.2.31" + "@vue/shared": "3.2.33" } }, "@vue/reactivity-transform": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.31.tgz", - "integrity": "sha512-uS4l4z/W7wXdI+Va5pgVxBJ345wyGFKvpPYtdSgvfJfX/x2Ymm6ophQlXXB6acqGHtXuBqNyyO3zVp9b1r0MOA==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.33.tgz", + "integrity": "sha512-4UL5KOIvSQb254aqenW4q34qMXbfZcmEsV/yVidLUgvwYQQ/D21bGX3DlgPUGI3c4C+iOnNmDCkIxkILoX/Pyw==", "requires": { "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.31", - "@vue/shared": "3.2.31", + "@vue/compiler-core": "3.2.33", + "@vue/shared": "3.2.33", "estree-walker": "^2.0.2", "magic-string": "^0.25.7" } }, "@vue/runtime-core": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.31.tgz", - "integrity": "sha512-Kcog5XmSY7VHFEMuk4+Gap8gUssYMZ2+w+cmGI6OpZWYOEIcbE0TPzzPHi+8XTzAgx1w/ZxDFcXhZeXN5eKWsA==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.33.tgz", + "integrity": "sha512-N2D2vfaXsBPhzCV3JsXQa2NECjxP3eXgZlFqKh4tgakp3iX6LCGv76DLlc+IfFZq+TW10Y8QUfeihXOupJ1dGw==", "requires": { - "@vue/reactivity": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/reactivity": "3.2.33", + "@vue/shared": "3.2.33" } }, "@vue/runtime-dom": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.31.tgz", - "integrity": "sha512-N+o0sICVLScUjfLG7u9u5XCjvmsexAiPt17GNnaWHJUfsKed5e85/A3SWgKxzlxx2SW/Hw7RQxzxbXez9PtY3g==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.33.tgz", + "integrity": "sha512-LSrJ6W7CZTSUygX5s8aFkraDWlO6K4geOwA3quFF2O+hC3QuAMZt/0Xb7JKE3C4JD4pFwCSO7oCrZmZ0BIJUnw==", "requires": { - "@vue/runtime-core": "3.2.31", - "@vue/shared": "3.2.31", + "@vue/runtime-core": "3.2.33", + "@vue/shared": "3.2.33", "csstype": "^2.6.8" } }, "@vue/server-renderer": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.31.tgz", - "integrity": "sha512-8CN3Zj2HyR2LQQBHZ61HexF5NReqngLT3oahyiVRfSSvak+oAvVmu8iNLSu6XR77Ili2AOpnAt1y8ywjjqtmkg==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.33.tgz", + "integrity": "sha512-4jpJHRD4ORv8PlbYi+/MfP8ec1okz6rybe36MdpkDrGIdEItHEUyaHSKvz+ptNEyQpALmmVfRteHkU9F8vxOew==", "requires": { - "@vue/compiler-ssr": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-ssr": "3.2.33", + "@vue/shared": "3.2.33" } }, "@vue/shared": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.31.tgz", - "integrity": "sha512-ymN2pj6zEjiKJZbrf98UM2pfDd6F2H7ksKw7NDt/ZZ1fh5Ei39X5tABugtT03ZRlWd9imccoK0hE8hpjpU7irQ==" + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.33.tgz", + "integrity": "sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==" }, "@webassemblyjs/ast": { "version": "1.11.1", @@ -11318,13 +11357,18 @@ "lodash": "^4.17.14" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "autoprefixer": { - "version": "10.4.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.4.tgz", - "integrity": "sha512-Tm8JxsB286VweiZ5F0anmbyGiNI3v3wGv3mz9W+cxEDYB/6jbnj6GM9H9mK3wIL8ftgl+C07Lcwb8PG5PCCPzA==", + "version": "10.4.7", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", + "integrity": "sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==", "requires": { - "browserslist": "^4.20.2", - "caniuse-lite": "^1.0.30001317", + "browserslist": "^4.20.3", + "caniuse-lite": "^1.0.30001335", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -11332,11 +11376,12 @@ } }, "axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", "requires": { - "follow-redirects": "^1.14.8" + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" } }, "babel-loader": { @@ -11587,14 +11632,14 @@ } }, "browserslist": { - "version": "4.20.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", - "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", "requires": { - "caniuse-lite": "^1.0.30001317", - "electron-to-chromium": "^1.4.84", + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", "escalade": "^3.1.1", - "node-releases": "^2.0.2", + "node-releases": "^2.0.3", "picocolors": "^1.0.0" } }, @@ -11668,9 +11713,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001325", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001325.tgz", - "integrity": "sha512-sB1bZHjseSjDtijV1Hb7PB2Zd58Kyx+n/9EotvZ4Qcz2K3d0lWB8dB4nb8wN/TsOGFq3UuAm0zQZNQ4SoR7TrQ==" + "version": "1.0.30001335", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001335.tgz", + "integrity": "sha512-ddP1Tgm7z2iIxu6QTtbZUv6HJxSaV/PZeSrWFZtbY4JZ69tOeNhBCl3HyRQgeNZKE5AOn1kpV7fhljigy0Ty3w==" }, "chalk": { "version": "4.1.2", @@ -11796,6 +11841,14 @@ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "optional": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -12219,6 +12272,11 @@ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=" }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -12402,9 +12460,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { - "version": "1.4.104", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.104.tgz", - "integrity": "sha512-2kjoAyiG7uMyGRM9mx25s3HAzmQG2ayuYXxsFmYugHSDcwxREgLtscZvbL1JcW9S/OemeQ3f/SG6JhDwpnCclQ==" + "version": "1.4.132", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.132.tgz", + "integrity": "sha512-JYdZUw/1068NWN+SwXQ7w6Ue0bWYGihvSUNNQwurvcDV/SM7vSiGZ3NuFvFgoEiCs4kB8xs3cX2an3wB7d4TBw==" }, "elliptic": { "version": "6.5.4", @@ -12491,12 +12549,12 @@ "dev": true }, "eslint": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", - "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz", + "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.2.1", + "@eslint/eslintrc": "^1.2.2", "@humanwhocodes/config-array": "^0.9.2", "ajv": "^6.10.0", "chalk": "^4.0.0", @@ -12545,13 +12603,15 @@ } }, "eslint-plugin-vue": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.6.0.tgz", - "integrity": "sha512-abXiF2J18n/7ZPy9foSlJyouKf54IqpKlNvNmzhM93N0zs3QUxZG/oBd3tVPOJTKg7SlhBUtPxugpqzNbgGpQQ==", + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", + "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", "dev": true, "requires": { "eslint-utils": "^3.0.0", "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", "semver": "^7.3.5", "vue-eslint-parser": "^8.0.1" } @@ -12910,9 +12970,9 @@ } }, "flatpickr": { - "version": "4.6.11", - "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.11.tgz", - "integrity": "sha512-/rnbE/hu5I5zndLEyYfYvqE4vPDvI5At0lFcQA5eOPfjquZLcQ0HMKTL7rv5/+DvbPM3/vJcXpXjB/DjBh+1jw==" + "version": "4.6.13", + "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz", + "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==" }, "flatted": { "version": "3.2.5", @@ -12925,6 +12985,16 @@ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -13751,9 +13821,9 @@ } }, "luxon": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.3.1.tgz", - "integrity": "sha512-I8vnjOmhXsMSlNMZlMkSOvgrxKJl0uOsEzdGgGNZuZPaS9KlefpE9KV95QFftlJSC+1UyCC9/I69R02cz/zcCA==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-2.3.2.tgz", + "integrity": "sha512-MlAQQVMFhGk4WUA6gpfsy0QycnKP0+NlCBJRVRNPxxSIbjrCbQ65nrpJD3FVyJNZLuJ0uoqL57ye6BmDYgHaSw==" }, "magic-string": { "version": "0.25.9", @@ -13957,9 +14027,9 @@ } }, "nanoid": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.2.tgz", - "integrity": "sha512-CuHBogktKwpm5g2sRgv83jEy2ijFzBwMoYA60orPDR7ynsLijJDqgsi4RDGj3OJpy3Ieb+LYwiRmIOGyytgITA==" + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" }, "natural-compare": { "version": "1.4.0", @@ -14035,9 +14105,9 @@ } }, "node-releases": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==" }, "normalize-path": { "version": "3.0.0", @@ -14081,9 +14151,9 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-hash": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz", - "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==" }, "object-inspect": { "version": "1.12.0", @@ -14349,11 +14419,11 @@ } }, "postcss": { - "version": "8.4.12", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.12.tgz", - "integrity": "sha512-lg6eITwYe9v6Hr5CncVbK70SoioNQIq81nsaG86ev5hAidQvmOeETBqs7jm43K2F5/Ley3ytDtriImV6TpNiSg==", + "version": "8.4.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.13.tgz", + "integrity": "sha512-jtL6eTBrza5MPzy8oJLFuUscHDXTV5KcLlqAWHl5q5WYRfnNRGSmOZmOZ1T6Gy7A99mOZfqungmZMpMmCVJ8ZA==", "requires": { - "nanoid": "^3.3.1", + "nanoid": "^3.3.3", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -15423,28 +15493,28 @@ } }, "tailwindcss": { - "version": "3.0.23", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.23.tgz", - "integrity": "sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==", + "version": "3.0.24", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.0.24.tgz", + "integrity": "sha512-H3uMmZNWzG6aqmg9q07ZIRNIawoiEcNFKDfL+YzOPuPsXuDXxJxB9icqzLgdzKNwjG3SAro2h9SYav8ewXNgig==", "requires": { "arg": "^5.0.1", - "chalk": "^4.1.2", "chokidar": "^3.5.3", "color-name": "^1.1.4", - "cosmiconfig": "^7.0.1", "detective": "^5.2.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.2.11", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", + "lilconfig": "^2.0.5", "normalize-path": "^3.0.0", - "object-hash": "^2.2.0", - "postcss": "^8.4.6", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.12", "postcss-js": "^4.0.0", - "postcss-load-config": "^3.1.0", + "postcss-load-config": "^3.1.4", "postcss-nested": "5.0.6", - "postcss-selector-parser": "^6.0.9", + "postcss-selector-parser": "^6.0.10", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.0" @@ -15690,15 +15760,15 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==" }, "vue": { - "version": "3.2.31", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.31.tgz", - "integrity": "sha512-odT3W2tcffTiQCy57nOT93INw1auq5lYLLYtWpPYQQYQOOdHiqFct9Xhna6GJ+pJQaF67yZABraH47oywkJgFw==", + "version": "3.2.33", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.33.tgz", + "integrity": "sha512-si1ExAlDUrLSIg/V7D/GgA4twJwfsfgG+t9w10z38HhL/HA07132pUQ2KuwAo8qbCyMJ9e6OqrmWrOCr+jW7ZQ==", "requires": { - "@vue/compiler-dom": "3.2.31", - "@vue/compiler-sfc": "3.2.31", - "@vue/runtime-dom": "3.2.31", - "@vue/server-renderer": "3.2.31", - "@vue/shared": "3.2.31" + "@vue/compiler-dom": "3.2.33", + "@vue/compiler-sfc": "3.2.33", + "@vue/runtime-dom": "3.2.33", + "@vue/server-renderer": "3.2.33", + "@vue/shared": "3.2.33" } }, "vue-echarts": { @@ -15734,9 +15804,9 @@ } }, "vue-flatpickr-component": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-9.0.5.tgz", - "integrity": "sha512-fKuz/D4ePQKi+jPo4xjYRgBCLTWrTsCoKbx8nam63x4kTDtSqvFOjNwLvy0QgwC0lC+aFpUWa1dNYTH0hgUcCA==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/vue-flatpickr-component/-/vue-flatpickr-component-9.0.6.tgz", + "integrity": "sha512-U3355po5WPejAagvDig+MA7v8NWr0+Dbx3a1pds19hx4i9CeXuBSpD7vl0fxKhk+Hfu3T+DN2aOR69HIwSJh1A==", "requires": { "flatpickr": "^4.6.9" } diff --git a/package.json b/package.json index 8896792..b28049d 100644 --- a/package.json +++ b/package.json @@ -13,36 +13,36 @@ "postinstall": "npm run prod" }, "dependencies": { - "@headlessui/vue": "^1.5.0", + "@headlessui/vue": "^1.6.1", "@heroicons/vue": "^1.0.6", "@inertiajs/inertia": "^0.11.0", "@inertiajs/inertia-vue3": "^0.6.0", "@inertiajs/progress": "^0.2.7", - "@tailwindcss/forms": "^0.5.0", - "@tailwindcss/line-clamp": "^0.3.1", + "@tailwindcss/forms": "^0.5.1", + "@tailwindcss/line-clamp": "^0.4.0", "@tailwindcss/typography": "^0.5.2", - "@vue/compiler-sfc": "^3.2.31", - "autoprefixer": "^10.4.4", - "axios": "^0.26.1", + "@vue/compiler-sfc": "^3.2.33", + "autoprefixer": "^10.4.7", + "axios": "^0.27.2", "echarts": "^5.3.2", "eslit": "^6.0.0", - "flatpickr": "^4.6.11", + "flatpickr": "^4.6.13", "laravel-mix": "^6.0.43", "lodash": "^4.17.21", - "luxon": "^2.3.1", - "postcss": "^8.4.12", - "tailwindcss": "^3.0.23", - "vue": "^3.2.31", + "luxon": "^2.3.2", + "postcss": "^8.4.13", + "tailwindcss": "^3.0.24", + "vue": "^3.2.33", "vue-echarts": "^6.0.2", - "vue-flatpickr-component": "^9.0.5", + "vue-flatpickr-component": "^9.0.6", "vue-loader": "^17.0.0", "vue-material-design-icons": "^5.0.0", "vue-toastification": "^2.0.0-rc.5", "vue3-popper": "^1.4.2" }, "devDependencies": { - "eslint": "^8.12.0", + "eslint": "^8.14.0", "eslint-plugin-tailwindcss": "^3.5.0", - "eslint-plugin-vue": "^8.5.0" + "eslint-plugin-vue": "^8.7.1" } } From 497f47068c7e0cf858b8744eb593fead581c634c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 May 2022 08:34:13 +0200 Subject: [PATCH 7/9] #5 - (php) Bump laravel/framework from 9.9.0 to 9.10.1 (#140) * #5 - (php) Bump laravel/framework from 9.9.0 to 9.10.1 Bumps [laravel/framework](https://github.com/laravel/framework) from 9.9.0 to 9.10.1. - [Release notes](https://github.com/laravel/framework/releases) - [Changelog](https://github.com/laravel/framework/blob/9.x/CHANGELOG.md) - [Commits](https://github.com/laravel/framework/compare/v9.9.0...v9.10.1) --- updated-dependencies: - dependency-name: laravel/framework dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * #5 - May 2022 composer update Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: EwelinaLasowy --- composer.json | 2 +- composer.lock | 333 ++++++++++++++------------------- docker-compose.yml | 8 +- environment/dev/php/Dockerfile | 2 +- 4 files changed, 146 insertions(+), 199 deletions(-) diff --git a/composer.json b/composer.json index 155b43e..72dce70 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "ext-redis": "*", "azuyalabs/yasumi": "^2.4", "barryvdh/laravel-dompdf": "^1.0", - "fruitcake/laravel-cors": "^2.0", + "fruitcake/laravel-cors": "^3.0", "guzzlehttp/guzzle": "^7.0.1", "inertiajs/inertia-laravel": "^0.5.1", "laravel/framework": "^9.7", diff --git a/composer.lock b/composer.lock index 1de54b9..69e26db 100644 --- a/composer.lock +++ b/composer.lock @@ -4,64 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "572998c0dff042cc8ddf65cb1b7348c9", + "content-hash": "c23bb050dbab6338570f0f73adb83cf8", "packages": [ - { - "name": "asm89/stack-cors", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/asm89/stack-cors.git", - "reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/asm89/stack-cors/zipball/73e5b88775c64ccc0b84fb60836b30dc9d92ac4a", - "reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0", - "symfony/http-foundation": "^4|^5|^6", - "symfony/http-kernel": "^4|^5|^6" - }, - "require-dev": { - "phpunit/phpunit": "^7|^9", - "squizlabs/php_codesniffer": "^3.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "psr-4": { - "Asm89\\Stack\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alexander", - "email": "iam.asm89@gmail.com" - } - ], - "description": "Cross-origin resource sharing library and stack middleware", - "homepage": "https://github.com/asm89/stack-cors", - "keywords": [ - "cors", - "stack" - ], - "support": { - "issues": "https://github.com/asm89/stack-cors/issues", - "source": "https://github.com/asm89/stack-cors/tree/v2.1.1" - }, - "time": "2022-01-18T09:12:03+00:00" - }, { "name": "azuyalabs/yasumi", "version": "2.5.0", @@ -515,16 +459,16 @@ }, { "name": "dompdf/dompdf", - "version": "v1.2.1", + "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "c6dfd9bb8b0040609f04754f729d4cb3016e0575" + "reference": "5031045d9640b38cfc14aac9667470df09c9e090" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/c6dfd9bb8b0040609f04754f729d4cb3016e0575", - "reference": "c6dfd9bb8b0040609f04754f729d4cb3016e0575", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/5031045d9640b38cfc14aac9667470df09c9e090", + "reference": "5031045d9640b38cfc14aac9667470df09c9e090", "shasum": "" }, "require": { @@ -535,6 +479,8 @@ "php": "^7.1 || ^8.0" }, "require-dev": { + "ext-json": "*", + "ext-zip": "*", "mockery/mockery": "^1.3", "phpunit/phpunit": "^7.5 || ^8 || ^9", "squizlabs/php_codesniffer": "^3.5" @@ -576,9 +522,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v1.2.1" + "source": "https://github.com/dompdf/dompdf/tree/v1.2.2" }, - "time": "2022-03-24T12:57:42+00:00" + "time": "2022-04-27T13:50:54+00:00" }, { "name": "dragonmantank/cron-expression", @@ -872,34 +818,34 @@ }, { "name": "fruitcake/laravel-cors", - "version": "v2.2.0", + "version": "v3.0.0", "source": { "type": "git", "url": "https://github.com/fruitcake/laravel-cors.git", - "reference": "783a74f5e3431d7b9805be8afb60fd0a8f743534" + "reference": "7c036ec08972d8d5d9db637e772af6887828faf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/783a74f5e3431d7b9805be8afb60fd0a8f743534", - "reference": "783a74f5e3431d7b9805be8afb60fd0a8f743534", + "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/7c036ec08972d8d5d9db637e772af6887828faf5", + "reference": "7c036ec08972d8d5d9db637e772af6887828faf5", "shasum": "" }, "require": { - "asm89/stack-cors": "^2.0.1", + "fruitcake/php-cors": "^1.2", "illuminate/contracts": "^6|^7|^8|^9", "illuminate/support": "^6|^7|^8|^9", - "php": ">=7.2" + "php": "^7.4|^8.0" }, "require-dev": { "laravel/framework": "^6|^7.24|^8", "orchestra/testbench-dusk": "^4|^5|^6|^7", - "phpunit/phpunit": "^6|^7|^8|^9", + "phpunit/phpunit": "^9", "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.1-dev" + "dev-master": "3.0-dev" }, "laravel": { "providers": [ @@ -935,7 +881,7 @@ ], "support": { "issues": "https://github.com/fruitcake/laravel-cors/issues", - "source": "https://github.com/fruitcake/laravel-cors/tree/v2.2.0" + "source": "https://github.com/fruitcake/laravel-cors/tree/v3.0.0" }, "funding": [ { @@ -947,7 +893,7 @@ "type": "github" } ], - "time": "2022-02-23T14:25:13+00:00" + "time": "2022-02-23T14:53:22+00:00" }, { "name": "fruitcake/php-cors", @@ -1093,16 +1039,16 @@ }, { "name": "google/apiclient-services", - "version": "v0.246.0", + "version": "v0.247.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "33aef1ccce34799a1124c39951fed8ad0b16aced" + "reference": "1fc6eab7512b4e2dd4b6c96b2697f9b6bfbaddc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/33aef1ccce34799a1124c39951fed8ad0b16aced", - "reference": "33aef1ccce34799a1124c39951fed8ad0b16aced", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/1fc6eab7512b4e2dd4b6c96b2697f9b6bfbaddc2", + "reference": "1fc6eab7512b4e2dd4b6c96b2697f9b6bfbaddc2", "shasum": "" }, "require": { @@ -1131,9 +1077,9 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.246.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.247.0" }, - "time": "2022-04-24T00:58:37+00:00" + "time": "2022-05-02T01:12:12+00:00" }, { "name": "google/auth", @@ -1733,16 +1679,16 @@ }, { "name": "laravel/framework", - "version": "v9.9.0", + "version": "v9.11.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "4d5a07640891b772188d7737348886a0222737d8" + "reference": "598a8c84d452a66b90a3213b1d67189cc726c728" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/4d5a07640891b772188d7737348886a0222737d8", - "reference": "4d5a07640891b772188d7737348886a0222737d8", + "url": "https://api.github.com/repos/laravel/framework/zipball/598a8c84d452a66b90a3213b1d67189cc726c728", + "reference": "598a8c84d452a66b90a3213b1d67189cc726c728", "shasum": "" }, "require": { @@ -1908,7 +1854,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-04-19T15:01:23+00:00" + "time": "2022-05-03T14:47:20+00:00" }, { "name": "laravel/helpers", @@ -2161,16 +2107,16 @@ }, { "name": "laravel/telescope", - "version": "v4.8.3", + "version": "v4.9.0", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "bb23d58161032c8745d38348452afcbcd8adfc78" + "reference": "d0cf8d6a54a1831dbe189a1f194e8271a4a5435a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/bb23d58161032c8745d38348452afcbcd8adfc78", - "reference": "bb23d58161032c8745d38348452afcbcd8adfc78", + "url": "https://api.github.com/repos/laravel/telescope/zipball/d0cf8d6a54a1831dbe189a1f194e8271a4a5435a", + "reference": "d0cf8d6a54a1831dbe189a1f194e8271a4a5435a", "shasum": "" }, "require": { @@ -2223,9 +2169,9 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v4.8.3" + "source": "https://github.com/laravel/telescope/tree/v4.9.0" }, - "time": "2022-04-11T14:29:02+00:00" + "time": "2022-04-19T15:48:51+00:00" }, { "name": "laravel/tinker", @@ -2648,16 +2594,16 @@ }, { "name": "league/flysystem", - "version": "3.0.17", + "version": "3.0.19", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "29eb78cac0be0c22237c5e0f6f98234d97037d79" + "reference": "670df21225d68d165a8df38587ac3f41caf608f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/29eb78cac0be0c22237c5e0f6f98234d97037d79", - "reference": "29eb78cac0be0c22237c5e0f6f98234d97037d79", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/670df21225d68d165a8df38587ac3f41caf608f8", + "reference": "670df21225d68d165a8df38587ac3f41caf608f8", "shasum": "" }, "require": { @@ -2718,7 +2664,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.0.17" + "source": "https://github.com/thephpleague/flysystem/tree/3.0.19" }, "funding": [ { @@ -2734,7 +2680,7 @@ "type": "tidelift" } ], - "time": "2022-04-14T14:57:13+00:00" + "time": "2022-05-03T21:19:02+00:00" }, { "name": "league/mime-type-detection", @@ -2870,16 +2816,16 @@ }, { "name": "maatwebsite/excel", - "version": "3.1.39", + "version": "3.1.40", "source": { "type": "git", "url": "https://github.com/SpartnerNL/Laravel-Excel.git", - "reference": "5165334de44c6f7788a5818a1d019aa71a43e092" + "reference": "8a54972e3d616c74687c3cbff15765555761885c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/5165334de44c6f7788a5818a1d019aa71a43e092", - "reference": "5165334de44c6f7788a5818a1d019aa71a43e092", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/8a54972e3d616c74687c3cbff15765555761885c", + "reference": "8a54972e3d616c74687c3cbff15765555761885c", "shasum": "" }, "require": { @@ -2932,7 +2878,7 @@ ], "support": { "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", - "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.39" + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.40" }, "funding": [ { @@ -2944,7 +2890,7 @@ "type": "github" } ], - "time": "2022-04-23T11:44:18+00:00" + "time": "2022-05-02T13:50:01+00:00" }, { "name": "maennchen/zipstream-php", @@ -3335,16 +3281,16 @@ }, { "name": "nesbot/carbon", - "version": "2.57.0", + "version": "2.58.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "4a54375c21eea4811dbd1149fe6b246517554e78" + "reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4a54375c21eea4811dbd1149fe6b246517554e78", - "reference": "4a54375c21eea4811dbd1149fe6b246517554e78", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/97a34af22bde8d0ac20ab34b29d7bfe360902055", + "reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055", "shasum": "" }, "require": { @@ -3362,7 +3308,8 @@ "phpmd/phpmd": "^2.9", "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^0.12.54 || ^1.0", - "phpunit/phpunit": "^7.5.20 || ^8.5.14", + "phpunit/php-file-iterator": "^2.0.5", + "phpunit/phpunit": "^7.5.20 || ^8.5.23", "squizlabs/php_codesniffer": "^3.4" }, "bin": [ @@ -3427,7 +3374,7 @@ "type": "tidelift" } ], - "time": "2022-02-13T18:13:33+00:00" + "time": "2022-04-25T19:31:17+00:00" }, { "name": "nette/schema", @@ -5296,16 +5243,16 @@ }, { "name": "symfony/console", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "70dcf7b2ca2ea08ad6ebcc475f104a024fb5632e" + "reference": "0d00aa289215353aa8746a31d101f8e60826285c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/70dcf7b2ca2ea08ad6ebcc475f104a024fb5632e", - "reference": "70dcf7b2ca2ea08ad6ebcc475f104a024fb5632e", + "url": "https://api.github.com/repos/symfony/console/zipball/0d00aa289215353aa8746a31d101f8e60826285c", + "reference": "0d00aa289215353aa8746a31d101f8e60826285c", "shasum": "" }, "require": { @@ -5371,7 +5318,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.7" + "source": "https://github.com/symfony/console/tree/v6.0.8" }, "funding": [ { @@ -5387,7 +5334,7 @@ "type": "tidelift" } ], - "time": "2022-03-31T17:18:25+00:00" + "time": "2022-04-20T15:01:42+00:00" }, { "name": "symfony/css-selector", @@ -5523,16 +5470,16 @@ }, { "name": "symfony/error-handler", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "e600c54e5b30555eecea3ffe4314e58f832e78ee" + "reference": "5e2795163acbd13b3cd46835c9f8f6c5d0a3a280" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/e600c54e5b30555eecea3ffe4314e58f832e78ee", - "reference": "e600c54e5b30555eecea3ffe4314e58f832e78ee", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/5e2795163acbd13b3cd46835c9f8f6c5d0a3a280", + "reference": "5e2795163acbd13b3cd46835c9f8f6c5d0a3a280", "shasum": "" }, "require": { @@ -5574,7 +5521,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.0.7" + "source": "https://github.com/symfony/error-handler/tree/v6.0.8" }, "funding": [ { @@ -5590,7 +5537,7 @@ "type": "tidelift" } ], - "time": "2022-03-18T16:21:55+00:00" + "time": "2022-04-12T16:11:42+00:00" }, { "name": "symfony/event-dispatcher", @@ -5756,16 +5703,16 @@ }, { "name": "symfony/finder", - "version": "v6.0.3", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "8661b74dbabc23223f38c9b99d3f8ade71170430" + "reference": "af7edab28d17caecd1f40a9219fc646ae751c21f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/8661b74dbabc23223f38c9b99d3f8ade71170430", - "reference": "8661b74dbabc23223f38c9b99d3f8ade71170430", + "url": "https://api.github.com/repos/symfony/finder/zipball/af7edab28d17caecd1f40a9219fc646ae751c21f", + "reference": "af7edab28d17caecd1f40a9219fc646ae751c21f", "shasum": "" }, "require": { @@ -5797,7 +5744,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.0.3" + "source": "https://github.com/symfony/finder/tree/v6.0.8" }, "funding": [ { @@ -5813,20 +5760,20 @@ "type": "tidelift" } ], - "time": "2022-01-26T17:23:29+00:00" + "time": "2022-04-15T08:07:58+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "c816b26f03b6902dba79b352c84a17f53d815f0d" + "reference": "c9c86b02d7ef6f44f3154acc7de42831518afe7c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/c816b26f03b6902dba79b352c84a17f53d815f0d", - "reference": "c816b26f03b6902dba79b352c84a17f53d815f0d", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/c9c86b02d7ef6f44f3154acc7de42831518afe7c", + "reference": "c9c86b02d7ef6f44f3154acc7de42831518afe7c", "shasum": "" }, "require": { @@ -5869,7 +5816,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.0.7" + "source": "https://github.com/symfony/http-foundation/tree/v6.0.8" }, "funding": [ { @@ -5885,20 +5832,20 @@ "type": "tidelift" } ], - "time": "2022-03-24T14:13:59+00:00" + "time": "2022-04-22T08:18:02+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "9c03dab07a6aa336ffaadc15352b1d14f4ce01f5" + "reference": "7aaf1cdc9cc2ad47e926f624efcb679883a39ca7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/9c03dab07a6aa336ffaadc15352b1d14f4ce01f5", - "reference": "9c03dab07a6aa336ffaadc15352b1d14f4ce01f5", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/7aaf1cdc9cc2ad47e926f624efcb679883a39ca7", + "reference": "7aaf1cdc9cc2ad47e926f624efcb679883a39ca7", "shasum": "" }, "require": { @@ -5978,7 +5925,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.0.7" + "source": "https://github.com/symfony/http-kernel/tree/v6.0.8" }, "funding": [ { @@ -5994,20 +5941,20 @@ "type": "tidelift" } ], - "time": "2022-04-02T06:35:11+00:00" + "time": "2022-04-27T17:26:02+00:00" }, { "name": "symfony/mailer", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "f7343f94e7afecca2ad840b078f9d80200e1bd27" + "reference": "706af6b3e99ebcbc639c9c664f5579aaa869409b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/f7343f94e7afecca2ad840b078f9d80200e1bd27", - "reference": "f7343f94e7afecca2ad840b078f9d80200e1bd27", + "url": "https://api.github.com/repos/symfony/mailer/zipball/706af6b3e99ebcbc639c9c664f5579aaa869409b", + "reference": "706af6b3e99ebcbc639c9c664f5579aaa869409b", "shasum": "" }, "require": { @@ -6052,7 +5999,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.0.7" + "source": "https://github.com/symfony/mailer/tree/v6.0.8" }, "funding": [ { @@ -6068,20 +6015,20 @@ "type": "tidelift" } ], - "time": "2022-03-18T16:06:28+00:00" + "time": "2022-04-27T17:10:30+00:00" }, { "name": "symfony/mime", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "74266e396f812a2301536397a6360b6e6913c0d8" + "reference": "c1701e88ad0ca49fc6ad6cdf360bc0e1209fb5e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/74266e396f812a2301536397a6360b6e6913c0d8", - "reference": "74266e396f812a2301536397a6360b6e6913c0d8", + "url": "https://api.github.com/repos/symfony/mime/zipball/c1701e88ad0ca49fc6ad6cdf360bc0e1209fb5e1", + "reference": "c1701e88ad0ca49fc6ad6cdf360bc0e1209fb5e1", "shasum": "" }, "require": { @@ -6133,7 +6080,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.0.7" + "source": "https://github.com/symfony/mime/tree/v6.0.8" }, "funding": [ { @@ -6149,7 +6096,7 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:10:05+00:00" + "time": "2022-04-12T16:11:42+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6808,16 +6755,16 @@ }, { "name": "symfony/process", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "e13f6757e267d687e20ec5b26ccfcbbe511cd8f4" + "reference": "d074154ea8b1443a96391f6e39f9e547b2dd01b9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/e13f6757e267d687e20ec5b26ccfcbbe511cd8f4", - "reference": "e13f6757e267d687e20ec5b26ccfcbbe511cd8f4", + "url": "https://api.github.com/repos/symfony/process/zipball/d074154ea8b1443a96391f6e39f9e547b2dd01b9", + "reference": "d074154ea8b1443a96391f6e39f9e547b2dd01b9", "shasum": "" }, "require": { @@ -6849,7 +6796,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.7" + "source": "https://github.com/symfony/process/tree/v6.0.8" }, "funding": [ { @@ -6865,20 +6812,20 @@ "type": "tidelift" } ], - "time": "2022-03-18T16:21:55+00:00" + "time": "2022-04-12T16:11:42+00:00" }, { "name": "symfony/routing", - "version": "v6.0.5", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "a738b152426ac7fcb94bdab8188264652238bef1" + "reference": "74c40c9fc334acc601a32fcf4274e74fb3bac11e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/a738b152426ac7fcb94bdab8188264652238bef1", - "reference": "a738b152426ac7fcb94bdab8188264652238bef1", + "url": "https://api.github.com/repos/symfony/routing/zipball/74c40c9fc334acc601a32fcf4274e74fb3bac11e", + "reference": "74c40c9fc334acc601a32fcf4274e74fb3bac11e", "shasum": "" }, "require": { @@ -6937,7 +6884,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.5" + "source": "https://github.com/symfony/routing/tree/v6.0.8" }, "funding": [ { @@ -6953,7 +6900,7 @@ "type": "tidelift" } ], - "time": "2022-01-31T19:46:53+00:00" + "time": "2022-04-22T08:18:02+00:00" }, { "name": "symfony/service-contracts", @@ -7039,16 +6986,16 @@ }, { "name": "symfony/string", - "version": "v6.0.3", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2" + "reference": "ac0aa5c2282e0de624c175b68d13f2c8f2e2649d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/522144f0c4c004c80d56fa47e40e17028e2eefc2", - "reference": "522144f0c4c004c80d56fa47e40e17028e2eefc2", + "url": "https://api.github.com/repos/symfony/string/zipball/ac0aa5c2282e0de624c175b68d13f2c8f2e2649d", + "reference": "ac0aa5c2282e0de624c175b68d13f2c8f2e2649d", "shasum": "" }, "require": { @@ -7104,7 +7051,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.3" + "source": "https://github.com/symfony/string/tree/v6.0.8" }, "funding": [ { @@ -7120,20 +7067,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-04-22T08:18:02+00:00" }, { "name": "symfony/translation", - "version": "v6.0.7", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b2792b39d74cf41ea3065f27fd2ddf0b556ac7a1" + "reference": "3d38cf8f8834148c4457681d539bc204de701501" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b2792b39d74cf41ea3065f27fd2ddf0b556ac7a1", - "reference": "b2792b39d74cf41ea3065f27fd2ddf0b556ac7a1", + "url": "https://api.github.com/repos/symfony/translation/zipball/3d38cf8f8834148c4457681d539bc204de701501", + "reference": "3d38cf8f8834148c4457681d539bc204de701501", "shasum": "" }, "require": { @@ -7199,7 +7146,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.7" + "source": "https://github.com/symfony/translation/tree/v6.0.8" }, "funding": [ { @@ -7215,7 +7162,7 @@ "type": "tidelift" } ], - "time": "2022-03-31T17:18:25+00:00" + "time": "2022-04-22T08:18:02+00:00" }, { "name": "symfony/translation-contracts", @@ -7297,16 +7244,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.0.6", + "version": "v6.0.8", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "38358405ae948963c50a3aae3dfea598223ba15e" + "reference": "fa61dfb4bd3068df2492013dc65f3190e9f550c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/38358405ae948963c50a3aae3dfea598223ba15e", - "reference": "38358405ae948963c50a3aae3dfea598223ba15e", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fa61dfb4bd3068df2492013dc65f3190e9f550c0", + "reference": "fa61dfb4bd3068df2492013dc65f3190e9f550c0", "shasum": "" }, "require": { @@ -7365,7 +7312,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.0.6" + "source": "https://github.com/symfony/var-dumper/tree/v6.0.8" }, "funding": [ { @@ -7381,7 +7328,7 @@ "type": "tidelift" } ], - "time": "2022-03-02T12:58:14+00:00" + "time": "2022-04-26T13:22:23+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -8388,16 +8335,16 @@ }, { "name": "laravel/dusk", - "version": "v6.23.0", + "version": "v6.23.1", "source": { "type": "git", "url": "https://github.com/laravel/dusk.git", - "reference": "98901d49176977c96330fd8c2ca5460eee50a246" + "reference": "41f6deb42ae42b9b7dae1c32c03cb35d365d3118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/dusk/zipball/98901d49176977c96330fd8c2ca5460eee50a246", - "reference": "98901d49176977c96330fd8c2ca5460eee50a246", + "url": "https://api.github.com/repos/laravel/dusk/zipball/41f6deb42ae42b9b7dae1c32c03cb35d365d3118", + "reference": "41f6deb42ae42b9b7dae1c32c03cb35d365d3118", "shasum": "" }, "require": { @@ -8455,9 +8402,9 @@ ], "support": { "issues": "https://github.com/laravel/dusk/issues", - "source": "https://github.com/laravel/dusk/tree/v6.23.0" + "source": "https://github.com/laravel/dusk/tree/v6.23.1" }, - "time": "2022-04-11T18:55:12+00:00" + "time": "2022-05-02T14:01:47+00:00" }, { "name": "mockery/mockery", @@ -8842,16 +8789,16 @@ }, { "name": "php-webdriver/webdriver", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/php-webdriver/php-webdriver.git", - "reference": "99d4856ed7dffcdf6a52eccd6551e83d8d557ceb" + "reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/99d4856ed7dffcdf6a52eccd6551e83d8d557ceb", - "reference": "99d4856ed7dffcdf6a52eccd6551e83d8d557ceb", + "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/b27ddf458d273c7d4602106fcaf978aa0b7fe15a", + "reference": "b27ddf458d273c7d4602106fcaf978aa0b7fe15a", "shasum": "" }, "require": { @@ -8901,9 +8848,9 @@ ], "support": { "issues": "https://github.com/php-webdriver/php-webdriver/issues", - "source": "https://github.com/php-webdriver/php-webdriver/tree/1.12.0" + "source": "https://github.com/php-webdriver/php-webdriver/tree/1.12.1" }, - "time": "2021-10-14T09:30:02+00:00" + "time": "2022-05-03T12:16:34+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -11057,5 +11004,5 @@ "ext-redis": "*" }, "platform-dev": [], - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.3.0" } diff --git a/docker-compose.yml b/docker-compose.yml index 6e14c5d..b4df020 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -35,7 +35,7 @@ services: restart: unless-stopped database: - image: postgres:13 + image: postgres:14 container_name: toby-db-dev environment: - PGPASSWORD=${DOCKER_DEV_DB_ROOT_PASSWORD} @@ -51,7 +51,7 @@ services: restart: unless-stopped database-test: - image: postgres:13 + image: postgres:14 container_name: toby-db-test environment: - PGPASSWORD=${DOCKER_TEST_DB_ROOT_PASSWORD} @@ -65,7 +65,7 @@ services: restart: unless-stopped redis: - image: redis:6 + image: redis:7 container_name: toby-redis ports: - ${FORWARD_REDIS_PORT:-6379}:6379 @@ -76,7 +76,7 @@ services: restart: unless-stopped node: - image: node:17.2.0-alpine3.14 + image: node:18.1.0-alpine3.14 container_name: toby-node working_dir: /application volumes: diff --git a/environment/dev/php/Dockerfile b/environment/dev/php/Dockerfile index d068a6c..39e707c 100644 --- a/environment/dev/php/Dockerfile +++ b/environment/dev/php/Dockerfile @@ -1,6 +1,6 @@ FROM ghcr.io/blumilksoftware/php:8.1 -ARG XDEBUG_VERSION=3.1.2 +ARG XDEBUG_VERSION=3.1.4 ARG INSTALL_XDEBUG=false RUN if [ ${INSTALL_XDEBUG} = true ]; then \ From f4d928c6aeeb3e6f6f9a9ff502a7274d32f6dfc2 Mon Sep 17 00:00:00 2001 From: Ewelina Lasowy <56546832+EwelinaLasowy@users.noreply.github.com> Date: Fri, 6 May 2022 12:29:06 +0200 Subject: [PATCH 8/9] - UX fixes (#142) * - changed homeoffice icon color * - improved list of request on dashboard * - hide holidays if no data * - fix to holidays * - fix * - made forms looks better * - hide chart when user has no vacation limit * - linter fix * - fix to pdf attachment for vacation request --- .../Http/Resources/HolidayResource.php | 2 +- resources/js/Composables/vacationTypeInfo.js | 4 +-- resources/js/Pages/Dashboard.vue | 2 +- resources/js/Pages/Holidays/Create.vue | 2 +- resources/js/Pages/Users/Create.vue | 2 +- resources/js/Pages/VacationRequest/Create.vue | 7 ++-- resources/js/Pages/VacationRequest/Show.vue | 4 +-- .../Widgets/PendingVacationRequests.vue | 33 +++++++++++-------- .../Shared/Widgets/UserVacationRequests.vue | 31 +++++++++-------- resources/js/Shared/Widgets/VacationStats.vue | 2 +- .../views/pdf/vacation-request.blade.php | 2 +- 11 files changed, 51 insertions(+), 40 deletions(-) diff --git a/app/Infrastructure/Http/Resources/HolidayResource.php b/app/Infrastructure/Http/Resources/HolidayResource.php index 4b79b09..e1d6216 100644 --- a/app/Infrastructure/Http/Resources/HolidayResource.php +++ b/app/Infrastructure/Http/Resources/HolidayResource.php @@ -16,7 +16,7 @@ class HolidayResource extends JsonResource "id" => $this->id, "name" => $this->name, "date" => $this->date->toDateString(), - "isPast" => $this->date->isPast(), + "isPast" => $this->date->endOfDay()->isPast(), "displayDate" => $this->date->toDisplayString(), "dayOfWeek" => $this->date->dayName, ]; diff --git a/resources/js/Composables/vacationTypeInfo.js b/resources/js/Composables/vacationTypeInfo.js index 65ec983..3bd73b9 100644 --- a/resources/js/Composables/vacationTypeInfo.js +++ b/resources/js/Composables/vacationTypeInfo.js @@ -85,8 +85,8 @@ const types = [ text: 'Praca zdalna', value: 'home_office', icon: HomeCityIcon, - color: 'text-blumilk-500', - border: 'border-blumilk-500', + color: 'text-lime-500', + border: 'border-lime-500', }, ] diff --git a/resources/js/Pages/Dashboard.vue b/resources/js/Pages/Dashboard.vue index c048343..e633816 100644 --- a/resources/js/Pages/Dashboard.vue +++ b/resources/js/Pages/Dashboard.vue @@ -23,7 +23,7 @@ :remote-days="remoteDays.data" />
diff --git a/resources/js/Pages/Holidays/Create.vue b/resources/js/Pages/Holidays/Create.vue index 3e22292..4b8f3c1 100644 --- a/resources/js/Pages/Holidays/Create.vue +++ b/resources/js/Pages/Holidays/Create.vue @@ -1,6 +1,6 @@