Revised webhooks list to new format
Also aligned query naming to start with model in use. Also added created/updated sort options to roles.
This commit is contained in:
		
							parent
							
								
									98b59a1024
								
							
						
					
					
						commit
						f75091a1c5
					
				| 
						 | 
					@ -0,0 +1,34 @@
 | 
				
			||||||
 | 
					<?php
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace BookStack\Actions\Queries;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use BookStack\Actions\Webhook;
 | 
				
			||||||
 | 
					use Illuminate\Pagination\LengthAwarePaginator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Get all the webhooks in the system in a paginated format.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					class WebhooksAllPaginatedAndSorted
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @param array{sort: string, order: string, search: string} $sortData
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public function run(int $count, array $sortData): LengthAwarePaginator
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        $sort = $sortData['sort'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $query = Webhook::query()->select(['*'])
 | 
				
			||||||
 | 
					            ->withCount(['trackedEvents'])
 | 
				
			||||||
 | 
					            ->orderBy($sort, $sortData['order']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ($sortData['search']) {
 | 
				
			||||||
 | 
					            $term = '%' . $sortData['search'] . '%';
 | 
				
			||||||
 | 
					            $query->where(function ($query) use ($term) {
 | 
				
			||||||
 | 
					                $query->where('name', 'like', $term)
 | 
				
			||||||
 | 
					                    ->orWhere('endpoint', 'like', $term);
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return $query->paginate($count);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Get all the roles in the system in a paginated format.
 | 
					 * Get all the roles in the system in a paginated format.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class AllRolesPaginatedAndSorted
 | 
					class RolesAllPaginatedAndSorted
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param array{sort: string, order: string, search: string} $sortData
 | 
					     * @param array{sort: string, order: string, search: string} $sortData
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
 | 
				
			||||||
 * user is assumed to be trusted. (Admin users).
 | 
					 * user is assumed to be trusted. (Admin users).
 | 
				
			||||||
 * Email search can be abused to extract email addresses.
 | 
					 * Email search can be abused to extract email addresses.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
class AllUsersPaginatedAndSorted
 | 
					class UsersAllPaginatedAndSorted
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @param array{sort: string, order: string, search: string} $sortData
 | 
					     * @param array{sort: string, order: string, search: string} $sortData
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
namespace BookStack\Http\Controllers;
 | 
					namespace BookStack\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use BookStack\Auth\Permissions\PermissionsRepo;
 | 
					use BookStack\Auth\Permissions\PermissionsRepo;
 | 
				
			||||||
use BookStack\Auth\Queries\AllRolesPaginatedAndSorted;
 | 
					use BookStack\Auth\Queries\RolesAllPaginatedAndSorted;
 | 
				
			||||||
use BookStack\Auth\Role;
 | 
					use BookStack\Auth\Role;
 | 
				
			||||||
use BookStack\Exceptions\PermissionsException;
 | 
					use BookStack\Exceptions\PermissionsException;
 | 
				
			||||||
use Exception;
 | 
					use Exception;
 | 
				
			||||||
| 
						 | 
					@ -32,7 +32,7 @@ class RoleController extends Controller
 | 
				
			||||||
            'order'  => setting()->getForCurrentUser('roles_sort_order', 'asc'),
 | 
					            'order'  => setting()->getForCurrentUser('roles_sort_order', 'asc'),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $roles = (new AllRolesPaginatedAndSorted())->run(20, $listDetails);
 | 
					        $roles = (new RolesAllPaginatedAndSorted())->run(20, $listDetails);
 | 
				
			||||||
        $roles->appends(['search' => $listDetails['search']]);
 | 
					        $roles->appends(['search' => $listDetails['search']]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->setPageTitle(trans('settings.roles'));
 | 
					        $this->setPageTitle(trans('settings.roles'));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@
 | 
				
			||||||
namespace BookStack\Http\Controllers;
 | 
					namespace BookStack\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use BookStack\Auth\Access\SocialAuthService;
 | 
					use BookStack\Auth\Access\SocialAuthService;
 | 
				
			||||||
use BookStack\Auth\Queries\AllUsersPaginatedAndSorted;
 | 
					use BookStack\Auth\Queries\UsersAllPaginatedAndSorted;
 | 
				
			||||||
use BookStack\Auth\Role;
 | 
					use BookStack\Auth\Role;
 | 
				
			||||||
use BookStack\Auth\User;
 | 
					use BookStack\Auth\User;
 | 
				
			||||||
use BookStack\Auth\UserRepo;
 | 
					use BookStack\Auth\UserRepo;
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,7 @@ class UserController extends Controller
 | 
				
			||||||
            'order'  => setting()->getForCurrentUser('users_sort_order', 'asc'),
 | 
					            'order'  => setting()->getForCurrentUser('users_sort_order', 'asc'),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $users = (new AllUsersPaginatedAndSorted())->run(20, $listDetails);
 | 
					        $users = (new UsersAllPaginatedAndSorted())->run(20, $listDetails);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->setPageTitle(trans('settings.users'));
 | 
					        $this->setPageTitle(trans('settings.users'));
 | 
				
			||||||
        $users->appends(['search' => $listDetails['search']]);
 | 
					        $users->appends(['search' => $listDetails['search']]);
 | 
				
			||||||
| 
						 | 
					@ -251,7 +251,7 @@ class UserController extends Controller
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function changeSort(Request $request, string $id, string $type)
 | 
					    public function changeSort(Request $request, string $id, string $type)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $validSortTypes = ['books', 'bookshelves', 'shelf_books', 'users', 'roles'];
 | 
					        $validSortTypes = ['books', 'bookshelves', 'shelf_books', 'users', 'roles', 'webhooks'];
 | 
				
			||||||
        if (!in_array($type, $validSortTypes)) {
 | 
					        if (!in_array($type, $validSortTypes)) {
 | 
				
			||||||
            return redirect()->back(500);
 | 
					            return redirect()->back(500);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -322,7 +322,7 @@ class UserController extends Controller
 | 
				
			||||||
        //   Probably better to do a simple validation here then validate at usage.
 | 
					        //   Probably better to do a simple validation here then validate at usage.
 | 
				
			||||||
        $validSorts = [
 | 
					        $validSorts = [
 | 
				
			||||||
            'name', 'created_at', 'updated_at', 'default', 'email', 'last_activity_at', 'display_name',
 | 
					            'name', 'created_at', 'updated_at', 'default', 'email', 'last_activity_at', 'display_name',
 | 
				
			||||||
            'users_count', 'permissions_count',
 | 
					            'users_count', 'permissions_count', 'endpoint', 'active',
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
        if (!in_array($sort, $validSorts)) {
 | 
					        if (!in_array($sort, $validSorts)) {
 | 
				
			||||||
            $sort = 'name';
 | 
					            $sort = 'name';
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@
 | 
				
			||||||
namespace BookStack\Http\Controllers;
 | 
					namespace BookStack\Http\Controllers;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use BookStack\Actions\ActivityType;
 | 
					use BookStack\Actions\ActivityType;
 | 
				
			||||||
 | 
					use BookStack\Actions\Queries\WebhooksAllPaginatedAndSorted;
 | 
				
			||||||
use BookStack\Actions\Webhook;
 | 
					use BookStack\Actions\Webhook;
 | 
				
			||||||
use Illuminate\Http\Request;
 | 
					use Illuminate\Http\Request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,16 +19,23 @@ class WebhookController extends Controller
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Show all webhooks configured in the system.
 | 
					     * Show all webhooks configured in the system.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public function index()
 | 
					    public function index(Request $request)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        $webhooks = Webhook::query()
 | 
					        $listDetails = [
 | 
				
			||||||
            ->orderBy('name', 'desc')
 | 
					            'search' => $request->get('search', ''),
 | 
				
			||||||
            ->with('trackedEvents')
 | 
					            'sort'   => setting()->getForCurrentUser('webhooks_sort', 'name'),
 | 
				
			||||||
            ->get();
 | 
					            'order'  => setting()->getForCurrentUser('webhooks_sort_order', 'asc'),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        $webhooks = (new WebhooksAllPaginatedAndSorted())->run(20, $listDetails);
 | 
				
			||||||
 | 
					        $webhooks->appends(['search' => $listDetails['search']]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        $this->setPageTitle(trans('settings.webhooks'));
 | 
					        $this->setPageTitle(trans('settings.webhooks'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return view('settings.webhooks.index', ['webhooks' => $webhooks]);
 | 
					        return view('settings.webhooks.index', [
 | 
				
			||||||
 | 
					            'webhooks'    => $webhooks,
 | 
				
			||||||
 | 
					            'listDetails' => $listDetails,
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -247,6 +247,8 @@ return [
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Webhooks
 | 
					    // Webhooks
 | 
				
			||||||
    'webhooks' => 'Webhooks',
 | 
					    'webhooks' => 'Webhooks',
 | 
				
			||||||
 | 
					    'webhooks_index_desc' => 'Webhooks are a way to send data to external URLs when certain actions and events occur within the system which allows event-based integration with external platforms such as messaging or notification systems.',
 | 
				
			||||||
 | 
					    'webhooks_x_trigger_events' => '1 trigger event|:count trigger events',
 | 
				
			||||||
    'webhooks_create' => 'Create New Webhook',
 | 
					    'webhooks_create' => 'Create New Webhook',
 | 
				
			||||||
    'webhooks_none_created' => 'No webhooks have yet been created.',
 | 
					    'webhooks_none_created' => 'No webhooks have yet been created.',
 | 
				
			||||||
    'webhooks_edit' => 'Edit Webhook',
 | 
					    'webhooks_edit' => 'Edit Webhook',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -969,4 +969,17 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.item-list-row:hover .item-list-row-toggle-all {
 | 
					.item-list-row:hover .item-list-row-toggle-all {
 | 
				
			||||||
  visibility: visible;
 | 
					  visibility: visible;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.status-indicator-active, .status-indicator-inactive {
 | 
				
			||||||
 | 
					  width: 8px;
 | 
				
			||||||
 | 
					  height: 8px;
 | 
				
			||||||
 | 
					  border-radius: 50%;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.status-indicator-active {
 | 
				
			||||||
 | 
					  background-color: $positive;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.status-indicator-inactive {
 | 
				
			||||||
 | 
					  background-color: $negative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					<span title="{{ trans('common.status_' . ($status ? 'active' : 'inactive')) }}"
 | 
				
			||||||
 | 
					      class="status-indicator-{{ $status ? 'active' : 'inactive' }}"
 | 
				
			||||||
 | 
					></span>
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,8 @@
 | 
				
			||||||
                        'display_name' => trans('common.sort_name'),
 | 
					                        'display_name' => trans('common.sort_name'),
 | 
				
			||||||
                        'users_count' => trans('settings.roles_assigned_users'),
 | 
					                        'users_count' => trans('settings.roles_assigned_users'),
 | 
				
			||||||
                        'permissions_count' => trans('settings.roles_permissions_provided'),
 | 
					                        'permissions_count' => trans('settings.roles_permissions_provided'),
 | 
				
			||||||
 | 
					                        'created_at' => trans('common.sort_created_at'),
 | 
				
			||||||
 | 
					                        'updated_at' => trans('common.sort_updated_at'),
 | 
				
			||||||
                    ], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'roles'])
 | 
					                    ], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'roles'])
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,48 +8,51 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="card content-wrap auto-height">
 | 
					        <div class="card content-wrap auto-height">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <div class="grid half v-center">
 | 
					            <div class="flex-container-row items-center justify-space-between wrap">
 | 
				
			||||||
                <h1 class="list-heading">{{ trans('settings.webhooks') }}</h1>
 | 
					                <h1 class="list-heading">{{ trans('settings.webhooks') }}</h1>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <div class="text-right">
 | 
					                <div>
 | 
				
			||||||
                    <a href="{{ url("/settings/webhooks/create") }}"
 | 
					                    <a href="{{ url("/settings/webhooks/create") }}"
 | 
				
			||||||
                       class="button outline">{{ trans('settings.webhooks_create') }}</a>
 | 
					                       class="button outline">{{ trans('settings.webhooks_create') }}</a>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            @if(count($webhooks) > 0)
 | 
					            <p class="text-muted">{{ trans('settings.webhooks_index_desc') }}</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <table class="table">
 | 
					            <div class="flex-container-row items-center justify-space-between gap-m mt-m mb-l wrap">
 | 
				
			||||||
                    <tr>
 | 
					                <div>
 | 
				
			||||||
                        <th>{{ trans('common.name') }}</th>
 | 
					                    <div class="block inline mr-xs">
 | 
				
			||||||
                        <th width="100">{{ trans('settings.webhook_events_table_header') }}</th>
 | 
					                        <form method="get" action="{{ url("/settings/webhooks") }}">
 | 
				
			||||||
                        <th width="100">{{ trans('common.status') }}</th>
 | 
					                            <input type="text" name="search" placeholder="{{ trans('common.search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
 | 
				
			||||||
                    </tr>
 | 
					                        </form>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					                <div class="justify-flex-end">
 | 
				
			||||||
 | 
					                    @include('common.sort', ['options' => [
 | 
				
			||||||
 | 
					                        'name' => trans('common.sort_name'),
 | 
				
			||||||
 | 
					                        'endpoint'  => trans('settings.webhooks_endpoint'),
 | 
				
			||||||
 | 
					                        'created_at' => trans('common.sort_created_at'),
 | 
				
			||||||
 | 
					                        'updated_at' => trans('common.sort_updated_at'),
 | 
				
			||||||
 | 
					                        'active'     => trans('common.status'),
 | 
				
			||||||
 | 
					                    ], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'webhooks'])
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @if(count($webhooks) > 0)
 | 
				
			||||||
 | 
					                <div class="item-list">
 | 
				
			||||||
                    @foreach($webhooks as $webhook)
 | 
					                    @foreach($webhooks as $webhook)
 | 
				
			||||||
                        <tr>
 | 
					                        @include('settings.webhooks.parts.webhooks-list-item', ['webhook' => $webhook])
 | 
				
			||||||
                            <td>
 | 
					 | 
				
			||||||
                                <a href="{{ $webhook->getUrl() }}">{{ $webhook->name }}</a> <br>
 | 
					 | 
				
			||||||
                                <span class="small text-muted italic">{{ $webhook->endpoint }}</span>
 | 
					 | 
				
			||||||
                            </td>
 | 
					 | 
				
			||||||
                            <td>
 | 
					 | 
				
			||||||
                                @if($webhook->tracksEvent('all'))
 | 
					 | 
				
			||||||
                                    {{ trans('settings.webhooks_events_all') }}
 | 
					 | 
				
			||||||
                                @else
 | 
					 | 
				
			||||||
                                    {{ $webhook->trackedEvents->count() }}
 | 
					 | 
				
			||||||
                                @endif
 | 
					 | 
				
			||||||
                            </td>
 | 
					 | 
				
			||||||
                            <td>
 | 
					 | 
				
			||||||
                                {{ trans('common.status_' . ($webhook->active ? 'active' : 'inactive')) }}
 | 
					 | 
				
			||||||
                            </td>
 | 
					 | 
				
			||||||
                        </tr>
 | 
					 | 
				
			||||||
                    @endforeach
 | 
					                    @endforeach
 | 
				
			||||||
                </table>
 | 
					                </div>
 | 
				
			||||||
            @else
 | 
					            @else
 | 
				
			||||||
                <p class="text-muted empty-text px-none">
 | 
					                <p class="text-muted empty-text px-none">
 | 
				
			||||||
                    {{ trans('settings.webhooks_none_created') }}
 | 
					                    {{ trans('settings.webhooks_none_created') }}
 | 
				
			||||||
                </p>
 | 
					                </p>
 | 
				
			||||||
            @endif
 | 
					            @endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <div class="my-m">
 | 
				
			||||||
 | 
					                {{ $webhooks->links() }}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					<div class="item-list-row py-s">
 | 
				
			||||||
 | 
					    <div class="flex-container-row">
 | 
				
			||||||
 | 
					        <div class="flex-2 py-xxs px-m flex-container-row items-center gap-s">
 | 
				
			||||||
 | 
					            @include('common.status-indicator', ['status' => $webhook->active])
 | 
				
			||||||
 | 
					            <a href="{{ $webhook->getUrl() }}">{{ $webhook->name }}</a>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="flex py-xxs px-m text-right text-muted">
 | 
				
			||||||
 | 
					            @if($webhook->tracksEvent('all'))
 | 
				
			||||||
 | 
					                {{ trans('settings.webhooks_events_all') }}
 | 
				
			||||||
 | 
					            @else
 | 
				
			||||||
 | 
					                {{ trans_choice('settings.webhooks_x_trigger_events', $webhook->tracked_events_count, ['count' =>  $webhook->tracked_events_count]) }}
 | 
				
			||||||
 | 
					            @endif
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					    <div class="px-m py-xxs text-muted italic text-limit-lines-1">
 | 
				
			||||||
 | 
					        <small>{{ $webhook->endpoint }}</small>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					</div>
 | 
				
			||||||
		Loading…
	
		Reference in New Issue