From c71411465a03499caf98937857e95ec489e865b4 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Tue, 24 Sep 2024 15:17:35 +0100 Subject: [PATCH 01/59] First pass at better-handling those annoying Rollbars we keep getting --- .../Controllers/Assets/AssetsController.php | 34 ++++++++++++++----- .../lang/en-US/admin/hardware/message.php | 3 ++ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index dceaa9b08a41..315c86f72570 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -112,8 +112,10 @@ public function store(ImageUploadRequest $request) : RedirectResponse $settings = Setting::getSettings(); - $success = false; + $successes = 0; + $failures = 0; $serials = $request->input('serials'); + $last_succesful_asset = null; for ($a = 1; $a <= count($asset_tags); $a++) { $asset = new Asset(); @@ -200,20 +202,36 @@ public function store(ImageUploadRequest $request) : RedirectResponse $asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location); } - $success = true; - + $last_succesful_asset = $asset; + $successes++; + + } else { + $failures++; } } session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]); - if ($success) { + if ($successes > 0) { + if ($failures > 0) { + //some succeeded, some failed + return redirect()->to(Helper::getRedirectOption($request, $last_succesful_asset->id, 'Assets')) + ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['link' => route('hardware.show', ['hardware' => $last_succesful_asset->id]), 'id', 'tag' => e($last_succesful_asset->asset_tag)])) + ->with('warning', trans_choice('admin/hardware/message.create.partial_failure', $failures)); + } else { + if ($successes == 1) { + //the most common case, keeping it so we don't have to make every use of that translation string be trans_choice'ed + //and re-translated + return redirect()->to(Helper::getRedirectOption($request, $last_succesful_asset->id, 'Assets')) + ->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', ['hardware' => $last_succesful_asset->id]), 'id', 'tag' => e($last_succesful_asset->asset_tag)])); + } else { + //multi-success + return redirect()->to(Helper::getRedirectOption($request, $last_succesful_asset->id, 'Assets')) + ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['link' => route('hardware.show', ['hardware' => $last_succesful_asset->id]), 'id', 'tag' => e($last_succesful_asset->asset_tag)])); + } + } - return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) - ->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', ['hardware' => $asset->id]), 'id', 'tag' => e($asset->asset_tag)])); - - } return redirect()->back()->withInput()->withErrors($asset->getErrors()); diff --git a/resources/lang/en-US/admin/hardware/message.php b/resources/lang/en-US/admin/hardware/message.php index 041d32f56c90..a33aea1813e4 100644 --- a/resources/lang/en-US/admin/hardware/message.php +++ b/resources/lang/en-US/admin/hardware/message.php @@ -14,6 +14,9 @@ 'error' => 'Asset was not created, please try again. :(', 'success' => 'Asset created successfully. :)', 'success_linked' => 'Asset with tag :tag was created successfully. Click here to view.', + 'multi_success_linked' => 'Asset with tag :tag was created successfully. Click here to view.|:count assets were created succesfully. The last one was :tag. Click here to view.', + 'partial_success_linked' => 'Asset with tag :tag was created successfully. Click here to view.', + 'partial_failure' => 'An asset was unable to be created.|:count assets were unable to be created.' ], 'update' => [ From b6340532d7e34c31d65999e55440241935c6db60 Mon Sep 17 00:00:00 2001 From: Brady Wetherington Date: Tue, 24 Sep 2024 17:15:39 +0100 Subject: [PATCH 02/59] Improve the error and success messages and linking --- .../Controllers/Assets/AssetsController.php | 31 +++++++++---------- .../lang/en-US/admin/hardware/message.php | 5 ++- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index 315c86f72570..e37d7c59b36c 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -112,10 +112,10 @@ public function store(ImageUploadRequest $request) : RedirectResponse $settings = Setting::getSettings(); - $successes = 0; - $failures = 0; + $successes = []; + $failures = []; $serials = $request->input('serials'); - $last_succesful_asset = null; + $asset = null; for ($a = 1; $a <= count($asset_tags); $a++) { $asset = new Asset(); @@ -202,33 +202,32 @@ public function store(ImageUploadRequest $request) : RedirectResponse $asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location); } - $last_succesful_asset = $asset; - $successes++; + $successes[] = " $asset->id]) . "' style='color: white;'>" . e($asset->asset_tag) . ""; } else { - $failures++; + $failures[] = join(",", $asset->getErrors()->all()); } } session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]); - if ($successes > 0) { - if ($failures > 0) { + if ($successes) { + if ($failures) { //some succeeded, some failed - return redirect()->to(Helper::getRedirectOption($request, $last_succesful_asset->id, 'Assets')) - ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['link' => route('hardware.show', ['hardware' => $last_succesful_asset->id]), 'id', 'tag' => e($last_succesful_asset->asset_tag)])) - ->with('warning', trans_choice('admin/hardware/message.create.partial_failure', $failures)); + return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) //FIXME - not tested + ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)])) + ->with('warning', trans_choice('admin/hardware/message.create.partial_failure', $failures, ['failures' => join("; ", $failures)])); } else { - if ($successes == 1) { + if (count($successes) == 1) { //the most common case, keeping it so we don't have to make every use of that translation string be trans_choice'ed //and re-translated - return redirect()->to(Helper::getRedirectOption($request, $last_succesful_asset->id, 'Assets')) - ->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', ['hardware' => $last_succesful_asset->id]), 'id', 'tag' => e($last_succesful_asset->asset_tag)])); + return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) + ->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', ['hardware' => $asset->id]), 'id', 'tag' => e($asset->asset_tag)])); } else { //multi-success - return redirect()->to(Helper::getRedirectOption($request, $last_succesful_asset->id, 'Assets')) - ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['link' => route('hardware.show', ['hardware' => $last_succesful_asset->id]), 'id', 'tag' => e($last_succesful_asset->asset_tag)])); + return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) + ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)])); } } diff --git a/resources/lang/en-US/admin/hardware/message.php b/resources/lang/en-US/admin/hardware/message.php index a33aea1813e4..874888de9dd0 100644 --- a/resources/lang/en-US/admin/hardware/message.php +++ b/resources/lang/en-US/admin/hardware/message.php @@ -14,9 +14,8 @@ 'error' => 'Asset was not created, please try again. :(', 'success' => 'Asset created successfully. :)', 'success_linked' => 'Asset with tag :tag was created successfully. Click here to view.', - 'multi_success_linked' => 'Asset with tag :tag was created successfully. Click here to view.|:count assets were created succesfully. The last one was :tag. Click here to view.', - 'partial_success_linked' => 'Asset with tag :tag was created successfully. Click here to view.', - 'partial_failure' => 'An asset was unable to be created.|:count assets were unable to be created.' + 'multi_success_linked' => 'Asset with tag :links was created successfully.|:count assets were created succesfully. :links.', + 'partial_failure' => 'An asset was unable to be created. Reason: :failures|:count assets were unable to be created. Reasons: :failures', ], 'update' => [ From b29d032bf0250941a2a968c85c227bbee9449c81 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 15 Oct 2024 11:28:27 -0700 Subject: [PATCH 03/59] adds checkoutAssetMail class, and content method --- .../CheckoutAssetNotification.php | 30 -- composer.json | 2 + composer.lock | 416 ++++++++++-------- 3 files changed, 245 insertions(+), 203 deletions(-) diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php index b14796fb8c0f..e61d49bf5cc5 100644 --- a/app/Notifications/CheckoutAssetNotification.php +++ b/app/Notifications/CheckoutAssetNotification.php @@ -191,35 +191,5 @@ public function toGoogleChat() * @param mixed $notifiable * @return \Illuminate\Notifications\Messages\MailMessage */ - public function toMail() - { $this->item->load('assetstatus'); - $eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : ''; - $req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0; - $fields = []; - - // Check if the item has custom fields associated with it - if (($this->item->model) && ($this->item->model->fieldset)) { - $fields = $this->item->model->fieldset->fields; - } - $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); - - $message = (new MailMessage)->markdown('notifications.markdown.checkout-asset', - [ - 'item' => $this->item, - 'admin' => $this->admin, - 'status' => $this->item->assetstatus?->name, - 'note' => $this->note, - 'target' => $this->target, - 'fields' => $fields, - 'eula' => $eula, - 'req_accept' => $req_accept, - 'accept_url' => $accept_url, - 'last_checkout' => $this->last_checkout, - 'expected_checkin' => $this->expected_checkin, - ]) - ->subject(trans('mail.Confirm_asset_delivery')); - - return $message; - } } diff --git a/composer.json b/composer.json index 6d893125787c..b255f821cd73 100644 --- a/composer.json +++ b/composer.json @@ -63,6 +63,8 @@ "rollbar/rollbar-laravel": "^8.0", "spatie/laravel-backup": "^8.8", "spatie/laravel-ignition": "^2.0", + "symfony/http-client": "^7.1", + "symfony/mailgun-mailer": "^7.1", "tecnickcom/tc-lib-barcode": "^1.15", "tecnickcom/tcpdf": "^6.5", "unicodeveloper/laravel-password": "^1.0", diff --git a/composer.lock b/composer.lock index 3f79921b26df..c6e469c5978f 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": "3819ab4ef72eb77fabe494c0e746b83b", + "content-hash": "0378e36c927d3838ac338c4f58ed30cd", "packages": [ { "name": "alek13/slack", @@ -9081,6 +9081,178 @@ ], "time": "2024-08-13T14:27:37+00:00" }, + { + "name": "symfony/http-client", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T13:35:23+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/http-foundation", "version": "v6.4.12", @@ -9352,6 +9524,75 @@ ], "time": "2024-09-08T12:30:05+00:00" }, + { + "name": "symfony/mailgun-mailer", + "version": "v7.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailgun-mailer.git", + "reference": "dac02fe68e9306849703025511c56f10701696a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/dac02fe68e9306849703025511c56f10701696a8", + "reference": "dac02fe68e9306849703025511c56f10701696a8", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/mailer": "^6.4|^7.0" + }, + "conflict": { + "symfony/http-foundation": "<6.4" + }, + "require-dev": { + "symfony/http-client": "^6.4|^7.0", + "symfony/webhook": "^6.4|^7.0" + }, + "type": "symfony-mailer-bridge", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\Bridge\\Mailgun\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Mailgun Mailer Bridge", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailgun-mailer/tree/v7.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-04T11:20:59+00:00" + }, { "name": "symfony/mime", "version": "v6.4.12", @@ -16028,177 +16269,6 @@ ], "time": "2024-09-16T16:01:33+00:00" }, - { - "name": "symfony/http-client", - "version": "v6.4.12", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56", - "reference": "fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56", - "shasum": "" - }, - "require": { - "php": ">=8.1", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.3" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/http-kernel": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v6.4.12" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-20T08:21:33+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/options-resolver", "version": "v6.4.8", @@ -16658,5 +16728,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } From f8476f713396027e7149e7306db2bfcc710d5e5c Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 15 Oct 2024 12:49:52 -0700 Subject: [PATCH 04/59] finished the construct and mail call in the listner --- app/Listeners/CheckoutableListener.php | 27 ++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index eb6b73809420..7dab68f18ccc 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -3,6 +3,7 @@ namespace App\Listeners; use App\Events\CheckoutableCheckedOut; +use App\Mail\CheckoutAssetMail; use App\Models\Accessory; use App\Models\Asset; use App\Models\CheckoutAcceptance; @@ -20,6 +21,7 @@ use App\Notifications\CheckoutConsumableNotification; use App\Notifications\CheckoutLicenseSeatNotification; use GuzzleHttp\Exception\ClientException; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Exception; use Illuminate\Support\Facades\Log; @@ -44,23 +46,24 @@ public function onCheckedOut($event) * Make a checkout acceptance and attach it in the notification */ $acceptance = $this->getCheckoutAcceptance($event); - $notifiables = $this->getNotifiables($event); + $notifiable = $this->getNotifiables($event); + $mailable = (new CheckoutAssetMail( + $event->checkoutable, + $event->checkedOutTo, + $event->checkedOutBy, + $acceptance, + $event->note + )); // Send email notifications try { - foreach ($notifiables as $notifiable) { - if ($notifiable instanceof User && $notifiable->email != '') { - if (! $event->checkedOutTo->locale){ - Notification::locale(Setting::getSettings()->locale)->send($notifiable, $this->getCheckoutNotification($event, $acceptance)); - } - else { - Notification::send($notifiable, $this->getCheckoutNotification($event, $acceptance)); - } + if (! $event->checkedOutTo->locale){ + $mailable->locale($event->checkedOutTo->locale); } - } + Mail::to($notifiable)->send($mailable); - // Send Webhook notification - if ($this->shouldSendWebhookNotification()) { + // Send Webhook notification + if ($this->shouldSendWebhookNotification()) { // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { Notification::route('slack', Setting::getSettings()->webhook_endpoint) From 9f06a0e441940606de32279c428b24a8957186fb Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 15 Oct 2024 14:01:28 -0700 Subject: [PATCH 05/59] handle some edge cases, null values clean up variable names --- app/Listeners/CheckoutableListener.php | 42 +++++++++++++----------- app/Models/Recipients/AdminRecipient.php | 6 ++++ 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 7dab68f18ccc..4d21fd6c1099 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -4,6 +4,7 @@ use App\Events\CheckoutableCheckedOut; use App\Mail\CheckoutAssetMail; +use App\Mail\CheckinAssetMail; use App\Models\Accessory; use App\Models\Asset; use App\Models\CheckoutAcceptance; @@ -14,7 +15,6 @@ use App\Models\Setting; use App\Models\User; use App\Notifications\CheckinAccessoryNotification; -use App\Notifications\CheckinAssetNotification; use App\Notifications\CheckinLicenseSeatNotification; use App\Notifications\CheckoutAccessoryNotification; use App\Notifications\CheckoutAssetNotification; @@ -46,7 +46,7 @@ public function onCheckedOut($event) * Make a checkout acceptance and attach it in the notification */ $acceptance = $this->getCheckoutAcceptance($event); - $notifiable = $this->getNotifiables($event); + $notifiable = $this->getNotifiable($event); $mailable = (new CheckoutAssetMail( $event->checkoutable, $event->checkedOutTo, @@ -57,11 +57,11 @@ public function onCheckedOut($event) // Send email notifications try { - if (! $event->checkedOutTo->locale){ + if (!$event->checkedOutTo->locale){ $mailable->locale($event->checkedOutTo->locale); } Mail::to($notifiable)->send($mailable); - + \Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); // Send Webhook notification if ($this->shouldSendWebhookNotification()) { // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint @@ -107,19 +107,22 @@ public function onCheckedIn($event) } } - $notifiables = $this->getNotifiables($event); + $notifiable = $this->getNotifiable($event); + $mailable = (new CheckInAssetMail( + $event->checkoutable, + $event->checkedOutTo, + $event->checkedOutBy, + $event->note, + null, + )); + // Send email notifications try { - foreach ($notifiables as $notifiable) { - if ($notifiable instanceof User && $notifiable->email != '') { - if (! $event->checkedOutTo->locale){ - Notification::locale(Setting::getSettings()->locale)->send($notifiable, $this->getCheckoutNotification($event, $acceptance)); - } - else { - Notification::send($notifiable, $this->getCheckinNotification($event)); - } - } + if (!$event->checkedOutTo->locale){ + $mailable->locale($event->checkedOutTo->locale); } + Mail::to($notifiable)->send($mailable); + \Log::info('Sending email, Locale: ' .$event->checkedOutTo->locale); // Send Webhook notification if ($this->shouldSendWebhookNotification()) { // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint @@ -168,25 +171,26 @@ private function getCheckoutAcceptance($event) * @param Event $event * @return Collection */ - private function getNotifiables($event) + private function getNotifiable($event) { - $notifiables = collect(); + $notifiable = collect(); /** * Notify who checked out the item as long as the model can route notifications */ if (method_exists($event->checkedOutTo, 'routeNotificationFor')) { - $notifiables->push($event->checkedOutTo); + $notifiable->push($event->checkedOutTo); } /** * Notify Admin users if the settings is activated */ if ((Setting::getSettings()) && (Setting::getSettings()->admin_cc_email != '')) { - $notifiables->push(new AdminRecipient()); + $adminRecipient= new AdminRecipient; + $notifiable->push($adminRecipient->getEmail()); } - return $notifiables; + return new $notifiable; } /** diff --git a/app/Models/Recipients/AdminRecipient.php b/app/Models/Recipients/AdminRecipient.php index 433bd002094a..90e39d4ee53e 100644 --- a/app/Models/Recipients/AdminRecipient.php +++ b/app/Models/Recipients/AdminRecipient.php @@ -6,9 +6,15 @@ class AdminRecipient extends Recipient { + + protected $email; public function __construct() { $settings = Setting::getSettings(); $this->email = trim($settings->admin_cc_email); } + + public function getEmail(){ + return $this->email; + } } From 3ab2521cb0b8f61cb42a7b205a7836d7950046a6 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 12:21:33 -0700 Subject: [PATCH 06/59] email comes through, no picture and html markup appear though. --- .../Account/AcceptanceController.php | 1 + app/Listeners/CheckoutableListener.php | 25 ++-- .../CheckoutAssetNotification.php | 21 --- .../markdown/checkout-asset.blade.php | 130 +++++++++--------- routes/web.php | 22 +++ 5 files changed, 100 insertions(+), 99 deletions(-) diff --git a/app/Http/Controllers/Account/AcceptanceController.php b/app/Http/Controllers/Account/AcceptanceController.php index e29fa7c63b08..278d7e208106 100644 --- a/app/Http/Controllers/Account/AcceptanceController.php +++ b/app/Http/Controllers/Account/AcceptanceController.php @@ -338,4 +338,5 @@ public function store(Request $request, $id) : RedirectResponse return redirect()->to('account/accept')->with('success', $return_msg); } + } diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 4d21fd6c1099..cfadad5ae915 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -51,8 +51,8 @@ public function onCheckedOut($event) $event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, + $event->note, $acceptance, - $event->note )); // Send email notifications @@ -61,18 +61,18 @@ public function onCheckedOut($event) $mailable->locale($event->checkedOutTo->locale); } Mail::to($notifiable)->send($mailable); - \Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); + Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); // Send Webhook notification - if ($this->shouldSendWebhookNotification()) { - // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint - if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { - Notification::route('slack', Setting::getSettings()->webhook_endpoint) - ->notify($this->getCheckoutNotification($event, $acceptance)); - } else { - Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) - ->notify($this->getCheckoutNotification($event, $acceptance)); - } - } +// if ($this->shouldSendWebhookNotification()) { +// // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint +// if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { +// Notification::route('slack', Setting::getSettings()->webhook_endpoint) +// ->notify($this->getCheckoutNotification($event, $acceptance)); +// } else { +// Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) +// ->notify($this->getCheckoutNotification($event, $acceptance)); +// } +// } } catch (ClientException $e) { Log::debug("Exception caught during checkout notification: " . $e->getMessage()); } catch (Exception $e) { @@ -113,7 +113,6 @@ public function onCheckedIn($event) $event->checkedOutTo, $event->checkedOutBy, $event->note, - null, )); // Send email notifications diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php index e61d49bf5cc5..4337749f4942 100644 --- a/app/Notifications/CheckoutAssetNotification.php +++ b/app/Notifications/CheckoutAssetNotification.php @@ -32,28 +32,7 @@ class CheckoutAssetNotification extends Notification */ public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note) { - $this->item = $asset; - $this->admin = $checkedOutBy; - $this->note = $note; - $this->target = $checkedOutTo; - $this->acceptance = $acceptance; - - $this->settings = Setting::getSettings(); - - $this->last_checkout = ''; - $this->expected_checkin = ''; - - if ($this->item->last_checkout) { - $this->last_checkout = Helper::getFormattedDateObject($this->item->last_checkout, 'date', - false); - } - - if ($this->item->expected_checkin) { - $this->expected_checkin = Helper::getFormattedDateObject($this->item->expected_checkin, 'date', - false); - } } - /** * Get the notification's delivery channels. * diff --git a/resources/views/notifications/markdown/checkout-asset.blade.php b/resources/views/notifications/markdown/checkout-asset.blade.php index 9b5fc26dc2e9..5b4c811dd712 100644 --- a/resources/views/notifications/markdown/checkout-asset.blade.php +++ b/resources/views/notifications/markdown/checkout-asset.blade.php @@ -1,76 +1,76 @@ @component('mail::message') -# {{ trans('mail.hello') }} {{ $target->present()->fullName() }}, + # {{ trans('mail.hello') }} {{ $target->present()->fullName() }}, -{{ trans('mail.new_item_checked') }} + {{ trans('mail.new_item_checked') }} -@if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl()) -
Asset
-@endif + @if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl()) +
Asset
+ @endif -@component('mail::table') -| | | -| ------------- | ------------- | -@if ((isset($item->name)) && ($item->name!='')) -| **{{ trans('mail.asset_name') }}** | {{ $item->name }} | -@endif -@if (($item->name!=$item->asset_tag)) -| **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} | -@endif -@if (isset($item->manufacturer)) -| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} | -@endif -@if (isset($item->model)) -| **{{ trans('general.asset_model') }}** | {{ $item->model->name }} | -@endif -@if ((isset($item->model->model_number)) && ($item->model->name!=$item->model->model_number)) -| **{{ trans('general.model_no') }}** | {{ $item->model->model_number }} | -@endif -@if (isset($item->serial)) -| **{{ trans('mail.serial') }}** | {{ $item->serial }} | -@endif -@if (isset($last_checkout)) -| **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} | -@endif -@if (isset($status)) -| **{{ trans('general.status') }}** | {{ $status }} | -@endif -@if ((isset($expected_checkin)) && ($expected_checkin!='')) -| **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} | -@endif -@foreach($fields as $field) -@if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0')) -| **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} | -@endif -@endforeach -@if ($admin) -| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} | -@endif -@if ($note) -| **{{ trans('mail.additional_notes') }}** | {{ $note }} | -@endif -@endcomponent + @component('mail::table') + | | | + | ------------- | ------------- | + @if ((isset($item->name)) && ($item->name!='')) + | **{{ trans('mail.asset_name') }}** | {{ $item->name }} | + @endif + @if (($item->name!=$item->asset_tag)) + | **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} | + @endif + @if (isset($item->manufacturer)) + | **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} | + @endif + @if (isset($item->model)) + | **{{ trans('general.asset_model') }}** | {{ $item->model->name }} | + @endif + @if ((isset($item->model->model_number)) && ($item->model->name!=$item->model->model_number)) + | **{{ trans('general.model_no') }}** | {{ $item->model->model_number }} | + @endif + @if (isset($item->serial)) + | **{{ trans('mail.serial') }}** | {{ $item->serial }} | + @endif + @if (isset($last_checkout)) + | **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} | + @endif + @if (isset($status)) + | **{{ trans('general.status') }}** | {{ $status }} | + @endif + @if ((isset($expected_checkin)) && ($expected_checkin!='')) + | **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} | + @endif + @foreach($fields as $field) + @if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0')) + | **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} | + @endif + @endforeach + @if ($admin) + | **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} | + @endif + @if ($note) + | **{{ trans('mail.additional_notes') }}** | {{ $note }} | + @endif + @endcomponent -@if (($req_accept == 1) && ($eula!='')) -{{ trans('mail.read_the_terms_and_click') }} -@elseif (($req_accept == 1) && ($eula=='')) -{{ trans('mail.click_on_the_link_asset') }} -@elseif (($req_accept == 0) && ($eula!='')) -{{ trans('mail.read_the_terms') }} -@endif + @if (($req_accept == 1) && ($eula!='')) + {{ trans('mail.read_the_terms_and_click') }} + @elseif (($req_accept == 1) && ($eula=='')) + {{ trans('mail.click_on_the_link_asset') }} + @elseif (($req_accept == 0) && ($eula!='')) + {{ trans('mail.read_the_terms') }} + @endif -@if ($eula) -@component('mail::panel') -{!! $eula !!} -@endcomponent -@endif + @if ($eula) + @component('mail::panel') + {!! $eula !!} + @endcomponent + @endif -@if ($req_accept == 1) -**[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})** -@endif + @if ($req_accept == 1) + **[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})** + @endif -{{ trans('mail.best_regards') }} + {{ trans('mail.best_regards') }} -{{ $snipeSettings->site_name }} + {{ $snipeSettings->site_name }} -@endcomponent +@endcomponent \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 60b74476c799..7bed89acf7ff 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,8 @@ use App\Http\Controllers\Auth\ForgotPasswordController; use App\Http\Controllers\Auth\ResetPasswordController; use App\Livewire\Importer; +use App\Models\Asset; +use App\Models\User; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Auth; @@ -53,6 +55,26 @@ /* * Locations */ + Route::get('/test-email', function() { + $item = Asset::find(1); // Load some test data + $admin = User::find(1); + $target = User::find(2); + $acceptance = null; // Simulate acceptance data + $note = 'Test note'; + + $fields = []; + if (($item->model) && ($item->model->fieldset)) { + $fields = $item->model->fieldset->fields; + } + + return new \App\Mail\CheckoutAssetMail( + $item, + $admin, + $target, + $acceptance, + $note); + }); + Route::group(['prefix' => 'locations', 'middleware' => ['auth']], function () { From 9e1b86f586f2942312105b0b37d69ee8ec34ca17 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 12:51:19 -0700 Subject: [PATCH 07/59] sends checkout notification via webhook --- app/Listeners/CheckoutableListener.php | 34 +++++------ .../CheckinAssetNotification.php | 17 +++--- .../CheckoutAssetNotification.php | 61 ++++++++----------- 3 files changed, 51 insertions(+), 61 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index cfadad5ae915..3204bf628b43 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -62,17 +62,17 @@ public function onCheckedOut($event) } Mail::to($notifiable)->send($mailable); Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); - // Send Webhook notification -// if ($this->shouldSendWebhookNotification()) { -// // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint -// if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { -// Notification::route('slack', Setting::getSettings()->webhook_endpoint) -// ->notify($this->getCheckoutNotification($event, $acceptance)); -// } else { -// Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) -// ->notify($this->getCheckoutNotification($event, $acceptance)); -// } -// } +// Send Webhook notification + if ($this->shouldSendWebhookNotification()) { + // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint + if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { + Notification::route('slack', Setting::getSettings()->webhook_endpoint) + ->notify($this->getCheckoutNotification($event, $acceptance)); + } else { + Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) + ->notify($this->getCheckoutNotification($event, $acceptance)); + } + } } catch (ClientException $e) { Log::debug("Exception caught during checkout notification: " . $e->getMessage()); } catch (Exception $e) { @@ -231,17 +231,17 @@ private function getCheckoutNotification($event, $acceptance = null) { $notificationClass = null; - switch (get_class($event->checkoutable)) { - case Accessory::class: + switch (true) { + case $event->checkoutable instanceof Accessory: $notificationClass = CheckoutAccessoryNotification::class; break; - case Asset::class: + case $event->checkoutable instanceof Asset: $notificationClass = CheckoutAssetNotification::class; break; - case Consumable::class: + case $event->checkoutable instanceof Consumable: $notificationClass = CheckoutConsumableNotification::class; - break; - case LicenseSeat::class: + break; + case $event->checkoutable instanceof LicenseSeat: $notificationClass = CheckoutLicenseSeatNotification::class; break; } diff --git a/app/Notifications/CheckinAssetNotification.php b/app/Notifications/CheckinAssetNotification.php index 77cd6d9b5a87..85b1c744130a 100644 --- a/app/Notifications/CheckinAssetNotification.php +++ b/app/Notifications/CheckinAssetNotification.php @@ -50,7 +50,6 @@ public function __construct(Asset $asset, $checkedOutTo, User $checkedInBy, $not */ public function via() { - $notifyBy = []; if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) { $notifyBy[] = GoogleChatChannel::class; @@ -64,14 +63,14 @@ public function via() Log::debug('use webhook'); $notifyBy[] = 'slack'; } - - /** - * Only send checkin notifications to users if the category - * has the corresponding checkbox checked. - */ - if ($this->item->checkin_email() && $this->target instanceof User && $this->target->email != '') { - $notifyBy[] = 'mail'; - } +dd($notifyBy); +// /** +// * Only send checkin notifications to users if the category +// * has the corresponding checkbox checked. +// */ +// if ($this->item->checkin_email() && $this->target instanceof User && $this->target->email != '') { +// $notifyBy[] = 'mail'; +// } return $notifyBy; } diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php index 4337749f4942..1ca329ed80e7 100644 --- a/app/Notifications/CheckoutAssetNotification.php +++ b/app/Notifications/CheckoutAssetNotification.php @@ -8,6 +8,7 @@ use App\Models\User; use Exception; use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Channels\SlackWebhookChannel; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -32,6 +33,23 @@ class CheckoutAssetNotification extends Notification */ public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note) { + $this->settings = Setting::getSettings(); + $this->item = $asset; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->last_checkout = ''; + $this->expected_checkin = ''; + + if ($this->item->last_checkout) { + $this->last_checkout = Helper::getFormattedDateObject($this->item->last_checkout, 'date', + false); + } + + if ($this->item->expected_checkin) { + $this->expected_checkin = Helper::getFormattedDateObject($this->item->expected_checkin, 'date', + false); + } } /** * Get the notification's delivery channels. @@ -41,61 +59,34 @@ public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $ac public function via() { $notifyBy = []; - if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) { + + if (Setting::getSettings()->webhook_selected === 'google' && Setting::getSettings()->webhook_endpoint) { $notifyBy[] = GoogleChatChannel::class; } - if (Setting::getSettings()->webhook_selected == 'microsoft' && Setting::getSettings()->webhook_endpoint) { + if (Setting::getSettings()->webhook_selected === 'microsoft' && Setting::getSettings()->webhook_endpoint) { $notifyBy[] = MicrosoftTeamsChannel::class; } - if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) { + if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general' ) { Log::debug('use webhook'); - $notifyBy[] = 'slack'; - } - - /** - * Only send notifications to users that have email addresses - */ - if ($this->target instanceof User && $this->target->email != '') { - - /** - * Send an email if the asset requires acceptance, - * so the user can accept or decline the asset - */ - if ($this->item->requireAcceptance()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if the item has a EULA, since the user should always receive it - */ - if ($this->item->getEula()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if an email should be sent at checkin/checkout - */ - if ($this->item->checkin_email()) { - $notifyBy[1] = 'mail'; - } + $notifyBy[] = SlackWebhookChannel::class; } return $notifyBy; } - public function toSlack() + public function toSlack() :SlackMessage { $target = $this->target; $admin = $this->admin; $item = $this->item; $note = $this->note; - $botname = ($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot'; + $botname = ($this->settings->webhook_botname) ?: 'Snipe-Bot'; $channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : ''; $fields = [ @@ -103,7 +94,7 @@ public function toSlack() 'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>', ]; - if (($this->expected_checkin) && ($this->expected_checkin != '')) { + if (($this->expected_checkin) && ($this->expected_checkin !== '')) { $fields['Expected Checkin'] = $this->expected_checkin; } From 16cffe9a9dd0cbce4f38d161a2b4cbebeaffde1c Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 12:53:35 -0700 Subject: [PATCH 08/59] simplified checkout webhook call --- app/Listeners/CheckoutableListener.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 3204bf628b43..16032a54f50a 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -124,16 +124,9 @@ public function onCheckedIn($event) \Log::info('Sending email, Locale: ' .$event->checkedOutTo->locale); // Send Webhook notification if ($this->shouldSendWebhookNotification()) { - // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint - if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { - Notification::route('slack', Setting::getSettings()->webhook_endpoint) - ->notify($this->getCheckinNotification($event)); - } else { Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) ->notify($this->getCheckinNotification($event)); } - } - } catch (ClientException $e) { Log::warning("Exception caught during checkout notification: " . $e->getMessage()); } catch (Exception $e) { From 9710436d54fc23e79bf96b61430f3f0f3345581a Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 13:12:07 -0700 Subject: [PATCH 09/59] adds Mailables for asset checkin and out --- app/Listeners/CheckoutableListener.php | 8 +- app/Mail/CheckinAssetMail.php | 102 ++++++++++++ app/Mail/CheckoutAssetMail.php | 150 ++++++++++++++++++ .../CheckinAssetNotification.php | 32 +--- .../markdown/checkin-asset.blade.php | 0 routes/web.php | 2 +- 6 files changed, 255 insertions(+), 39 deletions(-) create mode 100644 app/Mail/CheckinAssetMail.php create mode 100644 app/Mail/CheckoutAssetMail.php rename resources/views/{notifications => mail}/markdown/checkin-asset.blade.php (100%) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 16032a54f50a..44e731b4baf5 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -64,15 +64,9 @@ public function onCheckedOut($event) Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); // Send Webhook notification if ($this->shouldSendWebhookNotification()) { - // Slack doesn't include the URL in its messaging format, so this is needed to hit the endpoint - if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') { - Notification::route('slack', Setting::getSettings()->webhook_endpoint) - ->notify($this->getCheckoutNotification($event, $acceptance)); - } else { Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) ->notify($this->getCheckoutNotification($event, $acceptance)); } - } } catch (ClientException $e) { Log::debug("Exception caught during checkout notification: " . $e->getMessage()); } catch (Exception $e) { @@ -111,7 +105,7 @@ public function onCheckedIn($event) $mailable = (new CheckInAssetMail( $event->checkoutable, $event->checkedOutTo, - $event->checkedOutBy, + $event->checkedInBy, $event->note, )); diff --git a/app/Mail/CheckinAssetMail.php b/app/Mail/CheckinAssetMail.php new file mode 100644 index 000000000000..5795d795c701 --- /dev/null +++ b/app/Mail/CheckinAssetMail.php @@ -0,0 +1,102 @@ +target = $checkedOutTo; + $this->item = $asset; + $this->admin = $checkedInBy; + $this->note = $note; + + $this->settings = Setting::getSettings(); + $this->expected_checkin = ''; + + if ($this->item->expected_checkin) { + $this->expected_checkin = Helper::getFormattedDateObject($this->item->expected_checkin, 'date', + false); + } + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: trans('mail.Asset_Checkin_Notification'), + ); + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return Content + */ + public function content(): Content + { + $this->item->load('assetstatus'); + $fields = []; + + // Check if the item has custom fields associated with it + if (($this->item->model) && ($this->item->model->fieldset)) { + $fields = $this->item->model->fieldset->fields; + } + + return new Content( + markdown: 'mail.markdown.checkin-asset', + with: [ + 'item' => $this->item, + 'status' => $this->item->assetstatus?->name, + 'admin' => $this->admin, + 'note' => $this->note, + 'target' => $this->target, + 'fields' => $fields, + 'expected_checkin' => $this->expected_checkin, + ], + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/app/Mail/CheckoutAssetMail.php b/app/Mail/CheckoutAssetMail.php new file mode 100644 index 000000000000..214c48ed5c16 --- /dev/null +++ b/app/Mail/CheckoutAssetMail.php @@ -0,0 +1,150 @@ +item = $asset; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + + $this->settings = Setting::getSettings(); + + $this->last_checkout = ''; + $this->expected_checkin = ''; + + if ($this->item->last_checkout) { + $this->last_checkout = Helper::getFormattedDateObject($this->item->last_checkout, 'date', + false); + } + + if ($this->item->expected_checkin) { + $this->expected_checkin = Helper::getFormattedDateObject($this->item->expected_checkin, 'date', + false); + } + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: trans('mail.Asset_Checkout_Notification'), + ); + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return Content + */ + public function content(): Content + { + $this->item->load('assetstatus'); + $eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : ''; + $req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0; + $fields = []; + + // Check if the item has custom fields associated with it + if (($this->item->model) && ($this->item->model->fieldset)) { + $fields = $this->item->model->fieldset->fields; + } + + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + + return new Content( + markdown: 'mail.markdown.checkout-asset', + with: [ + 'item' => $this->item, + 'admin' => $this->admin, + 'status' => $this->item->assetstatus?->name, + 'note' => $this->note, + 'target' => $this->target, + 'fields' => $fields, + 'eula' => $eula, + 'req_accept' => $req_accept, + 'accept_url' => $accept_url, + 'last_checkout' => $this->last_checkout, + 'expected_checkin' => $this->expected_checkin, + ], + ); + } +// public function build() +// { +// $this->item->load('assetstatus'); +// $eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : ''; +// $req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0; +// $fields = []; +// +// // Check if the item has custom fields associated with it +// if (($this->item->model) && ($this->item->model->fieldset)) { +// $fields = $this->item->model->fieldset->fields; +// } +// +// $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); +// +// return $this +// ->subject('Asset Checkout Notification') +// ->markdown('notifications.markdown.checkout-asset') +// ->with([ +// 'item' => $this->item, +// 'admin' => $this->admin, +// 'status' => $this->item->assetstatus?->name, +// 'note' => $this->note, +// 'target' => $this->target, +// 'fields' => $fields, +// 'eula' => $eula, +// 'req_accept' => $req_accept, +// 'accept_url' => $accept_url, +// 'last_checkout' => $this->last_checkout, +// 'expected_checkin' => $this->expected_checkin, +// ]); +// } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/app/Notifications/CheckinAssetNotification.php b/app/Notifications/CheckinAssetNotification.php index 85b1c744130a..5c38982ab690 100644 --- a/app/Notifications/CheckinAssetNotification.php +++ b/app/Notifications/CheckinAssetNotification.php @@ -63,7 +63,7 @@ public function via() Log::debug('use webhook'); $notifyBy[] = 'slack'; } -dd($notifyBy); + // /** // * Only send checkin notifications to users if the category // * has the corresponding checkbox checked. @@ -141,35 +141,5 @@ public function toGoogleChat() ) ) ); - - } - - /** - * Get the mail representation of the notification. - * - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail() - { - $fields = []; - - // Check if the item has custom fields associated with it - if (($this->item->model) && ($this->item->model->fieldset)) { - $fields = $this->item->model->fieldset->fields; - } - - $message = (new MailMessage)->markdown('notifications.markdown.checkin-asset', - [ - 'item' => $this->item, - 'status' => $this->item->assetstatus?->name, - 'admin' => $this->admin, - 'note' => $this->note, - 'target' => $this->target, - 'fields' => $fields, - 'expected_checkin' => $this->expected_checkin, - ]) - ->subject(trans('mail.Asset_Checkin_Notification')); - - return $message; } } diff --git a/resources/views/notifications/markdown/checkin-asset.blade.php b/resources/views/mail/markdown/checkin-asset.blade.php similarity index 100% rename from resources/views/notifications/markdown/checkin-asset.blade.php rename to resources/views/mail/markdown/checkin-asset.blade.php diff --git a/routes/web.php b/routes/web.php index 7bed89acf7ff..548758e3827d 100644 --- a/routes/web.php +++ b/routes/web.php @@ -67,7 +67,7 @@ $fields = $item->model->fieldset->fields; } - return new \App\Mail\CheckoutAssetMail( + return new \App\Mail\CheckinAssetMail( $item, $admin, $target, From dcdf600b785501d960ee6a8f99a46f9a6ba90b9f Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:27:34 -0700 Subject: [PATCH 10/59] adds Checkin and Checkout mailables and listner logic --- app/Listeners/CheckoutableListener.php | 43 +++++--- app/Mail/CheckoutAccessoryMail.php | 98 +++++++++++++++++++ .../CheckinAccessoryNotification.php | 62 ++++++------ .../CheckoutAccessoryNotification.php | 58 +---------- .../markdown/checkin-accessory.blade.php | 0 .../markdown/checkout-accessory.blade.php | 0 routes/web.php | 6 +- 7 files changed, 162 insertions(+), 105 deletions(-) create mode 100644 app/Mail/CheckoutAccessoryMail.php rename resources/views/{notifications => mail}/markdown/checkin-accessory.blade.php (100%) rename resources/views/{notifications => mail}/markdown/checkout-accessory.blade.php (100%) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 44e731b4baf5..6acedd4d97b6 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -3,6 +3,8 @@ namespace App\Listeners; use App\Events\CheckoutableCheckedOut; +use App\Mail\CheckinAccessoryMail; +use App\Mail\CheckoutAccessoryMail; use App\Mail\CheckoutAssetMail; use App\Mail\CheckinAssetMail; use App\Models\Accessory; @@ -47,14 +49,7 @@ public function onCheckedOut($event) */ $acceptance = $this->getCheckoutAcceptance($event); $notifiable = $this->getNotifiable($event); - $mailable = (new CheckoutAssetMail( - $event->checkoutable, - $event->checkedOutTo, - $event->checkedOutBy, - $event->note, - $acceptance, - )); - + $mailable = $this->getCheckoutMailType($event, $acceptance); // Send email notifications try { if (!$event->checkedOutTo->locale){ @@ -102,12 +97,7 @@ public function onCheckedIn($event) } $notifiable = $this->getNotifiable($event); - $mailable = (new CheckInAssetMail( - $event->checkoutable, - $event->checkedOutTo, - $event->checkedInBy, - $event->note, - )); + $mailable = $this->getCheckinMailType($event); // Send email notifications try { @@ -233,9 +223,32 @@ private function getCheckoutNotification($event, $acceptance = null) break; } - return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note); } + private function getCheckoutMailType($event, $acceptance){ + $lookup = [ + Accessory::class => CheckoutAccessoryMail::class, + Asset::class => CheckoutAssetMail::class, +// Consumable::class => +// LicenseSeat::class => + ]; + $mailable= $lookup[get_class($event->checkoutable)]; + + return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $event->note, $acceptance); + + } + private function getCheckinMailType($event){ + $lookup = [ + Accessory::class => CheckinAccessoryMail::class, + Asset::class => CheckinAssetMail::class, +// Consumable::class => +// LicenseSeat::class => + ]; + $mailable= $lookup[get_class($event->checkoutable)]; + + return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note); + + } /** * Register the listeners for the subscriber. diff --git a/app/Mail/CheckoutAccessoryMail.php b/app/Mail/CheckoutAccessoryMail.php new file mode 100644 index 000000000000..f7f90e8fe2c4 --- /dev/null +++ b/app/Mail/CheckoutAccessoryMail.php @@ -0,0 +1,98 @@ +item = $accessory; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->checkout_qty = $accessory->checkout_qty; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + $this->settings = Setting::getSettings(); + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: (trans('mail.Accessory_Checkout_Notification')), + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + Log::debug($this->item->getImageUrl()); + $eula = $this->item->getEula(); + $req_accept = $this->item->requireAcceptance(); + + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + + // Check if the item has custom fields associated with it + if (($this->item->model) && ($this->item->model->fieldset)) { + $fields = $this->item->model->fieldset->fields; + } + + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + + return new Content( + markdown: 'mail.markdown.checkout-accessory', + with: [ + 'item' => $this->item, + 'admin' => $this->admin, + 'note' => $this->note, + 'target' => $this->target, + 'eula' => $eula, + 'req_accept' => $req_accept, + 'accept_url' => $accept_url, + 'checkout_qty' => $this->checkout_qty, + ], + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php index 7e033f1870bd..d36b77a85019 100644 --- a/app/Notifications/CheckinAccessoryNotification.php +++ b/app/Notifications/CheckinAccessoryNotification.php @@ -58,18 +58,18 @@ public function via() $notifyBy[] = 'slack'; } - /** - * Only send notifications to users that have email addresses - */ - if ($this->target instanceof User && $this->target->email != '') { - Log::debug('The target is a user'); - - if ($this->item->checkin_email()) { - $notifyBy[] = 'mail'; - } - } - - Log::debug('checkin_email on this category is '.$this->item->checkin_email()); +// /** +// * Only send notifications to users that have email addresses +// */ +// if ($this->target instanceof User && $this->target->email != '') { +// Log::debug('The target is a user'); +// +// if ($this->item->checkin_email()) { +// $notifyBy[] = 'mail'; +// } +// } +// +// Log::debug('checkin_email on this category is '.$this->item->checkin_email()); return $notifyBy; } @@ -143,23 +143,23 @@ public function toGoogleChat() } - /** - * Get the mail representation of the notification. - * - * @param mixed $notifiable - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail() - { - Log::debug('to email called'); - - return (new MailMessage)->markdown('notifications.markdown.checkin-accessory', - [ - 'item' => $this->item, - 'admin' => $this->admin, - 'note' => $this->note, - 'target' => $this->target, - ]) - ->subject(trans('mail.Accessory_Checkin_Notification')); - } +// /** +// * Get the mail representation of the notification. +// * +// * @param mixed $notifiable +// * @return \Illuminate\Notifications\Messages\MailMessage +// */ +// public function toMail() +// { +// Log::debug('to email called'); +// +// return (new MailMessage)->markdown('notifications.markdown.checkin-accessory', +// [ +// 'item' => $this->item, +// 'admin' => $this->admin, +// 'note' => $this->note, +// 'target' => $this->target, +// ]) +// ->subject(trans('mail.Accessory_Checkin_Notification')); +// } } diff --git a/app/Notifications/CheckoutAccessoryNotification.php b/app/Notifications/CheckoutAccessoryNotification.php index 721ba7f6a4b5..cbc946ba43ed 100644 --- a/app/Notifications/CheckoutAccessoryNotification.php +++ b/app/Notifications/CheckoutAccessoryNotification.php @@ -6,6 +6,7 @@ use App\Models\Setting; use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Channels\SlackWebhookChannel; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -55,35 +56,7 @@ public function via() } if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) { - $notifyBy[] = 'slack'; - } - - /** - * Only send notifications to users that have email addresses - */ - if ($this->target instanceof User && $this->target->email != '') { - - /** - * Send an email if the asset requires acceptance, - * so the user can accept or decline the asset - */ - if ($this->item->requireAcceptance()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if the item has a EULA, since the user should always receive it - */ - if ($this->item->getEula()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if an email should be sent at checkin/checkout - */ - if ($this->item->checkin_email()) { - $notifyBy[1] = 'mail'; - } + $notifyBy[] = SlackWebhookChannel::class; } return $notifyBy; @@ -163,31 +136,4 @@ public function toGoogleChat() } - - /** - * Get the mail representation of the notification. - * - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail() - { - Log::debug($this->item->getImageUrl()); - $eula = $this->item->getEula(); - $req_accept = $this->item->requireAcceptance(); - - $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); - - return (new MailMessage)->markdown('notifications.markdown.checkout-accessory', - [ - 'item' => $this->item, - 'admin' => $this->admin, - 'note' => $this->note, - 'target' => $this->target, - 'eula' => $eula, - 'req_accept' => $req_accept, - 'accept_url' => $accept_url, - 'checkout_qty' => $this->checkout_qty, - ]) - ->subject(trans('mail.Confirm_accessory_delivery')); - } } diff --git a/resources/views/notifications/markdown/checkin-accessory.blade.php b/resources/views/mail/markdown/checkin-accessory.blade.php similarity index 100% rename from resources/views/notifications/markdown/checkin-accessory.blade.php rename to resources/views/mail/markdown/checkin-accessory.blade.php diff --git a/resources/views/notifications/markdown/checkout-accessory.blade.php b/resources/views/mail/markdown/checkout-accessory.blade.php similarity index 100% rename from resources/views/notifications/markdown/checkout-accessory.blade.php rename to resources/views/mail/markdown/checkout-accessory.blade.php diff --git a/routes/web.php b/routes/web.php index 548758e3827d..756c6dd4513e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,7 @@ use App\Http\Controllers\Auth\ForgotPasswordController; use App\Http\Controllers\Auth\ResetPasswordController; use App\Livewire\Importer; +use App\Models\Accessory; use App\Models\Asset; use App\Models\User; use Illuminate\Support\Facades\Route; @@ -56,7 +57,7 @@ * Locations */ Route::get('/test-email', function() { - $item = Asset::find(1); // Load some test data + $item = Accessory::find(1); // Load some test data $admin = User::find(1); $target = User::find(2); $acceptance = null; // Simulate acceptance data @@ -67,11 +68,10 @@ $fields = $item->model->fieldset->fields; } - return new \App\Mail\CheckinAssetMail( + return new \App\Mail\CheckinAccessoryMail( $item, $admin, $target, - $acceptance, $note); }); From c39df34bdfabb2acde4ab8aaba01cf5c65582675 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:29:50 -0700 Subject: [PATCH 11/59] forgot to add accessory mail to project --- app/Mail/CheckinAccessoryMail.php | 79 +++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 app/Mail/CheckinAccessoryMail.php diff --git a/app/Mail/CheckinAccessoryMail.php b/app/Mail/CheckinAccessoryMail.php new file mode 100644 index 000000000000..0c3ddbba0e5e --- /dev/null +++ b/app/Mail/CheckinAccessoryMail.php @@ -0,0 +1,79 @@ +item = $accessory; + $this->target = $checkedOutTo; + $this->admin = $checkedInby; + $this->note = $note; + $this->settings = Setting::getSettings(); + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: trans('mail.Accessory_Checkin_Notification'), + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + return new Content( + markdown: 'mail.markdown.checkin-accessory', + with: [ + 'item' => $this->item, + 'admin' => $this->admin, + 'note' => $this->note, + 'target' => $this->target, + ] + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} From f1d83a3f281a7d17c2b8ca52ccaf8403cac4d246 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:30:53 -0700 Subject: [PATCH 12/59] forgot to add asset checkout markdown to projet --- .../mail/markdown/checkout-asset.blade.php | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 resources/views/mail/markdown/checkout-asset.blade.php diff --git a/resources/views/mail/markdown/checkout-asset.blade.php b/resources/views/mail/markdown/checkout-asset.blade.php new file mode 100644 index 000000000000..5b4c811dd712 --- /dev/null +++ b/resources/views/mail/markdown/checkout-asset.blade.php @@ -0,0 +1,76 @@ +@component('mail::message') + # {{ trans('mail.hello') }} {{ $target->present()->fullName() }}, + + {{ trans('mail.new_item_checked') }} + + @if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl()) +
Asset
+ @endif + + @component('mail::table') + | | | + | ------------- | ------------- | + @if ((isset($item->name)) && ($item->name!='')) + | **{{ trans('mail.asset_name') }}** | {{ $item->name }} | + @endif + @if (($item->name!=$item->asset_tag)) + | **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} | + @endif + @if (isset($item->manufacturer)) + | **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} | + @endif + @if (isset($item->model)) + | **{{ trans('general.asset_model') }}** | {{ $item->model->name }} | + @endif + @if ((isset($item->model->model_number)) && ($item->model->name!=$item->model->model_number)) + | **{{ trans('general.model_no') }}** | {{ $item->model->model_number }} | + @endif + @if (isset($item->serial)) + | **{{ trans('mail.serial') }}** | {{ $item->serial }} | + @endif + @if (isset($last_checkout)) + | **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} | + @endif + @if (isset($status)) + | **{{ trans('general.status') }}** | {{ $status }} | + @endif + @if ((isset($expected_checkin)) && ($expected_checkin!='')) + | **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} | + @endif + @foreach($fields as $field) + @if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0')) + | **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} | + @endif + @endforeach + @if ($admin) + | **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} | + @endif + @if ($note) + | **{{ trans('mail.additional_notes') }}** | {{ $note }} | + @endif + @endcomponent + + @if (($req_accept == 1) && ($eula!='')) + {{ trans('mail.read_the_terms_and_click') }} + @elseif (($req_accept == 1) && ($eula=='')) + {{ trans('mail.click_on_the_link_asset') }} + @elseif (($req_accept == 0) && ($eula!='')) + {{ trans('mail.read_the_terms') }} + @endif + + @if ($eula) + @component('mail::panel') + {!! $eula !!} + @endcomponent + @endif + + @if ($req_accept == 1) + **[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})** + @endif + + + {{ trans('mail.best_regards') }} + + {{ $snipeSettings->site_name }} + +@endcomponent \ No newline at end of file From 2584d603445bb0a82e722cd8b7a3dbf7f1c1d020 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:38:49 -0700 Subject: [PATCH 13/59] adds Licenses seat checkout Mailable --- app/Listeners/CheckoutableListener.php | 3 +- app/Mail/CheckoutLicenseMail.php | 89 +++++++++++++++++++ .../CheckoutLicenseSeatNotification.php | 28 ------ .../markdown/checkout-license.blade.php | 0 routes/web.php | 6 +- 5 files changed, 95 insertions(+), 31 deletions(-) create mode 100644 app/Mail/CheckoutLicenseMail.php rename resources/views/{notifications => mail}/markdown/checkout-license.blade.php (100%) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 6acedd4d97b6..915ed5753aae 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -7,6 +7,7 @@ use App\Mail\CheckoutAccessoryMail; use App\Mail\CheckoutAssetMail; use App\Mail\CheckinAssetMail; +use App\Mail\CheckoutLicenseMail; use App\Models\Accessory; use App\Models\Asset; use App\Models\CheckoutAcceptance; @@ -229,8 +230,8 @@ private function getCheckoutMailType($event, $acceptance){ $lookup = [ Accessory::class => CheckoutAccessoryMail::class, Asset::class => CheckoutAssetMail::class, + LicenseSeat::class => CheckoutLicenseMail::class, // Consumable::class => -// LicenseSeat::class => ]; $mailable= $lookup[get_class($event->checkoutable)]; diff --git a/app/Mail/CheckoutLicenseMail.php b/app/Mail/CheckoutLicenseMail.php new file mode 100644 index 000000000000..8389f1136fce --- /dev/null +++ b/app/Mail/CheckoutLicenseMail.php @@ -0,0 +1,89 @@ +item = $licenseSeat->license; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + + $this->settings = Setting::getSettings(); + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: trans('mail.Confirm_license_delivery'), + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + $eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : ''; + $req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0; + + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + + return new Content( + markdown: 'mail.markdown.checkout-license', + with: [ + 'item' => $this->item, + 'admin' => $this->admin, + 'note' => $this->note, + 'target' => $this->target, + 'eula' => $eula, + 'req_accept' => $req_accept, + 'accept_url' => $accept_url, + ] + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/app/Notifications/CheckoutLicenseSeatNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php index 8e0273c66e7d..16f8c7c1d50c 100644 --- a/app/Notifications/CheckoutLicenseSeatNotification.php +++ b/app/Notifications/CheckoutLicenseSeatNotification.php @@ -63,34 +63,6 @@ public function via() $notifyBy[] = 'slack'; } - /** - * Only send notifications to users that have email addresses - */ - if ($this->target instanceof User && $this->target->email != '') { - - /** - * Send an email if the asset requires acceptance, - * so the user can accept or decline the asset - */ - if ($this->item->requireAcceptance()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if the item has a EULA, since the user should always receive it - */ - if ($this->item->getEula()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if an email should be sent at checkin/checkout - */ - if ($this->item->checkin_email()) { - $notifyBy[1] = 'mail'; - } - } - return $notifyBy; } diff --git a/resources/views/notifications/markdown/checkout-license.blade.php b/resources/views/mail/markdown/checkout-license.blade.php similarity index 100% rename from resources/views/notifications/markdown/checkout-license.blade.php rename to resources/views/mail/markdown/checkout-license.blade.php diff --git a/routes/web.php b/routes/web.php index 756c6dd4513e..bcbe159b3046 100644 --- a/routes/web.php +++ b/routes/web.php @@ -26,6 +26,7 @@ use App\Livewire\Importer; use App\Models\Accessory; use App\Models\Asset; +use App\Models\LicenseSeat; use App\Models\User; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Auth; @@ -57,7 +58,7 @@ * Locations */ Route::get('/test-email', function() { - $item = Accessory::find(1); // Load some test data + $item = LicenseSeat::find(1); // Load some test data $admin = User::find(1); $target = User::find(2); $acceptance = null; // Simulate acceptance data @@ -68,10 +69,11 @@ $fields = $item->model->fieldset->fields; } - return new \App\Mail\CheckinAccessoryMail( + return new \App\Mail\CheckoutLicenseMail( $item, $admin, $target, + $acceptance, $note); }); From 4becdca8aa792957243e5ca9a3dcf04cfa3ee522 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:39:20 -0700 Subject: [PATCH 14/59] removes toMail from license notificaqtion --- .../CheckoutLicenseSeatNotification.php | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/app/Notifications/CheckoutLicenseSeatNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php index 16f8c7c1d50c..85d02abc9294 100644 --- a/app/Notifications/CheckoutLicenseSeatNotification.php +++ b/app/Notifications/CheckoutLicenseSeatNotification.php @@ -136,29 +136,4 @@ public function toGoogleChat() ); } - - /** - * Get the mail representation of the notification. - * - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail() - { - $eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : ''; - $req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0; - - $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); - - return (new MailMessage)->markdown('notifications.markdown.checkout-license', - [ - 'item' => $this->item, - 'admin' => $this->admin, - 'note' => $this->note, - 'target' => $this->target, - 'eula' => $eula, - 'req_accept' => $req_accept, - 'accept_url' => $accept_url, - ]) - ->subject(trans('mail.Confirm_license_delivery')); - } } From 02ff646da4388422d260ed50d8e93ea7bc57dab0 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:44:45 -0700 Subject: [PATCH 15/59] adds checkin license mailable --- app/Listeners/CheckoutableListener.php | 3 +- app/Mail/CheckinLicenseMail.php | 79 +++++++++++++++++++ .../CheckinAccessoryNotification.php | 33 -------- .../CheckinLicenseSeatNotification.php | 27 ------- .../markdown/checkin-license.blade.php | 0 5 files changed, 81 insertions(+), 61 deletions(-) create mode 100644 app/Mail/CheckinLicenseMail.php rename resources/views/{notifications => mail}/markdown/checkin-license.blade.php (100%) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 915ed5753aae..fe9f7b6d383b 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -4,6 +4,7 @@ use App\Events\CheckoutableCheckedOut; use App\Mail\CheckinAccessoryMail; +use App\Mail\CheckinLicenseMail; use App\Mail\CheckoutAccessoryMail; use App\Mail\CheckoutAssetMail; use App\Mail\CheckinAssetMail; @@ -242,8 +243,8 @@ private function getCheckinMailType($event){ $lookup = [ Accessory::class => CheckinAccessoryMail::class, Asset::class => CheckinAssetMail::class, + LicenseSeat::class => CheckinLicenseMail::class, // Consumable::class => -// LicenseSeat::class => ]; $mailable= $lookup[get_class($event->checkoutable)]; diff --git a/app/Mail/CheckinLicenseMail.php b/app/Mail/CheckinLicenseMail.php new file mode 100644 index 000000000000..e567383f8035 --- /dev/null +++ b/app/Mail/CheckinLicenseMail.php @@ -0,0 +1,79 @@ +target = $checkedOutTo; + $this->item = $licenseSeat->license; + $this->admin = $checkedInBy; + $this->note = $note; + $this->settings = Setting::getSettings(); + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: trans('mail.License_Checkin_Notification'), + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + return new Content( + markdown: 'mail.markdown.checkin-license', + with: [ + 'item' => $this->item, + 'admin' => $this->admin, + 'note' => $this->note, + 'target' => $this->target, + ] + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php index d36b77a85019..777834aae7bd 100644 --- a/app/Notifications/CheckinAccessoryNotification.php +++ b/app/Notifications/CheckinAccessoryNotification.php @@ -58,19 +58,6 @@ public function via() $notifyBy[] = 'slack'; } -// /** -// * Only send notifications to users that have email addresses -// */ -// if ($this->target instanceof User && $this->target->email != '') { -// Log::debug('The target is a user'); -// -// if ($this->item->checkin_email()) { -// $notifyBy[] = 'mail'; -// } -// } -// -// Log::debug('checkin_email on this category is '.$this->item->checkin_email()); - return $notifyBy; } @@ -142,24 +129,4 @@ public function toGoogleChat() ); } - -// /** -// * Get the mail representation of the notification. -// * -// * @param mixed $notifiable -// * @return \Illuminate\Notifications\Messages\MailMessage -// */ -// public function toMail() -// { -// Log::debug('to email called'); -// -// return (new MailMessage)->markdown('notifications.markdown.checkin-accessory', -// [ -// 'item' => $this->item, -// 'admin' => $this->admin, -// 'note' => $this->note, -// 'target' => $this->target, -// ]) -// ->subject(trans('mail.Accessory_Checkin_Notification')); -// } } diff --git a/app/Notifications/CheckinLicenseSeatNotification.php b/app/Notifications/CheckinLicenseSeatNotification.php index 289e63a16247..114011bd7284 100644 --- a/app/Notifications/CheckinLicenseSeatNotification.php +++ b/app/Notifications/CheckinLicenseSeatNotification.php @@ -61,14 +61,6 @@ public function via() $notifyBy[] = 'slack'; } - /** - * Only send checkin notifications to users if the category - * has the corresponding checkbox checked. - */ - if ($this->item->checkin_email() && $this->target instanceof User && $this->target->email != '') { - $notifyBy[] = 'mail'; - } - return $notifyBy; } @@ -149,23 +141,4 @@ public function toGoogleChat() ); } - - - /** - * Get the mail representation of the notification. - * - * @param mixed $notifiable - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail() - { - return (new MailMessage)->markdown('notifications.markdown.checkin-license', - [ - 'item' => $this->item, - 'admin' => $this->admin, - 'note' => $this->note, - 'target' => $this->target, - ]) - ->subject(trans('mail.License_Checkin_Notification')); - } } diff --git a/resources/views/notifications/markdown/checkin-license.blade.php b/resources/views/mail/markdown/checkin-license.blade.php similarity index 100% rename from resources/views/notifications/markdown/checkin-license.blade.php rename to resources/views/mail/markdown/checkin-license.blade.php From 02bda3cd9598d77ddd2c68f67f589f82e0af37b3 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 15:53:05 -0700 Subject: [PATCH 16/59] adds Checkout Consumable mailable and slackwebhook channel to notifs --- app/Listeners/CheckoutableListener.php | 16 ++-- app/Mail/CheckoutConsumableMail.php | 91 +++++++++++++++++++ .../CheckinAccessoryNotification.php | 3 +- .../CheckoutConsumableNotification.php | 83 ++++++----------- .../CheckoutLicenseSeatNotification.php | 3 +- .../markdown/checkout-consumable.blade.php | 0 6 files changed, 133 insertions(+), 63 deletions(-) create mode 100644 app/Mail/CheckoutConsumableMail.php rename resources/views/{notifications => mail}/markdown/checkout-consumable.blade.php (100%) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index fe9f7b6d383b..4f51ed705f5d 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -8,6 +8,7 @@ use App\Mail\CheckoutAccessoryMail; use App\Mail\CheckoutAssetMail; use App\Mail\CheckinAssetMail; +use App\Mail\CheckoutConsumableMail; use App\Mail\CheckoutLicenseMail; use App\Models\Accessory; use App\Models\Asset; @@ -210,21 +211,22 @@ private function getCheckoutNotification($event, $acceptance = null) { $notificationClass = null; - switch (true) { - case $event->checkoutable instanceof Accessory: + switch (get_class($event->checkoutable)) { + case Accessory::class: $notificationClass = CheckoutAccessoryNotification::class; break; - case $event->checkoutable instanceof Asset: + case Asset::class: $notificationClass = CheckoutAssetNotification::class; break; - case $event->checkoutable instanceof Consumable: + case Consumable::class: $notificationClass = CheckoutConsumableNotification::class; break; - case $event->checkoutable instanceof LicenseSeat: + case LicenseSeat::class: $notificationClass = CheckoutLicenseSeatNotification::class; break; } + return new $notificationClass($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note); } private function getCheckoutMailType($event, $acceptance){ @@ -232,7 +234,7 @@ private function getCheckoutMailType($event, $acceptance){ Accessory::class => CheckoutAccessoryMail::class, Asset::class => CheckoutAssetMail::class, LicenseSeat::class => CheckoutLicenseMail::class, -// Consumable::class => + Consumable::class => CheckoutConsumableMail::class, ]; $mailable= $lookup[get_class($event->checkoutable)]; @@ -244,8 +246,8 @@ private function getCheckinMailType($event){ Accessory::class => CheckinAccessoryMail::class, Asset::class => CheckinAssetMail::class, LicenseSeat::class => CheckinLicenseMail::class, -// Consumable::class => ]; + $mailable= $lookup[get_class($event->checkoutable)]; return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note); diff --git a/app/Mail/CheckoutConsumableMail.php b/app/Mail/CheckoutConsumableMail.php new file mode 100644 index 000000000000..382f789eb917 --- /dev/null +++ b/app/Mail/CheckoutConsumableMail.php @@ -0,0 +1,91 @@ +item = $consumable; + $this->admin = $checkedOutBy; + $this->note = $note; + $this->target = $checkedOutTo; + $this->acceptance = $acceptance; + + $this->settings = Setting::getSettings(); + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + $from = null; + $cc = []; + + if (!empty(Setting::getSettings()->alert_email)) { + $from = new Address(Setting::getSettings()->alert_email); + } + if (!empty(Setting::getSettings()->admin_cc_email)) { + $cc[] = new Address(Setting::getSettings()->admin_cc_email); + } + + return new Envelope( + from: $from ?? new Address('default@example.com', 'Default Sender'), + cc: $cc, + subject: trans('mail.Confirm_consumable_delivery'), + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + Log::debug($this->item->getImageUrl()); + $eula = $this->item->getEula(); + $req_accept = $this->item->requireAcceptance(); + + $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); + + return new Content( + markdown: 'mail.markdown.checkout-consumable', + with: [ + 'item' => $this->item, + 'admin' => $this->admin, + 'note' => $this->note, + 'target' => $this->target, + 'eula' => $eula, + 'req_accept' => $req_accept, + 'accept_url' => $accept_url, + ] + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php index 777834aae7bd..d2955151217b 100644 --- a/app/Notifications/CheckinAccessoryNotification.php +++ b/app/Notifications/CheckinAccessoryNotification.php @@ -6,6 +6,7 @@ use App\Models\Setting; use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Channels\SlackWebhookChannel; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -55,7 +56,7 @@ public function via() } if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) { - $notifyBy[] = 'slack'; + $notifyBy[] = SlackWebhookChannel::class; } return $notifyBy; diff --git a/app/Notifications/CheckoutConsumableNotification.php b/app/Notifications/CheckoutConsumableNotification.php index 6746795f2c63..0a2733689b93 100644 --- a/app/Notifications/CheckoutConsumableNotification.php +++ b/app/Notifications/CheckoutConsumableNotification.php @@ -6,6 +6,7 @@ use App\Models\Setting; use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Channels\SlackWebhookChannel; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -61,36 +62,36 @@ public function via() } if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) { - $notifyBy[] = 'slack'; + $notifyBy[] = SlackWebhookChannel::class; } - /** - * Only send notifications to users that have email addresses - */ - if ($this->target instanceof User && $this->target->email != '') { - - /** - * Send an email if the asset requires acceptance, - * so the user can accept or decline the asset - */ - if ($this->item->requireAcceptance()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if the item has a EULA, since the user should always receive it - */ - if ($this->item->getEula()) { - $notifyBy[1] = 'mail'; - } - - /** - * Send an email if an email should be sent at checkin/checkout - */ - if ((method_exists($this->item, 'checkin_email')) && ($this->item->checkin_email())) { - $notifyBy[1] = 'mail'; - } - } +// /** +// * Only send notifications to users that have email addresses +// */ +// if ($this->target instanceof User && $this->target->email != '') { +// +// /** +// * Send an email if the asset requires acceptance, +// * so the user can accept or decline the asset +// */ +// if ($this->item->requireAcceptance()) { +// $notifyBy[1] = 'mail'; +// } +// +// /** +// * Send an email if the item has a EULA, since the user should always receive it +// */ +// if ($this->item->getEula()) { +// $notifyBy[1] = 'mail'; +// } +// +// /** +// * Send an email if an email should be sent at checkin/checkout +// */ +// if ((method_exists($this->item, 'checkin_email')) && ($this->item->checkin_email())) { +// $notifyBy[1] = 'mail'; +// } +// } return $notifyBy; } @@ -165,30 +166,4 @@ public function toGoogleChat() ); } - - /** - * Get the mail representation of the notification. - * - * @return \Illuminate\Notifications\Messages\MailMessage - */ - public function toMail() - { - Log::debug($this->item->getImageUrl()); - $eula = $this->item->getEula(); - $req_accept = $this->item->requireAcceptance(); - - $accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance); - - return (new MailMessage)->markdown('notifications.markdown.checkout-consumable', - [ - 'item' => $this->item, - 'admin' => $this->admin, - 'note' => $this->note, - 'target' => $this->target, - 'eula' => $eula, - 'req_accept' => $req_accept, - 'accept_url' => $accept_url, - ]) - ->subject(trans('mail.Confirm_consumable_delivery')); - } } diff --git a/app/Notifications/CheckoutLicenseSeatNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php index 85d02abc9294..1c26138a6ed7 100644 --- a/app/Notifications/CheckoutLicenseSeatNotification.php +++ b/app/Notifications/CheckoutLicenseSeatNotification.php @@ -6,6 +6,7 @@ use App\Models\Setting; use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Channels\SlackWebhookChannel; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -60,7 +61,7 @@ public function via() } if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) { - $notifyBy[] = 'slack'; + $notifyBy[] = SlackWebhookChannel::class; } return $notifyBy; diff --git a/resources/views/notifications/markdown/checkout-consumable.blade.php b/resources/views/mail/markdown/checkout-consumable.blade.php similarity index 100% rename from resources/views/notifications/markdown/checkout-consumable.blade.php rename to resources/views/mail/markdown/checkout-consumable.blade.php From a7754c1a7fd6559b5d512fbd520556c9d10b76aa Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 16:46:52 -0700 Subject: [PATCH 17/59] fixed asset checkout markdown, and notifiable variable --- app/Listeners/CheckoutableListener.php | 35 +---- .../mail/markdown/checkout-asset.blade.php | 128 +++++++++--------- 2 files changed, 67 insertions(+), 96 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 4f51ed705f5d..44987e20d17c 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -16,10 +16,9 @@ use App\Models\Component; use App\Models\Consumable; use App\Models\LicenseSeat; -use App\Models\Recipients\AdminRecipient; use App\Models\Setting; -use App\Models\User; use App\Notifications\CheckinAccessoryNotification; +use App\Notifications\CheckinAssetNotification; use App\Notifications\CheckinLicenseSeatNotification; use App\Notifications\CheckoutAccessoryNotification; use App\Notifications\CheckoutAssetNotification; @@ -51,7 +50,7 @@ public function onCheckedOut($event) * Make a checkout acceptance and attach it in the notification */ $acceptance = $this->getCheckoutAcceptance($event); - $notifiable = $this->getNotifiable($event); + $notifiable = $event->checkedOutTo; $mailable = $this->getCheckoutMailType($event, $acceptance); // Send email notifications try { @@ -99,7 +98,7 @@ public function onCheckedIn($event) } } - $notifiable = $this->getNotifiable($event); + $notifiable = $event->checkedInBy; $mailable = $this->getCheckinMailType($event); // Send email notifications @@ -144,34 +143,6 @@ private function getCheckoutAcceptance($event) return $acceptance; } - /** - * Gets the entities to be notified of the passed event - * - * @param Event $event - * @return Collection - */ - private function getNotifiable($event) - { - $notifiable = collect(); - - /** - * Notify who checked out the item as long as the model can route notifications - */ - if (method_exists($event->checkedOutTo, 'routeNotificationFor')) { - $notifiable->push($event->checkedOutTo); - } - - /** - * Notify Admin users if the settings is activated - */ - if ((Setting::getSettings()) && (Setting::getSettings()->admin_cc_email != '')) { - $adminRecipient= new AdminRecipient; - $notifiable->push($adminRecipient->getEmail()); - } - - return new $notifiable; - } - /** * Get the appropriate notification for the event * diff --git a/resources/views/mail/markdown/checkout-asset.blade.php b/resources/views/mail/markdown/checkout-asset.blade.php index 5b4c811dd712..aae0b2158455 100644 --- a/resources/views/mail/markdown/checkout-asset.blade.php +++ b/resources/views/mail/markdown/checkout-asset.blade.php @@ -1,76 +1,76 @@ @component('mail::message') - # {{ trans('mail.hello') }} {{ $target->present()->fullName() }}, +# {{ trans('mail.hello') }} {{ $target->present()->fullName() }}, - {{ trans('mail.new_item_checked') }} +{{ trans('mail.new_item_checked') }} - @if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl()) -
Asset
- @endif +@if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl()) +
Asset
+@endif - @component('mail::table') - | | | - | ------------- | ------------- | - @if ((isset($item->name)) && ($item->name!='')) - | **{{ trans('mail.asset_name') }}** | {{ $item->name }} | - @endif - @if (($item->name!=$item->asset_tag)) - | **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} | - @endif - @if (isset($item->manufacturer)) - | **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} | - @endif - @if (isset($item->model)) - | **{{ trans('general.asset_model') }}** | {{ $item->model->name }} | - @endif - @if ((isset($item->model->model_number)) && ($item->model->name!=$item->model->model_number)) - | **{{ trans('general.model_no') }}** | {{ $item->model->model_number }} | - @endif - @if (isset($item->serial)) - | **{{ trans('mail.serial') }}** | {{ $item->serial }} | - @endif - @if (isset($last_checkout)) - | **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} | - @endif - @if (isset($status)) - | **{{ trans('general.status') }}** | {{ $status }} | - @endif - @if ((isset($expected_checkin)) && ($expected_checkin!='')) - | **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} | - @endif - @foreach($fields as $field) - @if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0')) - | **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} | - @endif - @endforeach - @if ($admin) - | **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} | - @endif - @if ($note) - | **{{ trans('mail.additional_notes') }}** | {{ $note }} | - @endif - @endcomponent +@component('mail::table') +| | | +| ------------- | ------------- | +@if ((isset($item->name)) && ($item->name!='')) +| **{{ trans('mail.asset_name') }}** | {{ $item->name }} | +@endif +@if (($item->name!=$item->asset_tag)) +| **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} | +@endif +@if (isset($item->manufacturer)) +| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} | +@endif +@if (isset($item->model)) +| **{{ trans('general.asset_model') }}** | {{ $item->model->name }} | +@endif +@if ((isset($item->model->model_number)) && ($item->model->name!=$item->model->model_number)) +| **{{ trans('general.model_no') }}** | {{ $item->model->model_number }} | +@endif +@if (isset($item->serial)) +| **{{ trans('mail.serial') }}** | {{ $item->serial }} | +@endif +@if (isset($last_checkout)) +| **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} | +@endif +@if (isset($status)) +| **{{ trans('general.status') }}** | {{ $status }} | +@endif +@if ((isset($expected_checkin)) && ($expected_checkin!='')) +| **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} | +@endif +@foreach($fields as $field) +@if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0')) +| **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} | +@endif +@endforeach +@if ($admin) +| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} | +@endif +@if ($note) +| **{{ trans('mail.additional_notes') }}** | {{ $note }} | +@endif +@endcomponent - @if (($req_accept == 1) && ($eula!='')) - {{ trans('mail.read_the_terms_and_click') }} - @elseif (($req_accept == 1) && ($eula=='')) - {{ trans('mail.click_on_the_link_asset') }} - @elseif (($req_accept == 0) && ($eula!='')) - {{ trans('mail.read_the_terms') }} - @endif +@if (($req_accept == 1) && ($eula!='')) +{{ trans('mail.read_the_terms_and_click') }} +@elseif (($req_accept == 1) && ($eula=='')) +{{ trans('mail.click_on_the_link_asset') }} +@elseif (($req_accept == 0) && ($eula!='')) +{{ trans('mail.read_the_terms') }} +@endif - @if ($eula) - @component('mail::panel') - {!! $eula !!} - @endcomponent - @endif +@if ($eula) +@component('mail::panel') +{!! $eula !!} +@endcomponent +@endif - @if ($req_accept == 1) - **[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})** - @endif +@if ($req_accept == 1) +**[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})** +@endif - {{ trans('mail.best_regards') }} +{{ trans('mail.best_regards') }} - {{ $snipeSettings->site_name }} +{{ $snipeSettings->site_name }} @endcomponent \ No newline at end of file From ed6034065b34797ba531782a207fe49384e0f465 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 16:47:36 -0700 Subject: [PATCH 18/59] removed test route --- routes/web.php | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/routes/web.php b/routes/web.php index bcbe159b3046..dbd1a53808b6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -57,27 +57,6 @@ /* * Locations */ - Route::get('/test-email', function() { - $item = LicenseSeat::find(1); // Load some test data - $admin = User::find(1); - $target = User::find(2); - $acceptance = null; // Simulate acceptance data - $note = 'Test note'; - - $fields = []; - if (($item->model) && ($item->model->fieldset)) { - $fields = $item->model->fieldset->fields; - } - - return new \App\Mail\CheckoutLicenseMail( - $item, - $admin, - $target, - $acceptance, - $note); - }); - - Route::group(['prefix' => 'locations', 'middleware' => ['auth']], function () { Route::post( From 9a794833755ff5fb335ab6cf1e118a0d411b021e Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Wed, 16 Oct 2024 16:59:18 -0700 Subject: [PATCH 19/59] removed namespaces from routing --- routes/web.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/routes/web.php b/routes/web.php index dbd1a53808b6..9d9d4ab21f14 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,10 +24,6 @@ use App\Http\Controllers\Auth\ForgotPasswordController; use App\Http\Controllers\Auth\ResetPasswordController; use App\Livewire\Importer; -use App\Models\Accessory; -use App\Models\Asset; -use App\Models\LicenseSeat; -use App\Models\User; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Auth; From 285d6897cf83d2cac7e791fa50d23ec88f116849 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 12:05:36 -0700 Subject: [PATCH 20/59] added a coulple test adjustments and moved mail send logic to listener --- app/Listeners/CheckoutableListener.php | 13 ++++ .../CheckoutAssetNotification.php | 9 --- .../CheckoutConsumableNotification.php | 54 ++++++------- .../markdown/checkout-asset.blade.php | 76 ------------------- .../Checkouts/Ui/ConsumableCheckoutTest.php | 7 +- .../EmailNotificationsUponCheckinTest.php | 22 +++--- 6 files changed, 57 insertions(+), 124 deletions(-) delete mode 100644 resources/views/notifications/markdown/checkout-asset.blade.php diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 44987e20d17c..3e23259fb682 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -57,8 +57,21 @@ public function onCheckedOut($event) if (!$event->checkedOutTo->locale){ $mailable->locale($event->checkedOutTo->locale); } + + /** + * Send an email if any of the following conditions are met: + * 1. The asset requires acceptance + * 2. The item has a EULA + * 3. The item should send an email at check-in/check-out + */ + + if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() || + (method_exists($event->checkoutable, 'checkin_email') && $event->checkoutable->checkin_email())) { + Mail::to($notifiable)->send($mailable); Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); + } + // Send Webhook notification if ($this->shouldSendWebhookNotification()) { Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) diff --git a/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php index 1ca329ed80e7..97706cec9474 100644 --- a/app/Notifications/CheckoutAssetNotification.php +++ b/app/Notifications/CheckoutAssetNotification.php @@ -9,7 +9,6 @@ use Exception; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Channels\SlackWebhookChannel; -use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; use NotificationChannels\GoogleChat\Card; @@ -154,12 +153,4 @@ public function toGoogleChat() ); } - - /** - * Get the mail representation of the notification. - * - * @param mixed $notifiable - * @return \Illuminate\Notifications\Messages\MailMessage - */ - } diff --git a/app/Notifications/CheckoutConsumableNotification.php b/app/Notifications/CheckoutConsumableNotification.php index 0a2733689b93..3f2adc33318b 100644 --- a/app/Notifications/CheckoutConsumableNotification.php +++ b/app/Notifications/CheckoutConsumableNotification.php @@ -65,33 +65,33 @@ public function via() $notifyBy[] = SlackWebhookChannel::class; } -// /** -// * Only send notifications to users that have email addresses -// */ -// if ($this->target instanceof User && $this->target->email != '') { -// -// /** -// * Send an email if the asset requires acceptance, -// * so the user can accept or decline the asset -// */ -// if ($this->item->requireAcceptance()) { -// $notifyBy[1] = 'mail'; -// } -// -// /** -// * Send an email if the item has a EULA, since the user should always receive it -// */ -// if ($this->item->getEula()) { -// $notifyBy[1] = 'mail'; -// } -// -// /** -// * Send an email if an email should be sent at checkin/checkout -// */ -// if ((method_exists($this->item, 'checkin_email')) && ($this->item->checkin_email())) { -// $notifyBy[1] = 'mail'; -// } -// } + /** + * Only send notifications to users that have email addresses + */ + if ($this->target instanceof User && $this->target->email != '') { + + /** + * Send an email if the asset requires acceptance, + * so the user can accept or decline the asset + */ + if ($this->item->requireAcceptance()) { + $notifyBy[1] = 'mail'; + } + + /** + * Send an email if the item has a EULA, since the user should always receive it + */ + if ($this->item->getEula()) { + $notifyBy[1] = 'mail'; + } + + /** + * Send an email if an email should be sent at checkin/checkout + */ + if ((method_exists($this->item, 'checkin_email')) && ($this->item->checkin_email())) { + $notifyBy[1] = 'mail'; + } + } return $notifyBy; } diff --git a/resources/views/notifications/markdown/checkout-asset.blade.php b/resources/views/notifications/markdown/checkout-asset.blade.php deleted file mode 100644 index 5b4c811dd712..000000000000 --- a/resources/views/notifications/markdown/checkout-asset.blade.php +++ /dev/null @@ -1,76 +0,0 @@ -@component('mail::message') - # {{ trans('mail.hello') }} {{ $target->present()->fullName() }}, - - {{ trans('mail.new_item_checked') }} - - @if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl()) -
Asset
- @endif - - @component('mail::table') - | | | - | ------------- | ------------- | - @if ((isset($item->name)) && ($item->name!='')) - | **{{ trans('mail.asset_name') }}** | {{ $item->name }} | - @endif - @if (($item->name!=$item->asset_tag)) - | **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} | - @endif - @if (isset($item->manufacturer)) - | **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} | - @endif - @if (isset($item->model)) - | **{{ trans('general.asset_model') }}** | {{ $item->model->name }} | - @endif - @if ((isset($item->model->model_number)) && ($item->model->name!=$item->model->model_number)) - | **{{ trans('general.model_no') }}** | {{ $item->model->model_number }} | - @endif - @if (isset($item->serial)) - | **{{ trans('mail.serial') }}** | {{ $item->serial }} | - @endif - @if (isset($last_checkout)) - | **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} | - @endif - @if (isset($status)) - | **{{ trans('general.status') }}** | {{ $status }} | - @endif - @if ((isset($expected_checkin)) && ($expected_checkin!='')) - | **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} | - @endif - @foreach($fields as $field) - @if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0')) - | **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} | - @endif - @endforeach - @if ($admin) - | **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} | - @endif - @if ($note) - | **{{ trans('mail.additional_notes') }}** | {{ $note }} | - @endif - @endcomponent - - @if (($req_accept == 1) && ($eula!='')) - {{ trans('mail.read_the_terms_and_click') }} - @elseif (($req_accept == 1) && ($eula=='')) - {{ trans('mail.click_on_the_link_asset') }} - @elseif (($req_accept == 0) && ($eula!='')) - {{ trans('mail.read_the_terms') }} - @endif - - @if ($eula) - @component('mail::panel') - {!! $eula !!} - @endcomponent - @endif - - @if ($req_accept == 1) - **[✔ {{ trans('mail.i_have_read') }}]({{ $accept_url }})** - @endif - - - {{ trans('mail.best_regards') }} - - {{ $snipeSettings->site_name }} - -@endcomponent \ No newline at end of file diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index 484b7e72cb72..46c34aedd75d 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -8,6 +8,7 @@ use App\Models\Consumable; use App\Models\User; use App\Notifications\CheckoutConsumableNotification; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Tests\TestCase; @@ -53,7 +54,7 @@ public function testConsumableCanBeCheckedOut() public function testUserSentNotificationUponCheckout() { - Notification::fake(); + Mail::fake(); $consumable = Consumable::factory()->create(); $user = User::factory()->create(); @@ -63,7 +64,9 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Notification::assertSentTo($user, CheckoutConsumableNotification::class); + Mail::assertSent(CheckoutConsumableNotification::class, function ($mail) use ($consumable, $user) { + return $mail->hasTo($user) && $mail->consumables->contains($consumable); + }); } public function testActionLogCreatedUponCheckout() diff --git a/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php b/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php index 449f65c7ab9c..c7c239b7abfb 100644 --- a/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php +++ b/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php @@ -2,6 +2,8 @@ namespace Tests\Feature\Notifications\Email; +use App\Mail\CheckinAssetMail; +use Illuminate\Support\Facades\Mail; use PHPUnit\Framework\Attributes\Group; use App\Events\CheckoutableCheckedIn; use App\Models\Asset; @@ -22,6 +24,8 @@ protected function setUp(): void public function testCheckInEmailSentToUserIfSettingEnabled() { + Mail::fake(); + $user = User::factory()->create(); $asset = Asset::factory()->assignedToUser($user)->create(); @@ -29,16 +33,16 @@ public function testCheckInEmailSentToUserIfSettingEnabled() $this->fireCheckInEvent($asset, $user); - Notification::assertSentTo( - $user, - function (CheckinAssetNotification $notification, $channels) { - return in_array('mail', $channels); - }, - ); + Mail::assertSent(CheckinAssetMail::class, function($mail) use ($user, $asset) { + return $mail->hasTo($user->email) && $mail->event->checkoutable->id === $asset->id; + }); + } public function testCheckInEmailNotSentToUserIfSettingDisabled() { + Mail::fake(); + $user = User::factory()->create(); $asset = Asset::factory()->assignedToUser($user)->create(); @@ -46,10 +50,8 @@ public function testCheckInEmailNotSentToUserIfSettingDisabled() $this->fireCheckInEvent($asset, $user); - Notification::assertNotSentTo( - $user, - function (CheckinAssetNotification $notification, $channels) { - return in_array('mail', $channels); + Mail::assertNotSent(CheckinAssetMail::class, function($mail) use ($user, $asset) { + return $mail->hasTo($user->email) && $mail->event->checkoutable->id === $asset->id; } ); } From 65735a31f178c8bd4e1efabc7190a30e3500f5fd Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 12:18:34 -0700 Subject: [PATCH 21/59] removed symfony/mailgun-mailer symfony/http-client --- composer.json | 2 - composer.lock | 415 +++++++++++++++++++++----------------------------- 2 files changed, 173 insertions(+), 244 deletions(-) diff --git a/composer.json b/composer.json index b255f821cd73..6d893125787c 100644 --- a/composer.json +++ b/composer.json @@ -63,8 +63,6 @@ "rollbar/rollbar-laravel": "^8.0", "spatie/laravel-backup": "^8.8", "spatie/laravel-ignition": "^2.0", - "symfony/http-client": "^7.1", - "symfony/mailgun-mailer": "^7.1", "tecnickcom/tc-lib-barcode": "^1.15", "tecnickcom/tcpdf": "^6.5", "unicodeveloper/laravel-password": "^1.0", diff --git a/composer.lock b/composer.lock index c6e469c5978f..9132659142f1 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": "0378e36c927d3838ac338c4f58ed30cd", + "content-hash": "3819ab4ef72eb77fabe494c0e746b83b", "packages": [ { "name": "alek13/slack", @@ -9081,178 +9081,6 @@ ], "time": "2024-08-13T14:27:37+00:00" }, - { - "name": "symfony/http-client", - "version": "v7.1.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.4" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-20T13:35:23+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/http-foundation", "version": "v6.4.12", @@ -9524,75 +9352,6 @@ ], "time": "2024-09-08T12:30:05+00:00" }, - { - "name": "symfony/mailgun-mailer", - "version": "v7.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "dac02fe68e9306849703025511c56f10701696a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/dac02fe68e9306849703025511c56f10701696a8", - "reference": "dac02fe68e9306849703025511c56f10701696a8", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/mailer": "^6.4|^7.0" - }, - "conflict": { - "symfony/http-foundation": "<6.4" - }, - "require-dev": { - "symfony/http-client": "^6.4|^7.0", - "symfony/webhook": "^6.4|^7.0" - }, - "type": "symfony-mailer-bridge", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mailer\\Bridge\\Mailgun\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Mailgun Mailer Bridge", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v7.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-07-04T11:20:59+00:00" - }, { "name": "symfony/mime", "version": "v6.4.12", @@ -16269,6 +16028,178 @@ ], "time": "2024-09-16T16:01:33+00:00" }, + { + "name": "symfony/http-client", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T13:35:23+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/options-resolver", "version": "v6.4.8", From ceb3f5cea629ed68fa4bfc119fefa2166456499c Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 12:19:50 -0700 Subject: [PATCH 22/59] added mail-gun and http-client to 8.1 --- composer.json | 2 + composer.lock | 415 +++++++++++++++++++++++++++++--------------------- 2 files changed, 244 insertions(+), 173 deletions(-) diff --git a/composer.json b/composer.json index 6d893125787c..b255f821cd73 100644 --- a/composer.json +++ b/composer.json @@ -63,6 +63,8 @@ "rollbar/rollbar-laravel": "^8.0", "spatie/laravel-backup": "^8.8", "spatie/laravel-ignition": "^2.0", + "symfony/http-client": "^7.1", + "symfony/mailgun-mailer": "^7.1", "tecnickcom/tc-lib-barcode": "^1.15", "tecnickcom/tcpdf": "^6.5", "unicodeveloper/laravel-password": "^1.0", diff --git a/composer.lock b/composer.lock index 9132659142f1..c6e469c5978f 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": "3819ab4ef72eb77fabe494c0e746b83b", + "content-hash": "0378e36c927d3838ac338c4f58ed30cd", "packages": [ { "name": "alek13/slack", @@ -9081,6 +9081,178 @@ ], "time": "2024-08-13T14:27:37+00:00" }, + { + "name": "symfony/http-client", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T13:35:23+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/http-foundation", "version": "v6.4.12", @@ -9352,6 +9524,75 @@ ], "time": "2024-09-08T12:30:05+00:00" }, + { + "name": "symfony/mailgun-mailer", + "version": "v7.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/mailgun-mailer.git", + "reference": "dac02fe68e9306849703025511c56f10701696a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/dac02fe68e9306849703025511c56f10701696a8", + "reference": "dac02fe68e9306849703025511c56f10701696a8", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/mailer": "^6.4|^7.0" + }, + "conflict": { + "symfony/http-foundation": "<6.4" + }, + "require-dev": { + "symfony/http-client": "^6.4|^7.0", + "symfony/webhook": "^6.4|^7.0" + }, + "type": "symfony-mailer-bridge", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mailer\\Bridge\\Mailgun\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Mailgun Mailer Bridge", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/mailgun-mailer/tree/v7.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-07-04T11:20:59+00:00" + }, { "name": "symfony/mime", "version": "v6.4.12", @@ -16028,178 +16269,6 @@ ], "time": "2024-09-16T16:01:33+00:00" }, - { - "name": "symfony/http-client", - "version": "v7.1.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.4" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-20T13:35:23+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/options-resolver", "version": "v6.4.8", From a690cc3582237fb6d40f8eaa3e3e83e7822574fc Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 12:26:55 -0700 Subject: [PATCH 23/59] removing my composer stuff again..for the last time --- composer.json | 2 - composer.lock | 415 +++++++++++++++++++++----------------------------- 2 files changed, 173 insertions(+), 244 deletions(-) diff --git a/composer.json b/composer.json index b255f821cd73..6d893125787c 100644 --- a/composer.json +++ b/composer.json @@ -63,8 +63,6 @@ "rollbar/rollbar-laravel": "^8.0", "spatie/laravel-backup": "^8.8", "spatie/laravel-ignition": "^2.0", - "symfony/http-client": "^7.1", - "symfony/mailgun-mailer": "^7.1", "tecnickcom/tc-lib-barcode": "^1.15", "tecnickcom/tcpdf": "^6.5", "unicodeveloper/laravel-password": "^1.0", diff --git a/composer.lock b/composer.lock index c6e469c5978f..9132659142f1 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": "0378e36c927d3838ac338c4f58ed30cd", + "content-hash": "3819ab4ef72eb77fabe494c0e746b83b", "packages": [ { "name": "alek13/slack", @@ -9081,178 +9081,6 @@ ], "time": "2024-08-13T14:27:37+00:00" }, - { - "name": "symfony/http-client", - "version": "v7.1.5", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client.git", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "psr/log": "^1|^2|^3", - "symfony/deprecation-contracts": "^2.5|^3", - "symfony/http-client-contracts": "^3.4.1", - "symfony/service-contracts": "^2.5|^3" - }, - "conflict": { - "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.4" - }, - "provide": { - "php-http/async-client-implementation": "*", - "php-http/client-implementation": "*", - "psr/http-client-implementation": "1.0", - "symfony/http-client-implementation": "3.0" - }, - "require-dev": { - "amphp/amp": "^2.5", - "amphp/http-client": "^4.2.1", - "amphp/http-tunnel": "^1.0", - "amphp/socket": "^1.1", - "guzzlehttp/promises": "^1.4|^2.0", - "nyholm/psr7": "^1.0", - "php-http/httplug": "^1.0|^2.0", - "psr/http-client": "^1.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Symfony\\Component\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", - "homepage": "https://symfony.com", - "keywords": [ - "http" - ], - "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.5" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-09-20T13:35:23+00:00" - }, - { - "name": "symfony/http-client-contracts", - "version": "v3.5.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "20414d96f391677bf80078aa55baece78b82647d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", - "reference": "20414d96f391677bf80078aa55baece78b82647d", - "shasum": "" - }, - "require": { - "php": ">=8.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Contracts\\HttpClient\\": "" - }, - "exclude-from-classmap": [ - "/Test/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Generic abstractions related to HTTP clients", - "homepage": "https://symfony.com", - "keywords": [ - "abstractions", - "contracts", - "decoupling", - "interfaces", - "interoperability", - "standards" - ], - "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-04-18T09:32:20+00:00" - }, { "name": "symfony/http-foundation", "version": "v6.4.12", @@ -9524,75 +9352,6 @@ ], "time": "2024-09-08T12:30:05+00:00" }, - { - "name": "symfony/mailgun-mailer", - "version": "v7.1.3", - "source": { - "type": "git", - "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "dac02fe68e9306849703025511c56f10701696a8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/dac02fe68e9306849703025511c56f10701696a8", - "reference": "dac02fe68e9306849703025511c56f10701696a8", - "shasum": "" - }, - "require": { - "php": ">=8.2", - "symfony/mailer": "^6.4|^7.0" - }, - "conflict": { - "symfony/http-foundation": "<6.4" - }, - "require-dev": { - "symfony/http-client": "^6.4|^7.0", - "symfony/webhook": "^6.4|^7.0" - }, - "type": "symfony-mailer-bridge", - "autoload": { - "psr-4": { - "Symfony\\Component\\Mailer\\Bridge\\Mailgun\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Mailgun Mailer Bridge", - "homepage": "https://symfony.com", - "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v7.1.3" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2024-07-04T11:20:59+00:00" - }, { "name": "symfony/mime", "version": "v6.4.12", @@ -16269,6 +16028,178 @@ ], "time": "2024-09-16T16:01:33+00:00" }, + { + "name": "symfony/http-client", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", + "reference": "abca35865118edf35a23f2f24978a1784c831cb4", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T13:35:23+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/options-resolver", "version": "v6.4.8", From 496b44e887078b6110f4e8e97e2b04bf22240677 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 12:28:57 -0700 Subject: [PATCH 24/59] merged composer lock from dev --- composer.lock | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/composer.lock b/composer.lock index 9132659142f1..3f79921b26df 100644 --- a/composer.lock +++ b/composer.lock @@ -16030,20 +16030,20 @@ }, { "name": "symfony/http-client", - "version": "v7.1.5", + "version": "v6.4.12", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4" + "reference": "fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/abca35865118edf35a23f2f24978a1784c831cb4", - "reference": "abca35865118edf35a23f2f24978a1784c831cb4", + "url": "https://api.github.com/repos/symfony/http-client/zipball/fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56", + "reference": "fbebfcce21084d3e91ea987ae5bdd8c71ff0fd56", "shasum": "" }, "require": { - "php": ">=8.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/deprecation-contracts": "^2.5|^3", "symfony/http-client-contracts": "^3.4.1", @@ -16051,7 +16051,7 @@ }, "conflict": { "php-http/discovery": "<1.15", - "symfony/http-foundation": "<6.4" + "symfony/http-foundation": "<6.3" }, "provide": { "php-http/async-client-implementation": "*", @@ -16068,12 +16068,11 @@ "nyholm/psr7": "^1.0", "php-http/httplug": "^1.0|^2.0", "psr/http-client": "^1.0", - "symfony/dependency-injection": "^6.4|^7.0", - "symfony/http-kernel": "^6.4|^7.0", - "symfony/messenger": "^6.4|^7.0", - "symfony/process": "^6.4|^7.0", - "symfony/rate-limiter": "^6.4|^7.0", - "symfony/stopwatch": "^6.4|^7.0" + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/http-kernel": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -16104,7 +16103,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.1.5" + "source": "https://github.com/symfony/http-client/tree/v6.4.12" }, "funding": [ { @@ -16120,7 +16119,7 @@ "type": "tidelift" } ], - "time": "2024-09-20T13:35:23+00:00" + "time": "2024-09-20T08:21:33+00:00" }, { "name": "symfony/http-client-contracts", @@ -16659,5 +16658,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 123cdeb858a8148cd8210847fcb39e635b7dc2bf Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 12:39:48 -0700 Subject: [PATCH 25/59] add email check to listener --- app/Listeners/CheckoutableListener.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index 3e23259fb682..ff76ae020e58 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -17,6 +17,7 @@ use App\Models\Consumable; use App\Models\LicenseSeat; use App\Models\Setting; +use App\Models\User; use App\Notifications\CheckinAccessoryNotification; use App\Notifications\CheckinAssetNotification; use App\Notifications\CheckinLicenseSeatNotification; @@ -64,13 +65,14 @@ public function onCheckedOut($event) * 2. The item has a EULA * 3. The item should send an email at check-in/check-out */ - + if ($notifiable instanceof User && $notifiable->email != '') { if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() || (method_exists($event->checkoutable, 'checkin_email') && $event->checkoutable->checkin_email())) { Mail::to($notifiable)->send($mailable); - Log::info('Sending email, Locale: ' .($event->checkedOutTo->locale ?? 'default')); + Log::info('Sending email, Locale: ' . ($event->checkedOutTo->locale ?? 'default')); } + } // Send Webhook notification if ($this->shouldSendWebhookNotification()) { From dceb8e305f55be79f3755a48bc3b4165dc79d43e Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 13:11:39 -0700 Subject: [PATCH 26/59] attempt to fix tests --- .../Checkins/Ui/AccessoryCheckinTest.php | 24 ++++++++----------- .../Checkouts/Ui/AccessoryCheckoutTest.php | 8 +++++-- .../Checkouts/Ui/ConsumableCheckoutTest.php | 3 ++- .../Importing/Api/ImportAssetsTest.php | 6 +++-- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php b/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php index 7a99b2ab56ab..56d429ac5625 100644 --- a/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php +++ b/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php @@ -3,10 +3,12 @@ namespace Tests\Feature\Checkins\Ui; use App\Events\CheckoutableCheckedIn; +use App\Mail\CheckoutAccessoryMail; use App\Models\Accessory; use App\Models\User; use App\Notifications\CheckinAccessoryNotification; use Illuminate\Support\Facades\Event; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Tests\TestCase; @@ -40,7 +42,7 @@ public function testAccessoryCanBeCheckedIn() public function testEmailSentToUserIfSettingEnabled() { - Notification::fake(); + Mail::fake(); $user = User::factory()->create(); $accessory = Accessory::factory()->checkedOutToUser($user)->create(); @@ -54,17 +56,14 @@ public function testEmailSentToUserIfSettingEnabled() '', )); - Notification::assertSentTo( - [$user], - function (CheckinAccessoryNotification $notification, $channels) { - return in_array('mail', $channels); - }, - ); + Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + return $mail->hasTo($user) && $mail->contains($accessory); + }); } public function testEmailNotSentToUserIfSettingDisabled() { - Notification::fake(); + Mail::fake(); $user = User::factory()->create(); $accessory = Accessory::factory()->checkedOutToUser($user)->create(); @@ -78,11 +77,8 @@ public function testEmailNotSentToUserIfSettingDisabled() '', )); - Notification::assertNotSentTo( - [$user], - function (CheckinAccessoryNotification $notification, $channels) { - return in_array('mail', $channels); - }, - ); + Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + return $mail->hasTo($user) && $mail->contains($accessory); + }); } } diff --git a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php index f63a8471f229..fedc1a258447 100644 --- a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php @@ -2,12 +2,14 @@ namespace Tests\Feature\Checkouts\Ui; +use App\Mail\CheckoutAccessoryMail; use App\Models\Accessory; use App\Models\Actionlog; use App\Models\Asset; use App\Models\Location; use App\Models\User; use App\Notifications\CheckoutAccessoryNotification; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Tests\TestCase; @@ -156,7 +158,7 @@ public function testAccessoryCanBeCheckedOutToAssetWithQuantity() public function testUserSentNotificationUponCheckout() { - Notification::fake(); + Mail::fake(); $accessory = Accessory::factory()->requiringAcceptance()->create(); $user = User::factory()->create(); @@ -168,7 +170,9 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Notification::assertSentTo($user, CheckoutAccessoryNotification::class); + Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + return $mail->hasTo($user) && $mail->contains($accessory); + }); } public function testActionLogCreatedUponCheckout() diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index 46c34aedd75d..2ce4a045337f 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -2,6 +2,7 @@ namespace Tests\Feature\Checkouts\Ui; +use App\Mail\CheckoutConsumableMail; use App\Models\Actionlog; use App\Models\Asset; use App\Models\Component; @@ -64,7 +65,7 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Mail::assertSent(CheckoutConsumableNotification::class, function ($mail) use ($consumable, $user) { + Mail::assertSent(CheckoutConsumableMail::class, function ($mail) use ($consumable, $user) { return $mail->hasTo($user) && $mail->consumables->contains($consumable); }); } diff --git a/tests/Feature/Importing/Api/ImportAssetsTest.php b/tests/Feature/Importing/Api/ImportAssetsTest.php index e001add381c5..66cc5174c4bf 100644 --- a/tests/Feature/Importing/Api/ImportAssetsTest.php +++ b/tests/Feature/Importing/Api/ImportAssetsTest.php @@ -2,6 +2,7 @@ namespace Tests\Feature\Importing\Api; +use App\Mail\CheckoutAssetMail; use App\Models\Actionlog as ActionLog; use App\Models\Asset; use App\Models\CustomField; @@ -11,6 +12,7 @@ use Carbon\Carbon; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Illuminate\Support\Str; use Illuminate\Testing\TestResponse; @@ -54,7 +56,7 @@ public function userWithImportAssetsPermissionCanImportAssets(): void #[Test] public function importAsset(): void { - Notification::fake(); + Mail::fake(); $importFileBuilder = ImportFileBuilder::new(); $row = $importFileBuilder->firstRow(); @@ -138,7 +140,7 @@ public function importAsset(): void //Notes is never read. // $this->assertEquals($row['notes'], $newAsset->notes); - Notification::assertSentTo($assignee, CheckoutAssetNotification::class); + Mail::assertSent($assignee, CheckoutAssetMail::class); } #[Test] From cdd4fef7df6d49951aaa09ca597995b90a26f2ad Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 13:34:55 -0700 Subject: [PATCH 27/59] attempt to fix tests p2 --- .../Feature/Checkins/Ui/AccessoryCheckinTest.php | 2 +- .../Checkouts/Api/AccessoryCheckoutTest.php | 8 ++++++-- .../Checkouts/Api/ConsumableCheckoutTest.php | 6 ++++-- .../Checkouts/Ui/AccessoryCheckoutTest.php | 2 +- .../Checkouts/Ui/ConsumableCheckoutTest.php | 2 +- tests/Feature/Importing/Api/ImportAssetsTest.php | 4 +++- .../Email/EmailNotificationsUponCheckinTest.php | 2 +- tests/Unit/NotificationTest.php | 16 +++++++++------- 8 files changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php b/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php index 56d429ac5625..419bead5a06f 100644 --- a/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php +++ b/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php @@ -77,7 +77,7 @@ public function testEmailNotSentToUserIfSettingDisabled() '', )); - Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { return $mail->hasTo($user) && $mail->contains($accessory); }); } diff --git a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php index 765b8436a03e..62a7b6873340 100644 --- a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php @@ -2,10 +2,12 @@ namespace Tests\Feature\Checkouts\Api; +use App\Mail\CheckoutAccessoryMail; use App\Models\Accessory; use App\Models\Actionlog; use App\Models\User; use App\Notifications\CheckoutAccessoryNotification; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Tests\Concerns\TestsPermissionsRequirement; use Tests\TestCase; @@ -146,7 +148,7 @@ public function testAccessoryCannotBeCheckedOutToInvalidUser() public function testUserSentNotificationUponCheckout() { - Notification::fake(); + Mail::fake(); $accessory = Accessory::factory()->requiringAcceptance()->create(); $user = User::factory()->create(); @@ -157,7 +159,9 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Notification::assertSentTo($user, CheckoutAccessoryNotification::class); + Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + return $mail->hasTo($user) && $mail->contains($accessory); + }); } public function testActionLogCreatedUponCheckout() diff --git a/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php index 94fa63cba320..eaeeb9fb83ca 100644 --- a/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php @@ -2,10 +2,12 @@ namespace Tests\Feature\Checkouts\Api; +use App\Mail\CheckoutConsumableMail; use App\Models\Actionlog; use App\Models\Consumable; use App\Models\User; use App\Notifications\CheckoutConsumableNotification; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Notification; use Tests\TestCase; @@ -51,7 +53,7 @@ public function testConsumableCanBeCheckedOut() public function testUserSentNotificationUponCheckout() { - Notification::fake(); + Mail::fake(); $consumable = Consumable::factory()->requiringAcceptance()->create(); @@ -62,7 +64,7 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Notification::assertSentTo($user, CheckoutConsumableNotification::class); + Mail::assertSentTo($user, CheckoutConsumableMail::class); } public function testActionLogCreatedUponCheckout() diff --git a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php index fedc1a258447..9b79b02da213 100644 --- a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php @@ -171,7 +171,7 @@ public function testUserSentNotificationUponCheckout() ]); Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { - return $mail->hasTo($user) && $mail->contains($accessory); + return $mail->hasTo($user->email) && $mail->accessory->is($accessory); }); } diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index 2ce4a045337f..4a8f6d7323a8 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -66,7 +66,7 @@ public function testUserSentNotificationUponCheckout() ]); Mail::assertSent(CheckoutConsumableMail::class, function ($mail) use ($consumable, $user) { - return $mail->hasTo($user) && $mail->consumables->contains($consumable); + return $mail->hasTo($user->email) && $mail->consumable->is($consumable); }); } diff --git a/tests/Feature/Importing/Api/ImportAssetsTest.php b/tests/Feature/Importing/Api/ImportAssetsTest.php index 66cc5174c4bf..58d3a83ecb04 100644 --- a/tests/Feature/Importing/Api/ImportAssetsTest.php +++ b/tests/Feature/Importing/Api/ImportAssetsTest.php @@ -140,7 +140,9 @@ public function importAsset(): void //Notes is never read. // $this->assertEquals($row['notes'], $newAsset->notes); - Mail::assertSent($assignee, CheckoutAssetMail::class); + Mail::assertSent(CheckoutAssetMail::class, function ($mail) use ($assignee) { + return $mail->hasTo($assignee->email); + }); } #[Test] diff --git a/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php b/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php index c7c239b7abfb..0b1a1fddc51d 100644 --- a/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php +++ b/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php @@ -19,7 +19,7 @@ protected function setUp(): void { parent::setUp(); - Notification::fake(); + Mail::fake(); } public function testCheckInEmailSentToUserIfSettingEnabled() diff --git a/tests/Unit/NotificationTest.php b/tests/Unit/NotificationTest.php index 86177c30306c..16350e117e6a 100644 --- a/tests/Unit/NotificationTest.php +++ b/tests/Unit/NotificationTest.php @@ -1,12 +1,14 @@ Carbon::createFromDate(2017, 1, 1)->hour(0)->minute(0)->second(0)->format('Y-m-d') ]); - Notification::fake(); + Mail::fake(); $asset->checkOut($user, $admin->id); - Notification::assertSentTo($user, CheckoutAssetNotification::class); + Mail::assertSent($user, CheckoutAssetMail::class); } public function testDefaultEulaIsSentWhenSetInCategory() { - Notification::fake(); + Mail::fake(); $this->settings->setEula('My Custom EULA Text'); @@ -51,10 +53,10 @@ public function testDefaultEulaIsSentWhenSetInCategory() $asset->checkOut($user, User::factory()->superuser()->create()->id); - Notification::assertSentTo($user, CheckoutAssetNotification::class, function ($notification) { - $content = $notification->toMail()->render(); - - return str_contains($content, 'My Custom EULA Text') && !str_contains($content, 'EULA Text that should not be used'); + Mail::assertSent(CheckoutAssetMail::class, function ($mail) use ($user) { + return $mail->hasTo($user->email) && + str_contains($mail->render(), 'My Custom EULA Text') && + !str_contains($mail->render(), 'EULA Text that should not be used'); }); } } From 83e8186d9e261efdde81ac56deeb9a799fdaa1e7 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 13:39:56 -0700 Subject: [PATCH 28/59] fix assertSent to AssertNotSent on some test --- tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php | 2 +- tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php | 2 +- tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php index 62a7b6873340..c0ea25f98f88 100644 --- a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php @@ -159,7 +159,7 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { return $mail->hasTo($user) && $mail->contains($accessory); }); } diff --git a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php index 9b79b02da213..b7210d936706 100644 --- a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php @@ -170,7 +170,7 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { return $mail->hasTo($user->email) && $mail->accessory->is($accessory); }); } diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index 4a8f6d7323a8..f404f37b0914 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -65,7 +65,7 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Mail::assertSent(CheckoutConsumableMail::class, function ($mail) use ($consumable, $user) { + Mail::assertNotSent(CheckoutConsumableMail::class, function ($mail) use ($consumable, $user) { return $mail->hasTo($user->email) && $mail->consumable->is($consumable); }); } From b98058ca98e02b865fdf1488e83a49d4bf7df9c8 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 13:48:26 -0700 Subject: [PATCH 29/59] fix tests pt 3 --- tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php | 2 +- tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php | 2 +- tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php | 2 +- tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php index c0ea25f98f88..9620b46bb614 100644 --- a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php @@ -160,7 +160,7 @@ public function testUserSentNotificationUponCheckout() ]); Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { - return $mail->hasTo($user) && $mail->contains($accessory); + return $mail->hasTo($user->email) && $mail->viewData['accessory']->id === $accessory->id; }); } diff --git a/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php index eaeeb9fb83ca..1b4a9ea33106 100644 --- a/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Api/ConsumableCheckoutTest.php @@ -64,7 +64,7 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Mail::assertSentTo($user, CheckoutConsumableMail::class); + Mail::assertSent($user, CheckoutConsumableMail::class); } public function testActionLogCreatedUponCheckout() diff --git a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php index b7210d936706..66751a06567b 100644 --- a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php @@ -171,7 +171,7 @@ public function testUserSentNotificationUponCheckout() ]); Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { - return $mail->hasTo($user->email) && $mail->accessory->is($accessory); + return $mail->hasTo($user->email) && $mail->viewData['accessory']->is($accessory); }); } diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index f404f37b0914..66e803c67bcf 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -66,7 +66,7 @@ public function testUserSentNotificationUponCheckout() ]); Mail::assertNotSent(CheckoutConsumableMail::class, function ($mail) use ($consumable, $user) { - return $mail->hasTo($user->email) && $mail->consumable->is($consumable); + return $mail->hasTo($user->email) && $mail->viewData['consumable']->is($consumable); }); } From 7ae76e7db9be7943ca473ab9ef30bda27b166aac Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 13:55:03 -0700 Subject: [PATCH 30/59] remove viewdata array from 3 tests --- tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php | 4 ++-- tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php | 4 ++-- tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php index 9620b46bb614..2b7b91058cb4 100644 --- a/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Api/AccessoryCheckoutTest.php @@ -159,8 +159,8 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { - return $mail->hasTo($user->email) && $mail->viewData['accessory']->id === $accessory->id; + Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($user) { + return $mail->hasTo($user->email); }); } diff --git a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php index 66751a06567b..980b390ad72a 100644 --- a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php @@ -170,8 +170,8 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { - return $mail->hasTo($user->email) && $mail->viewData['accessory']->is($accessory); + Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($user) { + return $mail->hasTo($user->email); }); } diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index 66e803c67bcf..76313bb71cc5 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -65,8 +65,8 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Mail::assertNotSent(CheckoutConsumableMail::class, function ($mail) use ($consumable, $user) { - return $mail->hasTo($user->email) && $mail->viewData['consumable']->is($consumable); + Mail::assertNotSent(CheckoutConsumableMail::class, function ($mail) use ($user) { + return $mail->hasTo($user->email); }); } From ff113ef523f77fb887b939a23de3936f603812a6 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Thu, 17 Oct 2024 14:56:58 -0700 Subject: [PATCH 31/59] typo fix --- app/Notifications/CheckinLicenseSeatNotification.php | 3 ++- tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php | 2 +- tests/Support/AssertsAgainstSlackNotifications.php | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Notifications/CheckinLicenseSeatNotification.php b/app/Notifications/CheckinLicenseSeatNotification.php index 114011bd7284..74018af7c9f9 100644 --- a/app/Notifications/CheckinLicenseSeatNotification.php +++ b/app/Notifications/CheckinLicenseSeatNotification.php @@ -6,6 +6,7 @@ use App\Models\Setting; use App\Models\User; use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Channels\SlackWebhookChannel; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Messages\SlackMessage; use Illuminate\Notifications\Notification; @@ -58,7 +59,7 @@ public function via() } if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) { - $notifyBy[] = 'slack'; + $notifyBy[] = SlackWebhookChannel::class; } return $notifyBy; diff --git a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php index 980b390ad72a..af9b286725d4 100644 --- a/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/AccessoryCheckoutTest.php @@ -170,7 +170,7 @@ public function testUserSentNotificationUponCheckout() 'checkout_to_type' => 'user', ]); - Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($user) { + Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($user) { return $mail->hasTo($user->email); }); } diff --git a/tests/Support/AssertsAgainstSlackNotifications.php b/tests/Support/AssertsAgainstSlackNotifications.php index 11e6beea2de9..e52f39a7e54f 100644 --- a/tests/Support/AssertsAgainstSlackNotifications.php +++ b/tests/Support/AssertsAgainstSlackNotifications.php @@ -14,6 +14,7 @@ public function assertSlackNotificationSent(string $notificationClass) new AnonymousNotifiable, $notificationClass, function ($notification, $channels, $notifiable) { + dd($notification); return $notifiable->routes['slack'] === Setting::getSettings()->webhook_endpoint; } ); From 1e31592c553e49eab175531cf9aa3b02ce738812 Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 22 Oct 2024 11:49:06 -0700 Subject: [PATCH 32/59] messing with the tests --- app/Listeners/CheckoutableListener.php | 36 ++++++++++++------- .../Checkins/Ui/AccessoryCheckinTest.php | 8 ++--- .../Checkouts/Ui/ConsumableCheckoutTest.php | 2 +- .../EmailNotificationsUponCheckinTest.php | 4 +-- 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php index ff76ae020e58..9c8abbcee896 100644 --- a/app/Listeners/CheckoutableListener.php +++ b/app/Listeners/CheckoutableListener.php @@ -59,16 +59,15 @@ public function onCheckedOut($event) $mailable->locale($event->checkedOutTo->locale); } - /** - * Send an email if any of the following conditions are met: - * 1. The asset requires acceptance - * 2. The item has a EULA - * 3. The item should send an email at check-in/check-out - */ - if ($notifiable instanceof User && $notifiable->email != '') { - if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() || - (method_exists($event->checkoutable, 'checkin_email') && $event->checkoutable->checkin_email())) { - + /** + * Send an email if any of the following conditions are met: + * 1. The asset requires acceptance + * 2. The item has a EULA + * 3. The item should send an email at check-in/check-out + */ + if ($notifiable instanceof User && $notifiable->email != '') { + if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() || + (method_exists($event->checkoutable, 'checkin_email') && $event->checkoutable->checkin_email())) { Mail::to($notifiable)->send($mailable); Log::info('Sending email, Locale: ' . ($event->checkedOutTo->locale ?? 'default')); } @@ -115,14 +114,25 @@ public function onCheckedIn($event) $notifiable = $event->checkedInBy; $mailable = $this->getCheckinMailType($event); - // Send email notifications try { if (!$event->checkedOutTo->locale){ $mailable->locale($event->checkedOutTo->locale); } - Mail::to($notifiable)->send($mailable); - \Log::info('Sending email, Locale: ' .$event->checkedOutTo->locale); + /** + * Send an email if any of the following conditions are met: + * 1. The asset requires acceptance + * 2. The item has a EULA + * 3. The item should send an email at check-in/check-out + */ + + if ($notifiable instanceof User && $notifiable->email != '') { + if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() || + (method_exists($event->checkoutable, 'checkin_email') && $event->checkoutable->checkin_email())) { + Mail::to($notifiable)->send($mailable); + Log::info('Sending email, Locale: ' . $event->checkedOutTo->locale); + } + } // Send Webhook notification if ($this->shouldSendWebhookNotification()) { Notification::route(Setting::getSettings()->webhook_selected, Setting::getSettings()->webhook_endpoint) diff --git a/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php b/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php index 419bead5a06f..b5fe540ae5b5 100644 --- a/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php +++ b/tests/Feature/Checkins/Ui/AccessoryCheckinTest.php @@ -3,7 +3,7 @@ namespace Tests\Feature\Checkins\Ui; use App\Events\CheckoutableCheckedIn; -use App\Mail\CheckoutAccessoryMail; +use App\Mail\CheckinAccessoryMail; use App\Models\Accessory; use App\Models\User; use App\Notifications\CheckinAccessoryNotification; @@ -56,8 +56,8 @@ public function testEmailSentToUserIfSettingEnabled() '', )); - Mail::assertSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { - return $mail->hasTo($user) && $mail->contains($accessory); + Mail::assertSent(CheckinAccessoryMail::class, function ($mail) use ( $user) { + return $mail->hasTo($user->email); }); } @@ -77,7 +77,7 @@ public function testEmailNotSentToUserIfSettingDisabled() '', )); - Mail::assertNotSent(CheckoutAccessoryMail::class, function ($mail) use ($accessory, $user) { + Mail::assertNotSent(CheckinAccessoryMail::class, function ($mail) use ($accessory, $user) { return $mail->hasTo($user) && $mail->contains($accessory); }); } diff --git a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php index 76313bb71cc5..2dc5fa62c0cf 100644 --- a/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php +++ b/tests/Feature/Checkouts/Ui/ConsumableCheckoutTest.php @@ -65,7 +65,7 @@ public function testUserSentNotificationUponCheckout() 'assigned_to' => $user->id, ]); - Mail::assertNotSent(CheckoutConsumableMail::class, function ($mail) use ($user) { + Mail::assertSent(CheckoutConsumableMail::class, function ($mail) use ($user) { return $mail->hasTo($user->email); }); } diff --git a/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php b/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php index 0b1a1fddc51d..098ef184c643 100644 --- a/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php +++ b/tests/Feature/Notifications/Email/EmailNotificationsUponCheckinTest.php @@ -33,8 +33,8 @@ public function testCheckInEmailSentToUserIfSettingEnabled() $this->fireCheckInEvent($asset, $user); - Mail::assertSent(CheckinAssetMail::class, function($mail) use ($user, $asset) { - return $mail->hasTo($user->email) && $mail->event->checkoutable->id === $asset->id; + Mail::assertSent(CheckinAssetMail::class, function($mail) use ($user) { + return $mail->hasTo($user->email); }); } From 0d59ccd6a66cf15a55afc1b92be8ab5e2a3679cb Mon Sep 17 00:00:00 2001 From: Godfrey M Date: Tue, 22 Oct 2024 14:23:26 -0700 Subject: [PATCH 33/59] upgraded livewire v3.5.9 => v3.5.12 --- .../Api/StatuslabelsController.php | 2 +- composer.lock | 14 +-- public/vendor/livewire/livewire.esm.js | 86 +++++++++++++----- public/vendor/livewire/livewire.js | 89 ++++++++++++++----- public/vendor/livewire/livewire.min.js | 12 +-- public/vendor/livewire/livewire.min.js.map | 6 +- public/vendor/livewire/manifest.json | 2 +- .../lang/en-US/admin/statuslabels/message.php | 2 +- 8 files changed, 152 insertions(+), 61 deletions(-) diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php index 7e4851ff5ae1..0d7d46cd0f3c 100644 --- a/app/Http/Controllers/Api/StatuslabelsController.php +++ b/app/Http/Controllers/Api/StatuslabelsController.php @@ -96,7 +96,7 @@ public function store(Request $request) : JsonResponse if (! $request->filled('type')) { - return response()->json(Helper::formatStandardApiResponse('error', null, ['type' => ['Status label type is required.']])); + return response()->json(Helper::formatStandardApiResponse('error', null, ['type' => [trans('admin/statuslabels/message.require_status_label')]])); } $statuslabel = new Statuslabel; diff --git a/composer.lock b/composer.lock index 0631fc275e29..5850996b11ad 100644 --- a/composer.lock +++ b/composer.lock @@ -4461,16 +4461,16 @@ }, { "name": "livewire/livewire", - "version": "v3.5.9", + "version": "v3.5.12", "source": { "type": "git", "url": "https://github.com/livewire/livewire.git", - "reference": "d04a229058afa76116d0e39209943a8ea3a7f888" + "reference": "3c8d1f9d7d9098aaea663093ae168f2d5d2ae73d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/livewire/livewire/zipball/d04a229058afa76116d0e39209943a8ea3a7f888", - "reference": "d04a229058afa76116d0e39209943a8ea3a7f888", + "url": "https://api.github.com/repos/livewire/livewire/zipball/3c8d1f9d7d9098aaea663093ae168f2d5d2ae73d", + "reference": "3c8d1f9d7d9098aaea663093ae168f2d5d2ae73d", "shasum": "" }, "require": { @@ -4525,7 +4525,7 @@ "description": "A front-end framework for Laravel.", "support": { "issues": "https://github.com/livewire/livewire/issues", - "source": "https://github.com/livewire/livewire/tree/v3.5.9" + "source": "https://github.com/livewire/livewire/tree/v3.5.12" }, "funding": [ { @@ -4533,7 +4533,7 @@ "type": "github" } ], - "time": "2024-10-01T12:40:06+00:00" + "time": "2024-10-15T19:35:06+00:00" }, { "name": "masterminds/html5", @@ -16504,5 +16504,5 @@ "ext-pdo": "*" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/public/vendor/livewire/livewire.esm.js b/public/vendor/livewire/livewire.esm.js index ae4bb2cb78d3..2d7ef4791c87 100644 --- a/public/vendor/livewire/livewire.esm.js +++ b/public/vendor/livewire/livewire.esm.js @@ -2557,7 +2557,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); } } function bindInputValue(el, value) { - if (el.type === "radio") { + if (isRadio(el)) { if (el.attributes.value === void 0) { el.value = value; } @@ -2568,7 +2568,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); el.checked = checkedAttrLooseCompare(el.value, value); } } - } else if (el.type === "checkbox") { + } else if (isCheckbox(el)) { if (Number.isInteger(value)) { el.value = value; } else if (!Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) { @@ -2707,6 +2707,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); } return attr; } + function isCheckbox(el) { + return el.type === "checkbox" || el.localName === "ui-checkbox" || el.localName === "ui-switch"; + } + function isRadio(el) { + return el.type === "radio" || el.localName === "ui-radio"; + } function debounce2(func, wait) { var timeout; return function() { @@ -2860,7 +2866,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); get raw() { return raw; }, - version: "3.14.1", + version: "3.14.3", flushAndStopDeferringMutations, dontAutoEvaluateFunctions, disableEffectScheduling, @@ -3296,7 +3302,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); setValue(getInputValue(el, modifiers, e, getValue())); }); if (modifiers.includes("fill")) { - if ([void 0, null, ""].includes(getValue()) || el.type === "checkbox" && Array.isArray(getValue()) || el.tagName.toLowerCase() === "select" && el.multiple) { + if ([void 0, null, ""].includes(getValue()) || isCheckbox(el) && Array.isArray(getValue()) || el.tagName.toLowerCase() === "select" && el.multiple) { setValue(getInputValue(el, modifiers, { target: el }, getValue())); } } @@ -3336,7 +3342,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); return mutateDom(() => { if (event instanceof CustomEvent && event.detail !== void 0) return event.detail !== null && event.detail !== void 0 ? event.detail : event.target.value; - else if (el.type === "checkbox") { + else if (isCheckbox(el)) { if (Array.isArray(currentValue)) { let newValue = null; if (modifiers.includes("number")) { @@ -3367,7 +3373,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); }); } else { let newValue; - if (el.type === "radio") { + if (isRadio(el)) { if (event.target.checked) { newValue = event.target.value; } else { @@ -6820,8 +6826,6 @@ var require_module_cjs8 = __commonJS({ let toAttributes = Array.from(to.attributes); for (let i = domAttributes.length - 1; i >= 0; i--) { let name = domAttributes[i].name; - if (name === "style") - continue; if (!to.hasAttribute(name)) { from2.removeAttribute(name); } @@ -6829,8 +6833,6 @@ var require_module_cjs8 = __commonJS({ for (let i = toAttributes.length - 1; i >= 0; i--) { let name = toAttributes[i].name; let value = toAttributes[i].value; - if (name === "style") - continue; if (from2.getAttribute(name) !== value) { from2.setAttribute(name, value); } @@ -9015,6 +9017,44 @@ function injectStyles() { document.head.appendChild(style); } +// js/plugins/navigate/popover.js +function packUpPersistedPopovers(persistedEl) { + persistedEl.querySelectorAll(":popover-open").forEach((el) => { + el.setAttribute("data-navigate-popover-open", ""); + let animations = el.getAnimations(); + el._pausedAnimations = animations.map((animation) => ({ + keyframes: animation.effect.getKeyframes(), + options: { + duration: animation.effect.getTiming().duration, + easing: animation.effect.getTiming().easing, + fill: animation.effect.getTiming().fill, + iterations: animation.effect.getTiming().iterations + }, + currentTime: animation.currentTime, + playState: animation.playState + })); + animations.forEach((i) => i.pause()); + }); +} +function unPackPersistedPopovers(persistedEl) { + persistedEl.querySelectorAll("[data-navigate-popover-open]").forEach((el) => { + el.removeAttribute("data-navigate-popover-open"); + queueMicrotask(() => { + if (!el.isConnected) + return; + el.showPopover(); + el.getAnimations().forEach((i) => i.finish()); + if (el._pausedAnimations) { + el._pausedAnimations.forEach(({ keyframes, options, currentTime, now, playState }) => { + let animation = el.animate(keyframes, options); + animation.currentTime = currentTime; + }); + delete el._pausedAnimations; + } + }); + }); +} + // js/plugins/navigate/page.js var oldBodyScriptTagHashes = []; var attributesExemptFromScriptTagHashing = [ @@ -9153,7 +9193,7 @@ var autofocus = false; function navigate_default(Alpine19) { Alpine19.navigate = (url) => { let destination = createUrlObjectFromString(url); - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: false, cached: false @@ -9184,7 +9224,7 @@ function navigate_default(Alpine19) { storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination); }); whenItIsReleased(() => { - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: false, cached: false @@ -9198,7 +9238,7 @@ function navigate_default(Alpine19) { function navigateTo(destination, shouldPushToHistoryState = true) { showProgressBar && showAndStartProgressBar(); fetchHtmlOrUsePrefetchedHtml(destination, (html, finalDestination) => { - fireEventForOtherLibariesToHookInto("alpine:navigating"); + fireEventForOtherLibrariesToHookInto("alpine:navigating"); restoreScroll && storeScrollInformationInHtmlBeforeNavigatingAway(); showProgressBar && finishAndHideProgressBar(); cleanupAlpineElementsOnThePageThatArentInsideAPersistedElement(); @@ -9206,6 +9246,7 @@ function navigate_default(Alpine19) { preventAlpineFromPickingUpDomChanges(Alpine19, (andAfterAllThis) => { enablePersist && storePersistantElementsForLater((persistedEl) => { packUpPersistedTeleports(persistedEl); + packUpPersistedPopovers(persistedEl); }); if (shouldPushToHistoryState) { updateUrlAndStoreLatestHtmlForFutureBackButtons(html, finalDestination); @@ -9216,6 +9257,7 @@ function navigate_default(Alpine19) { removeAnyLeftOverStaleTeleportTargets(document.body); enablePersist && putPersistantElementsBack((persistedEl, newStub) => { unPackPersistedTeleports(persistedEl); + unPackPersistedPopovers(persistedEl); }); restoreScrollPositionOrScrollToTop(); afterNewScriptsAreDoneLoading(() => { @@ -9224,7 +9266,7 @@ function navigate_default(Alpine19) { autofocus && autofocusElementsWithTheAutofocusAttribute(); }); nowInitializeAlpineOnTheNewPage(Alpine19); - fireEventForOtherLibariesToHookInto("alpine:navigated"); + fireEventForOtherLibrariesToHookInto("alpine:navigated"); }); }); }); @@ -9234,7 +9276,7 @@ function navigate_default(Alpine19) { whenTheBackOrForwardButtonIsClicked((ifThePageBeingVisitedHasntBeenCached) => { ifThePageBeingVisitedHasntBeenCached((url) => { let destination = createUrlObjectFromString(url); - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: true, cached: false @@ -9246,7 +9288,7 @@ function navigate_default(Alpine19) { }); }, (html, url, currentPageUrl, currentPageKey) => { let destination = createUrlObjectFromString(url); - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: true, cached: true @@ -9254,29 +9296,31 @@ function navigate_default(Alpine19) { if (prevented) return; storeScrollInformationInHtmlBeforeNavigatingAway(); - fireEventForOtherLibariesToHookInto("alpine:navigating"); + fireEventForOtherLibrariesToHookInto("alpine:navigating"); updateCurrentPageHtmlInSnapshotCacheForLaterBackButtonClicks(currentPageUrl, currentPageKey); preventAlpineFromPickingUpDomChanges(Alpine19, (andAfterAllThis) => { enablePersist && storePersistantElementsForLater((persistedEl) => { packUpPersistedTeleports(persistedEl); + packUpPersistedPopovers(persistedEl); }); swapCurrentPageWithNewHtml(html, () => { removeAnyLeftOverStaleProgressBars(); removeAnyLeftOverStaleTeleportTargets(document.body); enablePersist && putPersistantElementsBack((persistedEl, newStub) => { unPackPersistedTeleports(persistedEl); + unPackPersistedPopovers(persistedEl); }); restoreScrollPositionOrScrollToTop(); andAfterAllThis(() => { autofocus && autofocusElementsWithTheAutofocusAttribute(); nowInitializeAlpineOnTheNewPage(Alpine19); - fireEventForOtherLibariesToHookInto("alpine:navigated"); + fireEventForOtherLibrariesToHookInto("alpine:navigated"); }); }); }); }); setTimeout(() => { - fireEventForOtherLibariesToHookInto("alpine:navigated"); + fireEventForOtherLibrariesToHookInto("alpine:navigated"); }); } function fetchHtmlOrUsePrefetchedHtml(fromDestination, callback) { @@ -9293,7 +9337,7 @@ function preventAlpineFromPickingUpDomChanges(Alpine19, callback) { }); }); } -function fireEventForOtherLibariesToHookInto(name, detail) { +function fireEventForOtherLibrariesToHookInto(name, detail) { let event = new CustomEvent(name, { cancelable: true, bubbles: true, @@ -9809,6 +9853,7 @@ function morph2(component, el, html) { }, lookahead: false }); + trigger("morphed", { el, component }); } function isntElement(el) { return typeof el.hasAttribute !== "function"; @@ -10878,3 +10923,4 @@ focus-trap/dist/focus-trap.js: * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE *) */ +//# sourceMappingURL=livewire.esm.js.map diff --git a/public/vendor/livewire/livewire.js b/public/vendor/livewire/livewire.js index 687180f6b18e..670591055fa8 100644 --- a/public/vendor/livewire/livewire.js +++ b/public/vendor/livewire/livewire.js @@ -1975,7 +1975,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); } } function bindInputValue(el, value) { - if (el.type === "radio") { + if (isRadio(el)) { if (el.attributes.value === void 0) { el.value = value; } @@ -1986,7 +1986,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); el.checked = checkedAttrLooseCompare(el.value, value); } } - } else if (el.type === "checkbox") { + } else if (isCheckbox(el)) { if (Number.isInteger(value)) { el.value = value; } else if (!Array.isArray(value) && typeof value !== "boolean" && ![null, void 0].includes(value)) { @@ -2125,6 +2125,12 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); } return attr; } + function isCheckbox(el) { + return el.type === "checkbox" || el.localName === "ui-checkbox" || el.localName === "ui-switch"; + } + function isRadio(el) { + return el.type === "radio" || el.localName === "ui-radio"; + } function debounce(func, wait) { var timeout; return function() { @@ -2278,7 +2284,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); get raw() { return raw; }, - version: "3.14.1", + version: "3.14.3", flushAndStopDeferringMutations, dontAutoEvaluateFunctions, disableEffectScheduling, @@ -3361,7 +3367,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); setValue(getInputValue(el, modifiers, e, getValue())); }); if (modifiers.includes("fill")) { - if ([void 0, null, ""].includes(getValue()) || el.type === "checkbox" && Array.isArray(getValue()) || el.tagName.toLowerCase() === "select" && el.multiple) { + if ([void 0, null, ""].includes(getValue()) || isCheckbox(el) && Array.isArray(getValue()) || el.tagName.toLowerCase() === "select" && el.multiple) { setValue(getInputValue(el, modifiers, { target: el }, getValue())); } } @@ -3401,7 +3407,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); return mutateDom(() => { if (event instanceof CustomEvent && event.detail !== void 0) return event.detail !== null && event.detail !== void 0 ? event.detail : event.target.value; - else if (el.type === "checkbox") { + else if (isCheckbox(el)) { if (Array.isArray(currentValue)) { let newValue = null; if (modifiers.includes("number")) { @@ -3432,7 +3438,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); }); } else { let newValue; - if (el.type === "radio") { + if (isRadio(el)) { if (event.target.checked) { newValue = event.target.value; } else { @@ -4971,11 +4977,11 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); var checked = getCheckedRadio(radioSet, node.form); return !checked || checked === node; }; - var isRadio = function isRadio2(node) { + var isRadio2 = function isRadio22(node) { return isInput(node) && node.type === "radio"; }; var isNonTabbableRadio = function isNonTabbableRadio2(node) { - return isRadio(node) && !isTabbableRadio(node); + return isRadio2(node) && !isTabbableRadio(node); }; var isZeroArea = function isZeroArea2(node) { var _node$getBoundingClie = node.getBoundingClientRect(), width = _node$getBoundingClie.width, height = _node$getBoundingClie.height; @@ -7625,6 +7631,44 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); document.head.appendChild(style); } + // js/plugins/navigate/popover.js + function packUpPersistedPopovers(persistedEl) { + persistedEl.querySelectorAll(":popover-open").forEach((el) => { + el.setAttribute("data-navigate-popover-open", ""); + let animations = el.getAnimations(); + el._pausedAnimations = animations.map((animation) => ({ + keyframes: animation.effect.getKeyframes(), + options: { + duration: animation.effect.getTiming().duration, + easing: animation.effect.getTiming().easing, + fill: animation.effect.getTiming().fill, + iterations: animation.effect.getTiming().iterations + }, + currentTime: animation.currentTime, + playState: animation.playState + })); + animations.forEach((i) => i.pause()); + }); + } + function unPackPersistedPopovers(persistedEl) { + persistedEl.querySelectorAll("[data-navigate-popover-open]").forEach((el) => { + el.removeAttribute("data-navigate-popover-open"); + queueMicrotask(() => { + if (!el.isConnected) + return; + el.showPopover(); + el.getAnimations().forEach((i) => i.finish()); + if (el._pausedAnimations) { + el._pausedAnimations.forEach(({ keyframes, options, currentTime, now, playState }) => { + let animation = el.animate(keyframes, options); + animation.currentTime = currentTime; + }); + delete el._pausedAnimations; + } + }); + }); + } + // js/plugins/navigate/page.js var oldBodyScriptTagHashes = []; var attributesExemptFromScriptTagHashing = [ @@ -7763,7 +7807,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); function navigate_default(Alpine3) { Alpine3.navigate = (url) => { let destination = createUrlObjectFromString(url); - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: false, cached: false @@ -7794,7 +7838,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination); }); whenItIsReleased(() => { - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: false, cached: false @@ -7808,7 +7852,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); function navigateTo(destination, shouldPushToHistoryState = true) { showProgressBar && showAndStartProgressBar(); fetchHtmlOrUsePrefetchedHtml(destination, (html, finalDestination) => { - fireEventForOtherLibariesToHookInto("alpine:navigating"); + fireEventForOtherLibrariesToHookInto("alpine:navigating"); restoreScroll && storeScrollInformationInHtmlBeforeNavigatingAway(); showProgressBar && finishAndHideProgressBar(); cleanupAlpineElementsOnThePageThatArentInsideAPersistedElement(); @@ -7816,6 +7860,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); preventAlpineFromPickingUpDomChanges(Alpine3, (andAfterAllThis) => { enablePersist && storePersistantElementsForLater((persistedEl) => { packUpPersistedTeleports(persistedEl); + packUpPersistedPopovers(persistedEl); }); if (shouldPushToHistoryState) { updateUrlAndStoreLatestHtmlForFutureBackButtons(html, finalDestination); @@ -7826,6 +7871,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); removeAnyLeftOverStaleTeleportTargets(document.body); enablePersist && putPersistantElementsBack((persistedEl, newStub) => { unPackPersistedTeleports(persistedEl); + unPackPersistedPopovers(persistedEl); }); restoreScrollPositionOrScrollToTop(); afterNewScriptsAreDoneLoading(() => { @@ -7834,7 +7880,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); autofocus && autofocusElementsWithTheAutofocusAttribute(); }); nowInitializeAlpineOnTheNewPage(Alpine3); - fireEventForOtherLibariesToHookInto("alpine:navigated"); + fireEventForOtherLibrariesToHookInto("alpine:navigated"); }); }); }); @@ -7844,7 +7890,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); whenTheBackOrForwardButtonIsClicked((ifThePageBeingVisitedHasntBeenCached) => { ifThePageBeingVisitedHasntBeenCached((url) => { let destination = createUrlObjectFromString(url); - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: true, cached: false @@ -7856,7 +7902,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); }); }, (html, url, currentPageUrl, currentPageKey) => { let destination = createUrlObjectFromString(url); - let prevented = fireEventForOtherLibariesToHookInto("alpine:navigate", { + let prevented = fireEventForOtherLibrariesToHookInto("alpine:navigate", { url: destination, history: true, cached: true @@ -7864,29 +7910,31 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); if (prevented) return; storeScrollInformationInHtmlBeforeNavigatingAway(); - fireEventForOtherLibariesToHookInto("alpine:navigating"); + fireEventForOtherLibrariesToHookInto("alpine:navigating"); updateCurrentPageHtmlInSnapshotCacheForLaterBackButtonClicks(currentPageUrl, currentPageKey); preventAlpineFromPickingUpDomChanges(Alpine3, (andAfterAllThis) => { enablePersist && storePersistantElementsForLater((persistedEl) => { packUpPersistedTeleports(persistedEl); + packUpPersistedPopovers(persistedEl); }); swapCurrentPageWithNewHtml(html, () => { removeAnyLeftOverStaleProgressBars(); removeAnyLeftOverStaleTeleportTargets(document.body); enablePersist && putPersistantElementsBack((persistedEl, newStub) => { unPackPersistedTeleports(persistedEl); + unPackPersistedPopovers(persistedEl); }); restoreScrollPositionOrScrollToTop(); andAfterAllThis(() => { autofocus && autofocusElementsWithTheAutofocusAttribute(); nowInitializeAlpineOnTheNewPage(Alpine3); - fireEventForOtherLibariesToHookInto("alpine:navigated"); + fireEventForOtherLibrariesToHookInto("alpine:navigated"); }); }); }); }); setTimeout(() => { - fireEventForOtherLibariesToHookInto("alpine:navigated"); + fireEventForOtherLibrariesToHookInto("alpine:navigated"); }); } function fetchHtmlOrUsePrefetchedHtml(fromDestination, callback) { @@ -7903,7 +7951,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); }); }); } - function fireEventForOtherLibariesToHookInto(name, detail) { + function fireEventForOtherLibrariesToHookInto(name, detail) { let event = new CustomEvent(name, { cancelable: true, bubbles: true, @@ -8212,8 +8260,6 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); let toAttributes = Array.from(to.attributes); for (let i = domAttributes.length - 1; i >= 0; i--) { let name = domAttributes[i].name; - if (name === "style") - continue; if (!to.hasAttribute(name)) { from2.removeAttribute(name); } @@ -8221,8 +8267,6 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); for (let i = toAttributes.length - 1; i >= 0; i--) { let name = toAttributes[i].name; let value = toAttributes[i].value; - if (name === "style") - continue; if (from2.getAttribute(name) !== value) { from2.setAttribute(name, value); } @@ -8914,6 +8958,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el); }, lookahead: false }); + trigger2("morphed", { el, component }); } function isntElement(el) { return typeof el.hasAttribute !== "function"; diff --git a/public/vendor/livewire/livewire.min.js b/public/vendor/livewire/livewire.min.js index 90a91971d8e4..32197b3ebf7d 100644 --- a/public/vendor/livewire/livewire.min.js +++ b/public/vendor/livewire/livewire.min.js @@ -1,14 +1,14 @@ -(()=>{var nl=Object.create;var ii=Object.defineProperty;var il=Object.getOwnPropertyDescriptor;var ol=Object.getOwnPropertyNames;var sl=Object.getPrototypeOf,al=Object.prototype.hasOwnProperty;var ll=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var ul=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ol(t))!al.call(e,i)&&i!==r&&ii(e,i,{get:()=>t[i],enumerable:!(n=il(t,i))||n.enumerable});return e};var cl=(e,t,r)=>(r=e!=null?nl(sl(e)):{},ul(t||!e||!e.__esModule?ii(r,"default",{value:e,enumerable:!0}):r,e));var da=ll((Hn,fa)=>{(function(e,t){typeof define=="function"&&define.amd?define(t):typeof Hn=="object"?fa.exports=t():e.NProgress=t()})(Hn,function(){var e={};e.version="0.2.0";var t=e.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};e.configure=function(c){var d,m;for(d in c)m=c[d],m!==void 0&&c.hasOwnProperty(d)&&(t[d]=m);return this},e.status=null,e.set=function(c){var d=e.isStarted();c=r(c,t.minimum,1),e.status=c===1?null:c;var m=e.render(!d),b=m.querySelector(t.barSelector),g=t.speed,y=t.easing;return m.offsetWidth,o(function(v){t.positionUsing===""&&(t.positionUsing=e.getPositioningCSS()),s(b,i(c,g,y)),c===1?(s(m,{transition:"none",opacity:1}),m.offsetWidth,setTimeout(function(){s(m,{transition:"all "+g+"ms linear",opacity:0}),setTimeout(function(){e.remove(),v()},g)},g)):setTimeout(v,g)}),this},e.isStarted=function(){return typeof e.status=="number"},e.start=function(){e.status||e.set(0);var c=function(){setTimeout(function(){!e.status||(e.trickle(),c())},t.trickleSpeed)};return t.trickle&&c(),this},e.done=function(c){return!c&&!e.status?this:e.inc(.3+.5*Math.random()).set(1)},e.inc=function(c){var d=e.status;return d?(typeof c!="number"&&(c=(1-d)*r(Math.random()*d,.1,.95)),d=r(d+c,0,.994),e.set(d)):e.start()},e.trickle=function(){return e.inc(Math.random()*t.trickleRate)},function(){var c=0,d=0;e.promise=function(m){return!m||m.state()==="resolved"?this:(d===0&&e.start(),c++,d++,m.always(function(){d--,d===0?(c=0,e.done()):e.set((c-d)/c)}),this)}}(),e.render=function(c){if(e.isRendered())return document.getElementById("nprogress");l(document.documentElement,"nprogress-busy");var d=document.createElement("div");d.id="nprogress",d.innerHTML=t.template;var m=d.querySelector(t.barSelector),b=c?"-100":n(e.status||0),g=document.querySelector(t.parent),y;return s(m,{transition:"all 0 linear",transform:"translate3d("+b+"%,0,0)"}),t.showSpinner||(y=d.querySelector(t.spinnerSelector),y&&p(y)),g!=document.body&&l(g,"nprogress-custom-parent"),g.appendChild(d),d},e.remove=function(){u(document.documentElement,"nprogress-busy"),u(document.querySelector(t.parent),"nprogress-custom-parent");var c=document.getElementById("nprogress");c&&p(c)},e.isRendered=function(){return!!document.getElementById("nprogress")},e.getPositioningCSS=function(){var c=document.body.style,d="WebkitTransform"in c?"Webkit":"MozTransform"in c?"Moz":"msTransform"in c?"ms":"OTransform"in c?"O":"";return d+"Perspective"in c?"translate3d":d+"Transform"in c?"translate":"margin"};function r(c,d,m){return cm?m:c}function n(c){return(-1+c)*100}function i(c,d,m){var b;return t.positionUsing==="translate3d"?b={transform:"translate3d("+n(c)+"%,0,0)"}:t.positionUsing==="translate"?b={transform:"translate("+n(c)+"%,0)"}:b={"margin-left":n(c)+"%"},b.transition="all "+d+"ms "+m,b}var o=function(){var c=[];function d(){var m=c.shift();m&&m(d)}return function(m){c.push(m),c.length==1&&d()}}(),s=function(){var c=["Webkit","O","Moz","ms"],d={};function m(v){return v.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(_,T){return T.toUpperCase()})}function b(v){var _=document.body.style;if(v in _)return v;for(var T=c.length,A=v.charAt(0).toUpperCase()+v.slice(1),w;T--;)if(w=c[T]+A,w in _)return w;return v}function g(v){return v=m(v),d[v]||(d[v]=b(v))}function y(v,_,T){_=g(_),v.style[_]=T}return function(v,_){var T=arguments,A,w;if(T.length==2)for(A in _)w=_[A],w!==void 0&&_.hasOwnProperty(A)&&y(v,A,w);else y(v,T[1],T[2])}}();function a(c,d){var m=typeof c=="string"?c:f(c);return m.indexOf(" "+d+" ")>=0}function l(c,d){var m=f(c),b=m+d;a(m,d)||(c.className=b.substring(1))}function u(c,d){var m=f(c),b;!a(c,d)||(b=m.replace(" "+d+" "," "),c.className=b.substring(1,b.length-1))}function f(c){return(" "+(c.className||"")+" ").replace(/\s+/gi," ")}function p(c){c&&c.parentNode&&c.parentNode.removeChild(c)}return e})});var yt=class{constructor(){this.arrays={}}add(t,r){this.arrays[t]||(this.arrays[t]=[]),this.arrays[t].push(r)}remove(t){this.arrays[t]&&delete this.arrays[t]}get(t){return this.arrays[t]||[]}each(t,r){return this.get(t).forEach(r)}},Fe=class{constructor(){this.arrays=new WeakMap}add(t,r){this.arrays.has(t)||this.arrays.set(t,[]),this.arrays.get(t).push(r)}remove(t){this.arrays.has(t)&&this.arrays.delete(t,[])}get(t){return this.arrays.has(t)?this.arrays.get(t):[]}each(t,r){return this.get(t).forEach(r)}};function xt(e,t,r={},n=!0){e.dispatchEvent(new CustomEvent(t,{detail:r,bubbles:n,composed:!0,cancelable:!0}))}function _t(e,t,r){return e.addEventListener(t,r),()=>e.removeEventListener(t,r)}function St(e){return typeof e=="object"&&e!==null}function oi(e){return St(e)&&!br(e)}function br(e){return Array.isArray(e)}function wr(e){return typeof e=="function"}function si(e){return typeof e!="object"||e===null}function ce(e){return JSON.parse(JSON.stringify(e))}function W(e,t){return t===""?e:t.split(".").reduce((r,n)=>{if(r!==void 0)return r[n]},e)}function we(e,t,r){let n=t.split(".");if(n.length===1)return e[t]=r;let i=n.shift(),o=n.join(".");e[i]===void 0&&(e[i]={}),we(e[i],o,r)}function Ze(e,t,r={},n=""){if(e===t)return r;if(typeof e!=typeof t||oi(e)&&br(t)||br(e)&&oi(t)||si(e)||si(t))return r[n]=t,r;let i=Object.keys(e);return Object.entries(t).forEach(([o,s])=>{r={...r,...Ze(e[o],t[o],r,n===""?o:`${n}.${o}`)},i=i.filter(a=>a!==o)}),i.forEach(o=>{r[`${n}.${o}`]="__rm__"}),r}function ye(e){let t=ai(e)?e[0]:e,r=ai(e)?e[1]:void 0;return St(t)&&Object.entries(t).forEach(([n,i])=>{t[n]=ye(i)}),t}function ai(e){return Array.isArray(e)&&e.length===2&&typeof e[1]=="object"&&Object.keys(e[1]).includes("s")}function Et(){if(document.querySelector('meta[name="csrf-token"]'))return document.querySelector('meta[name="csrf-token"]').getAttribute("content");if(document.querySelector("[data-csrf]"))return document.querySelector("[data-csrf]").getAttribute("data-csrf");if(window.livewireScriptConfig.csrf??!1)return window.livewireScriptConfig.csrf;throw"Livewire: No CSRF token detected"}var Ie;function li(){if(Ie)return Ie;if(window.livewireScriptConfig&&(window.livewireScriptConfig.nonce??!1))return Ie=window.livewireScriptConfig.nonce,Ie;let e=document.querySelector("style[data-livewire-style][nonce]");return e?(Ie=e.nonce,Ie):null}function ui(){return document.querySelector("[data-update-uri]")?.getAttribute("data-update-uri")??window.livewireScriptConfig.uri??null}function At(e){return!!e.match(/