Fix popup toast messages (Remove Flasher) (#16090)

* Remove flasher
Just use a bit of custom code to interface with toastr js
This is able to retain our custom theme and work properly

* Fix style issues

* Missed reference rename

* Remove test code :)

* Fix a missed rename

* Fix one more missed reference

* Fix typo
This commit is contained in:
Tony Murray
2024-06-05 08:07:42 -05:00
committed by GitHub
parent 7879b450ff
commit fa16c025ba
30 changed files with 222 additions and 338 deletions

View File

@@ -54,32 +54,26 @@ class Checks
if ($user->isAdmin()) {
$notifications = Notification::isUnread($user)->where('severity', '>', Severity::Ok->value)->get();
foreach ($notifications as $notification) {
flash()
->using('template.librenms')
->title($notification->title)
->addWarning("<a href='notifications/'>$notification->body</a>");
toast()->warning($notification->title, "<a href='notifications/'>$notification->body</a>");
}
$warn_sec = Config::get('rrd.step', 300) * 3;
if (Device::isUp()->where('last_polled', '<=', Carbon::now()->subSeconds($warn_sec))->exists()) {
$warn_min = $warn_sec / 60;
flash()
->using('template.librenms')
->title('Devices unpolled')
->addWarning('<a href="poller/log?filter=unpolled/">It appears as though you have some devices that haven\'t completed polling within the last ' . $warn_min . ' minutes, you may want to check that out :)</a>');
toast()->warning('Devices unpolled', '<a href="poller/log?filter=unpolled/">It appears as though you have some devices that haven\'t completed polling within the last ' . $warn_min . ' minutes, you may want to check that out :)</a>');
}
// Directory access checks
$rrd_dir = Config::get('rrd_dir');
if (! is_dir($rrd_dir)) {
flash()->addError("RRD Directory is missing ($rrd_dir). Graphing may fail. <a href=" . url('validate') . '>Validate your install</a>');
toast()->error("RRD Directory is missing ($rrd_dir). Graphing may fail. <a href=" . url('validate') . '>Validate your install</a>');
}
$temp_dir = Config::get('temp_dir');
if (! is_dir($temp_dir)) {
flash()->addError("Temp Directory is missing ($temp_dir). Graphing may fail. <a href=" . url('validate') . '>Validate your install</a>');
toast()->error("Temp Directory is missing ($temp_dir). Graphing may fail. <a href=" . url('validate') . '>Validate your install</a>');
} elseif (! is_writable($temp_dir)) {
flash()->addError("Temp Directory is not writable ($temp_dir). Graphing may fail. <a href='" . url('validate') . "'>Validate your install</a>");
toast()->error("Temp Directory is not writable ($temp_dir). Graphing may fail. <a href='" . url('validate') . "'>Validate your install</a>");
}
}
}

View File

@@ -74,7 +74,7 @@ class SocialiteController extends Controller
if (array_key_exists('error', $request->query())) {
$error = $request->query('error');
$error_description = $request->query('error_description');
flash()->addError($error . ': ' . $error_description);
toast()->error($error . ': ' . $error_description);
return redirect()->route('login');
}
@@ -121,7 +121,7 @@ class SocialiteController extends Controller
return redirect()->intended();
} catch (AuthenticationException $e) {
flash()->addError($e->getMessage());
toast()->error($e->getMessage());
}
return redirect()->route('login');

View File

@@ -26,6 +26,7 @@
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Http\Interfaces\ToastInterface;
use App\Models\User;
use App\Models\UserPref;
use Illuminate\Http\Request;
@@ -37,14 +38,14 @@ use Session;
class TwoFactorController extends Controller
{
public function verifyTwoFactor(Request $request)
public function verifyTwoFactor(Request $request, ToastInterface $toast)
{
$this->validate($request, [
'twofactor' => 'required|numeric',
]);
try {
$this->checkToken($request->user(), $request->input('twofactor'));
$this->checkToken($request->user(), $request->input('twofactor'), $toast);
} catch (AuthenticationException $e) {
return redirect()->route('2fa.form')->withErrors($e->getMessage());
}
@@ -54,7 +55,7 @@ class TwoFactorController extends Controller
UserPref::forgetPref(auth()->user(), 'twofactor');
$request->session()->forget(['twofactor', 'twofactorremove']);
flash()->addInfo(__('TwoFactor auth removed.'));
$toast->info(__('TwoFactor auth removed.'));
return redirect('preferences');
}
@@ -153,7 +154,7 @@ class TwoFactorController extends Controller
*
* @throws AuthenticationException
*/
private function checkToken($user, $token)
private function checkToken($user, $token, ToastInterface $toast)
{
if (! $token) {
throw new AuthenticationException(__('No Two-Factor Token entered.'));
@@ -192,7 +193,7 @@ class TwoFactorController extends Controller
// notify if added
if (Session::has('twofactoradd')) {
flash()->addSuccess(__('TwoFactor auth added.'));
$toast->success(__('TwoFactor auth added.'));
Session::forget('twofactoradd');
}

View File

@@ -2,8 +2,8 @@
namespace App\Http\Controllers;
use App\Http\Interfaces\ToastInterface;
use App\Models\DeviceGroup;
use Flasher\Prime\FlasherInterface;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use LibreNMS\Alerting\QueryBuilderFilter;
@@ -49,7 +49,7 @@ class DeviceGroupController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request, FlasherInterface $flasher)
public function store(Request $request, ToastInterface $toast)
{
$this->validate($request, [
'name' => 'required|string|unique:device_groups',
@@ -67,7 +67,7 @@ class DeviceGroupController extends Controller
$deviceGroup->devices()->sync($request->devices);
}
$flasher->addSuccess(__('Device Group :name created', ['name' => htmlentities($deviceGroup->name)]));
$toast->success(__('Device Group :name created', ['name' => htmlentities($deviceGroup->name)]));
return redirect()->route('device-groups.index');
}
@@ -110,7 +110,7 @@ class DeviceGroupController extends Controller
* @param \App\Models\DeviceGroup $deviceGroup
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, DeviceGroup $deviceGroup, FlasherInterface $flasher)
public function update(Request $request, DeviceGroup $deviceGroup, ToastInterface $toast)
{
$this->validate($request, [
'name' => [
@@ -143,9 +143,9 @@ class DeviceGroupController extends Controller
if ($deviceGroup->isDirty() || $devices_updated) {
try {
if ($deviceGroup->save() || $devices_updated) {
$flasher->addSuccess(__('Device Group :name updated', ['name' => htmlentities($deviceGroup->name)]));
$toast->success(__('Device Group :name updated', ['name' => htmlentities($deviceGroup->name)]));
} else {
$flasher->addError(__('Failed to save'));
$toast->error(__('Failed to save'));
return redirect()->back()->withInput();
}
@@ -155,7 +155,7 @@ class DeviceGroupController extends Controller
]);
}
} else {
$flasher->addInfo(__('No changes made'));
$toast->info(__('No changes made'));
}
return redirect()->route('device-groups.index');

View File

@@ -2,8 +2,8 @@
namespace App\Http\Controllers;
use App\Http\Interfaces\ToastInterface;
use App\Models\PortGroup;
use Flasher\Prime\FlasherInterface;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
@@ -39,7 +39,7 @@ class PortGroupController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request, FlasherInterface $flasher)
public function store(Request $request, ToastInterface $toast)
{
$this->validate($request, [
'name' => 'required|string|unique:port_groups',
@@ -48,7 +48,7 @@ class PortGroupController extends Controller
$portGroup = PortGroup::make($request->only(['name', 'desc']));
$portGroup->save();
$flasher->addSuccess(__('Port Group :name created', ['name' => $portGroup->name]));
$toast->success(__('Port Group :name created', ['name' => $portGroup->name]));
return redirect()->route('port-groups.index');
}
@@ -73,7 +73,7 @@ class PortGroupController extends Controller
* @param \App\Models\PortGroup $portGroup
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Request $request, PortGroup $portGroup, FlasherInterface $flasher)
public function update(Request $request, PortGroup $portGroup, ToastInterface $toast)
{
$this->validate($request, [
'name' => [
@@ -90,9 +90,9 @@ class PortGroupController extends Controller
$portGroup->fill($request->only(['name', 'desc']));
if ($portGroup->save()) {
$flasher->addSuccess(__('Port Group :name updated', ['name' => $portGroup->name]));
$toast->success(__('Port Group :name updated', ['name' => $portGroup->name]));
} else {
$flasher->addError(__('Failed to save'));
$toast->error(__('Failed to save'));
return redirect()->back()->withInput();
}

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers;
use App\Http\Interfaces\ToastInterface;
use App\Models\Service;
use Illuminate\Http\Request;
@@ -13,7 +14,7 @@ class ServiceController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\View\View
*/
public function store(Request $request)
public function store(Request $request, ToastInterface $toast)
{
$request = [
'service_name' => 'required|string|unique:service',
@@ -44,7 +45,7 @@ class ServiceController extends Controller
);
$service->save();
flash()->addSuccess(__('Service :name created', ['name' => $service->service_name]));
$toast->success(__('Service :name created', ['name' => $service->service_name]));
return redirect()->route('services.templates.index');
}

View File

@@ -2,11 +2,11 @@
namespace App\Http\Controllers;
use App\Http\Interfaces\ToastInterface;
use App\Models\Device;
use App\Models\DeviceGroup;
use App\Models\Service;
use App\Models\ServiceTemplate;
use Flasher\Prime\FlasherInterface;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use LibreNMS\Alerting\QueryBuilderFilter;
@@ -60,7 +60,7 @@ class ServiceTemplateController extends Controller
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\View\View
*/
public function store(Request $request, FlasherInterface $flasher)
public function store(Request $request, ToastInterface $toast)
{
$this->validate(
$request, [
@@ -105,7 +105,7 @@ class ServiceTemplateController extends Controller
}
$template->groups()->sync($request->groups);
$flasher->addSuccess(__('Service Template :name created', ['name' => $template->name]));
$toast->success(__('Service Template :name created', ['name' => $template->name]));
return redirect()->route('services.templates.index');
}
@@ -146,7 +146,7 @@ class ServiceTemplateController extends Controller
* @param \App\Models\ServiceTemplate $template
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response|\Illuminate\View\View
*/
public function update(Request $request, ServiceTemplate $template, FlasherInterface $flasher)
public function update(Request $request, ServiceTemplate $template, ToastInterface $toast)
{
$this->validate(
$request, [
@@ -214,9 +214,9 @@ class ServiceTemplateController extends Controller
if ($template->isDirty() || $devices_updated || isset($device_groups_updated)) {
try {
if ($template->save() || $devices_updated || isset($device_groups_updated)) {
$flasher->addSuccess(__('Service Template :name updated', ['name' => $template->name]));
$toast->success(__('Service Template :name updated', ['name' => $template->name]));
} else {
$flasher->addError(__('Failed to save'));
$toast->error(__('Failed to save'));
return redirect()->back()->withInput();
}
@@ -226,7 +226,7 @@ class ServiceTemplateController extends Controller
]);
}
} else {
$flasher->addInfo(__('No changes made'));
$toast->info(__('No changes made'));
}
return redirect()->route('services.templates.index');

View File

@@ -25,6 +25,7 @@
namespace App\Http\Controllers;
use App\Http\Interfaces\ToastInterface;
use App\Http\Requests\StoreUserRequest;
use App\Http\Requests\UpdateUserRequest;
use App\Models\AuthLog;
@@ -32,7 +33,6 @@ use App\Models\Dashboard;
use App\Models\User;
use App\Models\UserPref;
use Auth;
use Flasher\Prime\FlasherInterface;
use Illuminate\Support\Str;
use LibreNMS\Authentication\LegacyAuth;
use LibreNMS\Config;
@@ -90,7 +90,7 @@ class UserController extends Controller
* @param StoreUserRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(StoreUserRequest $request, FlasherInterface $flasher)
public function store(StoreUserRequest $request, ToastInterface $toast)
{
$user = $request->only(['username', 'realname', 'email', 'descr', 'can_modify_passwd']);
$user['auth_type'] = LegacyAuth::getType();
@@ -105,12 +105,12 @@ class UserController extends Controller
$this->updateTimezone($user, $request->get('timezone'));
if ($user->save()) {
$flasher->addSuccess(__('User :username created', ['username' => $user->username]));
$toast->success(__('User :username created', ['username' => $user->username]));
return redirect(route('users.index'));
}
$flasher->addError(__('Failed to create user'));
$toast->error(__('Failed to create user'));
return redirect()->back();
}
@@ -169,7 +169,7 @@ class UserController extends Controller
* @param User $user
* @return \Illuminate\Http\RedirectResponse
*/
public function update(UpdateUserRequest $request, User $user, FlasherInterface $flasher)
public function update(UpdateUserRequest $request, User $user, ToastInterface $toast)
{
if ($request->get('new_password') && $user->canSetPassword($request->user())) {
$user->setPassword($request->new_password);
@@ -191,24 +191,24 @@ class UserController extends Controller
}
if ($request->has('dashboard') && $this->updateDashboard($user, $request->get('dashboard'))) {
$flasher->addSuccess(__('Updated dashboard for :username', ['username' => $user->username]));
$toast->success(__('Updated dashboard for :username', ['username' => $user->username]));
}
if ($request->has('timezone') && $this->updateTimezone($user, $request->get('timezone'))) {
if ($request->get('timezone') != 'default') {
$flasher->addSuccess(__('Updated timezone for :username', ['username' => $user->username]));
$toast->success(__('Updated timezone for :username', ['username' => $user->username]));
} else {
$flasher->addSuccess(__('Cleared timezone for :username', ['username' => $user->username]));
$toast->success(__('Cleared timezone for :username', ['username' => $user->username]));
}
}
if ($user->save()) {
$flasher->addSuccess(__('User :username updated', ['username' => $user->username]));
$toast->success(__('User :username updated', ['username' => $user->username]));
return redirect(route(Str::contains(URL::previous(), 'preferences') ? 'preferences.index' : 'users.index'));
}
$flasher->addError(__('Failed to update user :username', ['username' => $user->username]));
$toast->error(__('Failed to update user :username', ['username' => $user->username]));
return redirect()->back();
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* ToastInterface.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2024 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Interfaces;
use Illuminate\Session\SessionManager;
class ToastInterface
{
public function __construct(
private SessionManager $session
) {
}
public function info(string $title, ?string $message = null, ?array $options = null): static
{
return $this->message('info', $title, $message, $options);
}
public function success(string $title, ?string $message = null, ?array $options = null): static
{
return $this->message('success', $title, $message, $options);
}
public function error(string $title, ?string $message = null, ?array $options = null): static
{
return $this->message('error', $title, $message, $options);
}
public function warning(string $title, ?string $message = null, ?array $options = null): static
{
return $this->message('warning', $title, $message, $options);
}
public function message(string $level, string $title, ?string $message = null, ?array $options = null): static
{
$notifications = $this->session->get('toasts', []);
array_push($notifications, [
'level' => $level,
'title' => $message === null ? '' : $title,
'message' => $message ?? $title,
'options' => $options ?? [],
]);
$this->session->flash('toasts', $notifications);
return $this;
}
}

View File

@@ -33,7 +33,7 @@ class AuthEventListener
DB::table('authlog')->insert(['user' => $user->username ?: '', 'address' => Request::ip(), 'result' => 'Logged In']);
flash()->addInfo('Welcome ' . ($user->realname ?: $user->username));
toast()->info('Welcome ' . ($user->realname ?: $user->username));
}
/**

View File

@@ -136,7 +136,7 @@ class LegacyUserProvider implements UserProvider
if (Debug::isEnabled()) {
$auth_message .= '<br /> ' . $ae->getFile() . ': ' . $ae->getLine();
}
flash()->addError($auth_message);
toast()->error($auth_message);
$username = $username ?? Session::get('username', $credentials['username']);
@@ -183,7 +183,7 @@ class LegacyUserProvider implements UserProvider
error_reporting(-1);
} catch (AuthenticationException $ae) {
flash()->addError($ae->getMessage());
toast()->error($ae->getMessage());
}
if (empty($new_user)) {

View File

@@ -0,0 +1,36 @@
<?php
namespace App\View\Components;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;
use Illuminate\Session\SessionManager;
use Illuminate\View\Component;
class Toast extends Component
{
public array $purifier_config = [
'HTML.Allowed' => 'a[href],b,i,ul,ol,li,h1,h2,h3,h4,br,p,pre',
'URI.DisableExternal' => true,
];
public ?array $toasts;
/**
* Create a new component instance.
*/
public function __construct(Request $request, SessionManager $session)
{
$this->purifier_config['URI.Host'] = $request->getHttpHost();
$this->toasts = $session->get('toasts');
$session->forget('toasts'); // to ward againsts double toasts
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.toast');
}
}