diff --git a/.github/workflows/tests-mysql.yml b/.github/workflows/tests-mysql.yml
index 310414cda6..63fcb8e3e2 100644
--- a/.github/workflows/tests-mysql.yml
+++ b/.github/workflows/tests-mysql.yml
@@ -77,3 +77,7 @@ jobs:
DB_PORT: ${{ job.services.mysql.ports[3306] }}
DB_USERNAME: root
run: php artisan test
+
+ - name: Test failure
+ if: ${{ failure() }}
+ run: docker exec "$PROJECT_NAME-php-fpm" cat storage/logs/laravel.log
diff --git a/.github/workflows/tests-postgres.yml b/.github/workflows/tests-postgres.yml
index ae48277be3..3cc5244c5e 100644
--- a/.github/workflows/tests-postgres.yml
+++ b/.github/workflows/tests-postgres.yml
@@ -75,3 +75,7 @@ jobs:
DB_USERNAME: snipeit
DB_PASSWORD: password
run: php artisan test
+
+ - name: Test failure
+ if: ${{ failure() }}
+ run: docker exec "$PROJECT_NAME-php-fpm" cat storage/logs/laravel.log
diff --git a/.github/workflows/tests-sqlite.yml b/.github/workflows/tests-sqlite.yml
index 8bf0115169..011d19d783 100644
--- a/.github/workflows/tests-sqlite.yml
+++ b/.github/workflows/tests-sqlite.yml
@@ -59,3 +59,7 @@ jobs:
env:
DB_CONNECTION: sqlite_testing
run: php artisan test
+
+ - name: Test failure
+ if: ${{ failure() }}
+ run: docker exec "$PROJECT_NAME-php-fpm" cat storage/logs/laravel.log
diff --git a/app/Http/Controllers/Account/AcceptanceController.php b/app/Http/Controllers/Account/AcceptanceController.php
index e29fa7c63b..278d7e2081 100644
--- a/app/Http/Controllers/Account/AcceptanceController.php
+++ b/app/Http/Controllers/Account/AcceptanceController.php
@@ -338,4 +338,5 @@ class AcceptanceController extends Controller
return redirect()->to('account/accept')->with('success', $return_msg);
}
+
}
diff --git a/app/Http/Controllers/Api/ReportsController.php b/app/Http/Controllers/Api/ReportsController.php
index 566911dd27..63fca39d19 100644
--- a/app/Http/Controllers/Api/ReportsController.php
+++ b/app/Http/Controllers/Api/ReportsController.php
@@ -44,21 +44,6 @@ class ReportsController extends Controller
});
}
- if ($request->filled('action_type')) {
- $actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
- }
-
- if ($request->filled('created_by')) {
- $actionlogs = $actionlogs->where('created_by', '=', $request->input('created_by'));
- }
-
- if ($request->filled('action_source')) {
- $actionlogs = $actionlogs->where('action_source', '=', $request->input('action_source'))->orderBy('created_at', 'desc');
- }
-
- if ($request->filled('remote_ip')) {
- $actionlogs = $actionlogs->where('remote_ip', '=', $request->input('remote_ip'))->orderBy('created_at', 'desc');
- }
if ($request->filled('uploads')) {
$actionlogs = $actionlogs->whereNotNull('filename')->orderBy('created_at', 'desc');
@@ -74,6 +59,8 @@ class ReportsController extends Controller
'note',
'remote_ip',
'user_agent',
+ 'target_type',
+ 'item_type',
'action_source',
'action_date',
];
diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php
index 50a758ac37..52eb751a89 100755
--- a/app/Http/Controllers/Assets/AssetsController.php
+++ b/app/Http/Controllers/Assets/AssetsController.php
@@ -111,8 +111,10 @@ class AssetsController extends Controller
$settings = Setting::getSettings();
- $success = false;
+ $successes = [];
+ $failures = [];
$serials = $request->input('serials');
+ $asset = null;
for ($a = 1; $a <= count($asset_tags); $a++) {
$asset = new Asset();
@@ -199,20 +201,35 @@ class AssetsController extends Controller
$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;
-
+ $successes[] = " $asset->id]) . "' style='color: white;'>" . e($asset->asset_tag) . "";
+
+ } else {
+ $failures[] = join(",", $asset->getErrors()->all());
}
}
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
- if ($success) {
+ if ($successes) {
+ if ($failures) {
+ //some succeeded, some failed
+ 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 (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, $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, $asset->id, 'Assets'))
+ ->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]));
+ }
+ }
- 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/app/Listeners/CheckoutableListener.php b/app/Listeners/CheckoutableListener.php
index ba19d68f20..7d8b5c1c9d 100644
--- a/app/Listeners/CheckoutableListener.php
+++ b/app/Listeners/CheckoutableListener.php
@@ -3,13 +3,19 @@
namespace App\Listeners;
use App\Events\CheckoutableCheckedOut;
+use App\Mail\CheckinAccessoryMail;
+use App\Mail\CheckinLicenseMail;
+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;
use App\Models\CheckoutAcceptance;
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;
@@ -20,10 +26,10 @@ use App\Notifications\CheckoutAssetNotification;
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;
-use Osama\LaravelTeamsNotification\TeamsNotification;
class CheckoutableListener
{
@@ -44,41 +50,42 @@ class CheckoutableListener
/**
* Make a checkout acceptance and attach it in the notification
*/
+ $settings = Setting::getSettings();
$acceptance = $this->getCheckoutAcceptance($event);
- $notifiables = $this->getNotifiables($event);
+ $adminCcEmailsArray = [];
+ if($settings->admin_cc_email !== '') {
+ $adminCcEmail = $settings->admin_cc_email;
+ $adminCcEmailsArray = array_map('trim', explode(',', $adminCcEmail));
+ }
+ $ccEmails = array_filter($adminCcEmailsArray);
+ $notifiable = $event->checkedOutTo;
+ $mailable = $this->getCheckoutMailType($event, $acceptance);
// 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));
-// }
-// }
-// }
-
- // 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));
+ if (!$event->checkedOutTo->locale){
+ $mailable->locale($event->checkedOutTo->locale);
}
- // Handling Microsoft Teams notification
- else if (Setting::getSettings()->webhook_selected === 'microsoft') {
- $message = $this->getCheckoutNotification($event)->toMicrosoftTeams();
- $notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
- $notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
- }
- else {
+ /**
+ * 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)->cc($ccEmails)->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)
->notify($this->getCheckoutNotification($event, $acceptance));
}
- }
} catch (ClientException $e) {
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
} catch (Exception $e) {
@@ -112,39 +119,41 @@ class CheckoutableListener
}
}
}
+ $settings = Setting::getSettings();
+ $adminCcEmailsArray = [];
+
+ if($settings->admin_cc_email !== '') {
+ $adminCcEmail = $settings->admin_cc_email;
+ $adminCcEmailsArray = array_map('trim', explode(',', $adminCcEmail));
+ }
+ $ccEmails = array_filter($adminCcEmailsArray);
+ $notifiable = $event->checkedOutTo;
+ $mailable = $this->getCheckinMailType($event);
- $notifiables = $this->getNotifiables($event);
// 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);
+ }
+ /**
+ * 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)->cc($ccEmails)->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
- if (Setting::getSettings()->webhook_selected === 'slack' || Setting::getSettings()->webhook_selected === 'general') {
- Notification::route('slack', Setting::getSettings()->webhook_endpoint)
- ->notify($this->getCheckinNotification($event));
- } // Handling Microsoft Teams notification
- else if (Setting::getSettings()->webhook_selected === 'microsoft') {
-
- $message = $this->getCheckinNotification($event)->toMicrosoftTeams();
- $notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
- $notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
- }
- 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) {
@@ -175,33 +184,6 @@ class CheckoutableListener
return $acceptance;
}
- /**
- * Gets the entities to be notified of the passed event
- *
- * @param Event $event
- * @return Collection
- */
- private function getNotifiables($event)
- {
- $notifiables = 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);
- }
-
- /**
- * Notify Admin users if the settings is activated
- */
- if ((Setting::getSettings()) && (Setting::getSettings()->admin_cc_email != '')) {
- $notifiables->push(new AdminRecipient());
- }
-
- return $notifiables;
- }
-
/**
* Get the appropriate notification for the event
*
@@ -250,7 +232,7 @@ class CheckoutableListener
break;
case Consumable::class:
$notificationClass = CheckoutConsumableNotification::class;
- break;
+ break;
case LicenseSeat::class:
$notificationClass = CheckoutLicenseSeatNotification::class;
break;
@@ -259,6 +241,30 @@ class CheckoutableListener
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,
+ LicenseSeat::class => CheckoutLicenseMail::class,
+ Consumable::class => CheckoutConsumableMail::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,
+ LicenseSeat::class => CheckinLicenseMail::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/CheckinAccessoryMail.php b/app/Mail/CheckinAccessoryMail.php
new file mode 100644
index 0000000000..fc8d1455f9
--- /dev/null
+++ b/app/Mail/CheckinAccessoryMail.php
@@ -0,0 +1,70 @@
+item = $accessory;
+ $this->target = $checkedOutTo;
+ $this->admin = $checkedInby;
+ $this->note = $note;
+ $this->settings = Setting::getSettings();
+ }
+
+ /**
+ * Get the message envelope.
+ */
+ public function envelope(): Envelope
+ {
+ $from = new Address(env('MAIL_FROM_ADDR','service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ 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 [];
+ }
+}
diff --git a/app/Mail/CheckinAssetMail.php b/app/Mail/CheckinAssetMail.php
new file mode 100644
index 0000000000..5dd8394a5a
--- /dev/null
+++ b/app/Mail/CheckinAssetMail.php
@@ -0,0 +1,93 @@
+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 = new Address(env('MAIL_FROM_ADDR','service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ 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/CheckinLicenseMail.php b/app/Mail/CheckinLicenseMail.php
new file mode 100644
index 0000000000..97ce4dd3c3
--- /dev/null
+++ b/app/Mail/CheckinLicenseMail.php
@@ -0,0 +1,70 @@
+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 = new Address(env('MAIL_FROM_ADDR','service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ 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/Mail/CheckoutAccessoryMail.php b/app/Mail/CheckoutAccessoryMail.php
new file mode 100644
index 0000000000..f297c02754
--- /dev/null
+++ b/app/Mail/CheckoutAccessoryMail.php
@@ -0,0 +1,82 @@
+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 = new Address(env('MAIL_FROM_ADDR','service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ 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);
+
+ 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/Mail/CheckoutAssetMail.php b/app/Mail/CheckoutAssetMail.php
new file mode 100644
index 0000000000..fa1290e92d
--- /dev/null
+++ b/app/Mail/CheckoutAssetMail.php
@@ -0,0 +1,110 @@
+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 = new Address(env('MAIL_FROM_ADDR', 'service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ 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,
+ ],
+ );
+ }
+
+ /**
+ * Get the attachments for the message.
+ *
+ * @return array
+ */
+ public function attachments(): array
+ {
+ return [];
+ }
+}
diff --git a/app/Mail/CheckoutConsumableMail.php b/app/Mail/CheckoutConsumableMail.php
new file mode 100644
index 0000000000..18fe228258
--- /dev/null
+++ b/app/Mail/CheckoutConsumableMail.php
@@ -0,0 +1,84 @@
+item = $consumable;
+ $this->admin = $checkedOutBy;
+ $this->note = $note;
+ $this->target = $checkedOutTo;
+ $this->acceptance = $acceptance;
+ $this->qty = $consumable->checkout_qty;
+
+ $this->settings = Setting::getSettings();
+ }
+
+ /**
+ * Get the message envelope.
+ */
+ public function envelope(): Envelope
+ {
+ $from = new Address(env('MAIL_FROM_ADDR','service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ subject: trans('mail.Confirm_consumable_delivery'),
+ );
+ }
+
+ /**
+ * Get the message content definition.
+ */
+ public function content(): Content
+ {
+
+ $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,
+ 'qty' => $this->qty,
+ ]
+ );
+ }
+
+ /**
+ * Get the attachments for the message.
+ *
+ * @return array
+ */
+ public function attachments(): array
+ {
+ return [];
+ }
+}
diff --git a/app/Mail/CheckoutLicenseMail.php b/app/Mail/CheckoutLicenseMail.php
new file mode 100644
index 0000000000..ecd0d7390d
--- /dev/null
+++ b/app/Mail/CheckoutLicenseMail.php
@@ -0,0 +1,80 @@
+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 = new Address(env('MAIL_FROM_ADDR','service@snipe-it.io'));
+
+ return new Envelope(
+ from: $from,
+ 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/Models/Actionlog.php b/app/Models/Actionlog.php
index 0831352b87..008c5b1146 100755
--- a/app/Models/Actionlog.php
+++ b/app/Models/Actionlog.php
@@ -55,6 +55,8 @@ class Actionlog extends SnipeModel
'created_by',
'remote_ip',
'user_agent',
+ 'item_type',
+ 'target_type',
'action_source'
];
@@ -64,10 +66,10 @@ class Actionlog extends SnipeModel
* @var array
*/
protected $searchableRelations = [
- 'company' => ['name'],
- 'adminuser' => ['first_name','last_name','username', 'email'],
- 'user' => ['first_name','last_name','username', 'email'],
- 'assets' => ['asset_tag','name'],
+ 'company' => ['name'],
+ 'adminuser' => ['first_name','last_name','username', 'email'],
+ 'user' => ['first_name','last_name','username', 'email'],
+ 'assets' => ['asset_tag','name'],
];
/**
diff --git a/app/Models/Recipients/AdminRecipient.php b/app/Models/Recipients/AdminRecipient.php
index 433bd00209..90e39d4ee5 100644
--- a/app/Models/Recipients/AdminRecipient.php
+++ b/app/Models/Recipients/AdminRecipient.php
@@ -6,9 +6,15 @@ use App\Models\Setting;
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;
+ }
}
diff --git a/app/Notifications/CheckinAccessoryNotification.php b/app/Notifications/CheckinAccessoryNotification.php
index 92c3574eb7..28e6c054f7 100644
--- a/app/Notifications/CheckinAccessoryNotification.php
+++ b/app/Notifications/CheckinAccessoryNotification.php
@@ -6,6 +6,7 @@ use App\Models\Accessory;
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;
@@ -56,22 +57,9 @@ class CheckinAccessoryNotification extends Notification
}
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 != '') {
- 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;
}
@@ -154,24 +142,4 @@ class CheckinAccessoryNotification extends 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/CheckinAssetNotification.php b/app/Notifications/CheckinAssetNotification.php
index 1cde77c7e3..75077aeb46 100644
--- a/app/Notifications/CheckinAssetNotification.php
+++ b/app/Notifications/CheckinAssetNotification.php
@@ -51,7 +51,6 @@ class CheckinAssetNotification extends Notification
*/
public function via()
{
- $notifyBy = [];
if (Setting::getSettings()->webhook_selected == 'google' && Setting::getSettings()->webhook_endpoint) {
$notifyBy[] = GoogleChatChannel::class;
@@ -66,14 +65,6 @@ class CheckinAssetNotification extends Notification
$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;
}
@@ -157,35 +148,5 @@ class CheckinAssetNotification extends Notification
)
)
);
-
- }
-
- /**
- * 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/app/Notifications/CheckinLicenseSeatNotification.php b/app/Notifications/CheckinLicenseSeatNotification.php
index 825777fb3d..1cb8706e67 100644
--- a/app/Notifications/CheckinLicenseSeatNotification.php
+++ b/app/Notifications/CheckinLicenseSeatNotification.php
@@ -6,6 +6,7 @@ use App\Models\LicenseSeat;
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;
@@ -59,15 +60,7 @@ class CheckinLicenseSeatNotification extends Notification
}
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
- $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';
+ $notifyBy[] = SlackWebhookChannel::class;
}
return $notifyBy;
@@ -162,23 +155,4 @@ class CheckinLicenseSeatNotification extends Notification
);
}
-
-
- /**
- * 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/app/Notifications/CheckoutAssetNotification.php b/app/Notifications/CheckoutAssetNotification.php
index 771251ab45..83011e5c8e 100644
--- a/app/Notifications/CheckoutAssetNotification.php
+++ b/app/Notifications/CheckoutAssetNotification.php
@@ -8,7 +8,7 @@ use App\Models\Setting;
use App\Models\User;
use Exception;
use Illuminate\Bus\Queueable;
-use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Notifications\Channels\SlackWebhookChannel;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Str;
@@ -36,14 +36,11 @@ 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->acceptance = $acceptance;
-
- $this->settings = Setting::getSettings();
-
$this->last_checkout = '';
$this->expected_checkin = '';
@@ -57,7 +54,6 @@ class CheckoutAssetNotification extends Notification
false);
}
}
-
/**
* Get the notification's delivery channels.
*
@@ -66,61 +62,34 @@ class CheckoutAssetNotification extends Notification
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[] = TeamsNotification::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 = [
@@ -128,7 +97,7 @@ class CheckoutAssetNotification extends Notification
'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;
}
@@ -197,42 +166,4 @@ public function toGoogleChat()
);
}
-
- /**
- * Get the mail representation of the notification.
- *
- * @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/app/Notifications/CheckoutConsumableNotification.php b/app/Notifications/CheckoutConsumableNotification.php
index 7113ba5131..ba7c5646ab 100644
--- a/app/Notifications/CheckoutConsumableNotification.php
+++ b/app/Notifications/CheckoutConsumableNotification.php
@@ -6,6 +6,7 @@ use App\Models\Consumable;
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;
@@ -63,35 +64,7 @@ class CheckoutConsumableNotification extends Notification
}
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 ((method_exists($this->item, 'checkin_email')) && ($this->item->checkin_email())) {
- $notifyBy[1] = 'mail';
- }
+ $notifyBy[] = SlackWebhookChannel::class;
}
return $notifyBy;
@@ -180,30 +153,4 @@ class CheckoutConsumableNotification extends Notification
);
}
-
- /**
- * Get the mail representation of the notification.
- *
- * @return \Illuminate\Notifications\Messages\MailMessage
- */
- public function toMail()
- {
- $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,
- 'qty' => $this->qty,
- ])
- ->subject(trans('mail.Confirm_consumable_delivery'));
- }
}
diff --git a/app/Notifications/CheckoutLicenseSeatNotification.php b/app/Notifications/CheckoutLicenseSeatNotification.php
index f59c4416e9..1aed0d2004 100644
--- a/app/Notifications/CheckoutLicenseSeatNotification.php
+++ b/app/Notifications/CheckoutLicenseSeatNotification.php
@@ -6,6 +6,7 @@ use App\Models\LicenseSeat;
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,35 +62,7 @@ class CheckoutLicenseSeatNotification extends Notification
}
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;
@@ -177,29 +150,4 @@ class CheckoutLicenseSeatNotification extends Notification
);
}
-
- /**
- * 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'));
- }
}
diff --git a/app/Presenters/ActionlogPresenter.php b/app/Presenters/ActionlogPresenter.php
index 37a1adbc28..9251ce6347 100644
--- a/app/Presenters/ActionlogPresenter.php
+++ b/app/Presenters/ActionlogPresenter.php
@@ -42,27 +42,27 @@ class ActionlogPresenter extends Presenter
// User related icons
if ($this->itemType() == 'user') {
- if ($this->actionType()=='2fa reset') {
+ if ($this->action_type == '2fa reset') {
return 'fa-solid fa-mobile-screen';
}
- if ($this->actionType()=='create new') {
+ if ($this->action_type == 'create new') {
return 'fa-solid fa-user-plus';
}
- if ($this->actionType()=='merged') {
+ if ($this->action_type == 'merged') {
return 'fa-solid fa-people-arrows';
}
- if ($this->actionType()=='delete') {
+ if ($this->action_type == 'delete') {
return 'fa-solid fa-user-minus';
}
- if ($this->actionType()=='delete') {
+ if ($this->action_type == 'delete') {
return 'fa-solid fa-user-minus';
}
- if ($this->actionType()=='update') {
+ if ($this->action_type == 'update') {
return 'fa-solid fa-user-pen';
}
@@ -70,31 +70,31 @@ class ActionlogPresenter extends Presenter
}
// Everything else
- if ($this->actionType()=='create new') {
+ if ($this->action_type == 'create new') {
return 'fa-solid fa-plus';
}
- if ($this->actionType()=='delete') {
+ if ($this->action_type == 'delete') {
return 'fa-solid fa-trash';
}
- if ($this->actionType()=='update') {
+ if ($this->action_type == 'update') {
return 'fa-solid fa-pen';
}
- if ($this->actionType()=='restore') {
+ if ($this->action_type == 'restore') {
return 'fa-solid fa-trash-arrow-up';
}
- if ($this->actionType()=='upload') {
+ if ($this->action_type == 'upload') {
return 'fas fa-paperclip';
}
- if ($this->actionType()=='checkout') {
+ if ($this->action_type == 'checkout') {
return 'fa-solid fa-rotate-left';
}
- if ($this->actionType()=='checkin from') {
+ if ($this->action_type == 'checkin from') {
return 'fa-solid fa-rotate-right';
}
diff --git a/composer.lock b/composer.lock
index b04d7a9569..cdc86c22b4 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",
diff --git a/database/factories/ComponentFactory.php b/database/factories/ComponentFactory.php
index fcec2dac87..786e780895 100644
--- a/database/factories/ComponentFactory.php
+++ b/database/factories/ComponentFactory.php
@@ -31,6 +31,7 @@ class ComponentFactory extends Factory
*/
public function definition()
{
+
return [
'name' => $this->faker->text(20),
'category_id' => Category::factory(),
@@ -42,7 +43,6 @@ class ComponentFactory extends Factory
'purchase_cost' => $this->faker->randomFloat(2),
'min_amt' => $this->faker->numberBetween($min = 1, $max = 2),
'company_id' => Company::factory(),
- 'manufacturer_id' => Manufacturer::factory(),
'supplier_id' => Supplier::factory(),
'model_number' => $this->faker->numberBetween(1000000, 50000000),
];
@@ -50,7 +50,8 @@ class ComponentFactory extends Factory
public function ramCrucial4()
{
- return $this->state(function () {
+ $manufacturer = Manufacturer::where('name', 'Crucial')->first() ?? Manufacturer::factory()->create(['name' => 'Crucial']);
+ return $this->state(function () use ($manufacturer) {
return [
'name' => 'Crucial 4GB DDR3L-1600 SODIMM',
'category_id' => function () {
@@ -58,6 +59,7 @@ class ComponentFactory extends Factory
},
'qty' => 10,
'min_amt' => 2,
+ 'manufacturer_id' => $manufacturer->id,
'location_id' => Location::factory(),
];
});
@@ -65,7 +67,8 @@ class ComponentFactory extends Factory
public function ramCrucial8()
{
- return $this->state(function () {
+ $manufacturer = Manufacturer::where('name', 'Crucial')->first() ?? Manufacturer::factory()->create(['name' => 'Crucial']);
+ return $this->state(function () use ($manufacturer) {
return [
'name' => 'Crucial 8GB DDR3L-1600 SODIMM Memory for Mac',
'category_id' => function () {
@@ -73,13 +76,15 @@ class ComponentFactory extends Factory
},
'qty' => 10,
'min_amt' => 2,
+ 'manufacturer_id' => $manufacturer->id,
];
});
}
public function ssdCrucial120()
{
- return $this->state(function () {
+ $manufacturer = Manufacturer::where('name', 'Crucial')->first() ?? Manufacturer::factory()->create(['name' => 'Crucial']);
+ return $this->state(function () use ($manufacturer) {
return [
'name' => 'Crucial BX300 120GB SATA Internal SSD',
'category_id' => function () {
@@ -87,13 +92,15 @@ class ComponentFactory extends Factory
},
'qty' => 10,
'min_amt' => 2,
+ 'manufacturer_id' => $manufacturer->id,
];
});
}
public function ssdCrucial240()
{
- return $this->state(function () {
+ $manufacturer = Manufacturer::where('name', 'Crucial')->first() ?? Manufacturer::factory()->create(['name' => 'Crucial']);
+ return $this->state(function () use ($manufacturer) {
return [
'name' => 'Crucial BX300 240GB SATA Internal SSD',
'category_id' => function () {
@@ -101,6 +108,7 @@ class ComponentFactory extends Factory
},
'qty' => 10,
'min_amt' => 2,
+ 'manufacturer_id' => $manufacturer->id,
];
});
}
diff --git a/public/vendor/livewire/livewire.esm.js b/public/vendor/livewire/livewire.esm.js
index ae4bb2cb78..2d7ef4791c 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 687180f6b1..670591055f 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 90a91971d8..32197b3ebf 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(/