mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Redesigned users list to be responsive and aligned
This commit is contained in:
parent
2a65331573
commit
986346a0e9
@ -19,6 +19,9 @@ class AllUsersPaginatedAndSorted
|
||||
public function run(int $count, array $sortData): LengthAwarePaginator
|
||||
{
|
||||
$sort = $sortData['sort'];
|
||||
if ($sort === 'created_at') {
|
||||
$sort = 'users.created_at';
|
||||
}
|
||||
|
||||
$query = User::query()->select(['*'])
|
||||
->scopes(['withLastActivityAt'])
|
||||
|
@ -37,15 +37,15 @@ class UserController extends Controller
|
||||
{
|
||||
$this->checkPermission('users-manage');
|
||||
$listDetails = [
|
||||
'order' => $request->get('order', 'asc'),
|
||||
'search' => $request->get('search', ''),
|
||||
'sort' => $request->get('sort', 'name'),
|
||||
'sort' => setting()->getForCurrentUser('users_sort', 'name'),
|
||||
'order' => setting()->getForCurrentUser('users_sort_order', 'asc'),
|
||||
];
|
||||
|
||||
$users = (new AllUsersPaginatedAndSorted())->run(20, $listDetails);
|
||||
|
||||
$this->setPageTitle(trans('settings.users'));
|
||||
$users->appends($listDetails);
|
||||
$users->appends(['search' => $listDetails['search']]);
|
||||
|
||||
return view('users.index', [
|
||||
'users' => $users,
|
||||
@ -251,7 +251,7 @@ class UserController extends Controller
|
||||
*/
|
||||
public function changeSort(Request $request, string $id, string $type)
|
||||
{
|
||||
$validSortTypes = ['books', 'bookshelves', 'shelf_books'];
|
||||
$validSortTypes = ['books', 'bookshelves', 'shelf_books', 'users'];
|
||||
if (!in_array($type, $validSortTypes)) {
|
||||
return redirect()->back(500);
|
||||
}
|
||||
@ -318,7 +318,7 @@ class UserController extends Controller
|
||||
$this->checkPermissionOrCurrentUser('users-manage', $userId);
|
||||
|
||||
$sort = $request->get('sort');
|
||||
if (!in_array($sort, ['name', 'created_at', 'updated_at', 'default'])) {
|
||||
if (!in_array($sort, ['name', 'created_at', 'updated_at', 'default', 'email', 'last_activity_at'])) {
|
||||
$sort = 'name';
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,7 @@ class EntityPermissions {
|
||||
}
|
||||
|
||||
removeRowOnButtonClick(button) {
|
||||
const row = button.closest('.content-permissions-row');
|
||||
const row = button.closest('.item-list-row');
|
||||
const roleId = button.dataset.roleId;
|
||||
const roleName = button.dataset.roleName;
|
||||
|
||||
|
@ -172,6 +172,7 @@ return [
|
||||
|
||||
// Users
|
||||
'users' => 'Users',
|
||||
'users_index_desc' => 'Create & manage individual user accounts within the system. User accounts are used for login and attribution of content & activity. Access permissions are primarily role-based but user content ownership, among other factors, may also affect permissions & access.',
|
||||
'user_profile' => 'User Profile',
|
||||
'users_add_new' => 'Add New User',
|
||||
'users_search' => 'Search Users',
|
||||
|
@ -798,37 +798,6 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.content-permissions {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.content-permissions-row {
|
||||
border: 1.5px solid;
|
||||
@include lightDark(border-color, #E2E2E2, #444);
|
||||
border-bottom-width: 0;
|
||||
label {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
&:hover {
|
||||
@include lightDark(background-color, #F2F2F2, #333);
|
||||
}
|
||||
}
|
||||
.content-permissions-row:first-child {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
.content-permissions-row:last-child {
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-bottom-width: 1.5px;
|
||||
}
|
||||
.content-permissions-row:first-child:last-child {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.content-permissions-row-toggle-all {
|
||||
visibility: hidden;
|
||||
}
|
||||
.content-permissions-row:hover .content-permissions-row-toggle-all {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.template-item {
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
@ -970,3 +939,34 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
|
||||
max-height: 240px;
|
||||
}
|
||||
}
|
||||
|
||||
.item-list {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.item-list-row {
|
||||
border: 1.5px solid;
|
||||
@include lightDark(border-color, #E2E2E2, #444);
|
||||
border-bottom-width: 0;
|
||||
label {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
&:hover {
|
||||
@include lightDark(background-color, #F6F6F6, #333);
|
||||
}
|
||||
}
|
||||
.item-list-row:first-child {
|
||||
border-radius: 4px 4px 0 0;
|
||||
}
|
||||
.item-list-row:last-child {
|
||||
border-radius: 0 0 4px 4px;
|
||||
border-bottom-width: 1.5px;
|
||||
}
|
||||
.item-list-row:first-child:last-child {
|
||||
border-radius: 4px;
|
||||
}
|
||||
.item-list-row-toggle-all {
|
||||
visibility: hidden;
|
||||
}
|
||||
.item-list-row:hover .item-list-row-toggle-all {
|
||||
visibility: visible;
|
||||
}
|
@ -158,6 +158,18 @@ body.flexbox {
|
||||
}
|
||||
}
|
||||
|
||||
.flex-2 {
|
||||
min-height: 0;
|
||||
flex: 2;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.flex-3 {
|
||||
min-height: 0;
|
||||
flex: 3;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.flex-none {
|
||||
flex: none;
|
||||
}
|
||||
@ -178,6 +190,27 @@ body.flexbox {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/**
|
||||
* Min width utilities
|
||||
*/
|
||||
.min-width-xs {
|
||||
min-width: 120px;
|
||||
}
|
||||
.min-width-s {
|
||||
min-width: 160px;
|
||||
}
|
||||
.min-width-m {
|
||||
min-width: 200px;
|
||||
}
|
||||
.min-width-l {
|
||||
min-width: 240px;
|
||||
}
|
||||
.min-width-xl {
|
||||
min-width: 280px;
|
||||
}
|
||||
.min-width-xxl {
|
||||
min-width: 320px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display and float utilities
|
||||
|
@ -3,7 +3,7 @@
|
||||
<h1 class="list-heading">{{ trans('entities.books') }}</h1>
|
||||
<div class="text-m-right my-m">
|
||||
|
||||
@include('entities.sort', ['options' => [
|
||||
@include('common.sort', ['options' => [
|
||||
'name' => trans('common.sort_name'),
|
||||
'created_at' => trans('common.sort_created_at'),
|
||||
'updated_at' => trans('common.sort_updated_at'),
|
||||
|
@ -5,7 +5,7 @@ $permission - The entity permission containing the permissions.
|
||||
$inheriting - Boolean if the current row should be marked as inheriting default permissions. Used for "Everyone Else" role.
|
||||
--}}
|
||||
|
||||
<div component="permissions-table" class="content-permissions-row flex-container-row justify-space-between wrap">
|
||||
<div component="permissions-table" class="item-list-row flex-container-row justify-space-between wrap">
|
||||
<div class="gap-x-m flex-container-row items-center px-l py-m flex">
|
||||
<div class="text-large" title="{{ $role->id === 0 ? trans('entities.permissions_role_everyone_else') : trans('common.role') }}">
|
||||
@icon($role->id === 0 ? 'groups' : 'role')
|
||||
@ -16,7 +16,7 @@ $inheriting - Boolean if the current row should be marked as inheriting default
|
||||
</span>
|
||||
@if($role->id !== 0)
|
||||
<button type="button"
|
||||
class="ml-auto flex-none text-small text-primary text-button hover-underline content-permissions-row-toggle-all hide-under-s"
|
||||
class="ml-auto flex-none text-small text-primary text-button hover-underline item-list-row-toggle-all hide-under-s"
|
||||
refs="permissions-table@toggle-all"
|
||||
><strong>{{ trans('common.toggle_all') }}</strong></button>
|
||||
@endif
|
||||
|
@ -35,7 +35,7 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<div refs="entity-permissions@role-container" class="content-permissions mt-m mb-m">
|
||||
<div refs="entity-permissions@role-container" class="item-list mt-m mb-m">
|
||||
@foreach($data->permissionsWithRoles() as $permission)
|
||||
@include('form.entity-permissions-row', [
|
||||
'permission' => $permission,
|
||||
@ -58,7 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-permissions mt-m mb-xl">
|
||||
<div class="item-list mt-m mb-xl">
|
||||
@include('form.entity-permissions-row', [
|
||||
'role' => $data->everyoneElseRole(),
|
||||
'permission' => $data->everyoneElseEntityPermission(),
|
||||
|
@ -1,10 +1,9 @@
|
||||
|
||||
<main class="content-wrap mt-m card">
|
||||
|
||||
<div class="grid half v-center">
|
||||
<h1 class="list-heading">{{ trans('entities.shelves') }}</h1>
|
||||
<div class="text-right">
|
||||
@include('entities.sort', ['options' => $sortOptions, 'order' => $order, 'sort' => $sort, 'type' => 'bookshelves'])
|
||||
@include('common.sort', ['options' => $sortOptions, 'order' => $order, 'sort' => $sort, 'type' => 'bookshelves'])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -31,7 +30,8 @@
|
||||
@else
|
||||
<p class="text-muted">{{ trans('entities.shelves_empty') }}</p>
|
||||
@if(userCan('bookshelf-create-all'))
|
||||
<a href="{{ url("/create-shelf") }}" class="button outline">@icon('edit'){{ trans('entities.create_now') }}</a>
|
||||
<a href="{{ url("/create-shelf") }}"
|
||||
class="button outline">@icon('edit'){{ trans('entities.create_now') }}</a>
|
||||
@endif
|
||||
@endif
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
<h1 class="flex fit-content break-text">{{ $shelf->name }}</h1>
|
||||
<div class="flex"></div>
|
||||
<div class="flex fit-content text-m-right my-m ml-m">
|
||||
@include('entities.sort', ['options' => [
|
||||
@include('common.sort', ['options' => [
|
||||
'default' => trans('common.sort_default'),
|
||||
'name' => trans('common.sort_name'),
|
||||
'created_at' => trans('common.sort_created_at'),
|
||||
|
@ -9,37 +9,37 @@
|
||||
|
||||
<div class="flex-container-row wrap justify-space-between items-center">
|
||||
<h1 class="list-heading">{{ trans('settings.users') }}</h1>
|
||||
|
||||
<div>
|
||||
<div class="block inline mr-xs">
|
||||
<form method="get" action="{{ url("/settings/users") }}">
|
||||
@foreach(collect($listDetails)->except('search') as $name => $val)
|
||||
<input type="hidden" name="{{ $name }}" value="{{ $val }}">
|
||||
@endforeach
|
||||
<input type="text" name="search" placeholder="{{ trans('settings.users_search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
|
||||
</form>
|
||||
</div>
|
||||
<a href="{{ url("/settings/users/create") }}" class="outline button mt-none">{{ trans('settings.users_add_new') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th width="9%"></th>
|
||||
<th width="36%">
|
||||
<a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'name']) }}">{{ trans('auth.name') }}</a>
|
||||
/
|
||||
<a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'email']) }}">{{ trans('auth.email') }}</a>
|
||||
</th>
|
||||
<th width="35%">{{ trans('settings.role_user_roles') }}</th>
|
||||
<th class="text-right" width="20%">
|
||||
<a href="{{ sortUrl('/settings/users', $listDetails, ['sort' => 'last_activity_at']) }}">{{ trans('settings.users_latest_activity') }}</a>
|
||||
</th>
|
||||
</tr>
|
||||
<p class="text-muted">{{ trans('settings.users_index_desc') }}</p>
|
||||
|
||||
<div class="flex-container-row items-center justify-space-between gap-m mt-m mb-l wrap">
|
||||
<div>
|
||||
<div class="block inline mr-xs">
|
||||
<form method="get" action="{{ url("/settings/users") }}">
|
||||
<input type="text" name="search" placeholder="{{ trans('settings.users_search') }}" @if($listDetails['search']) value="{{$listDetails['search']}}" @endif>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="justify-flex-end">
|
||||
@include('common.sort', ['options' => [
|
||||
'name' => trans('common.sort_name'),
|
||||
'email' => trans('auth.email'),
|
||||
'created_at' => trans('common.sort_created_at'),
|
||||
'updated_at' => trans('common.sort_updated_at'),
|
||||
'last_activity_at' => trans('settings.users_latest_activity'),
|
||||
], 'order' => $listDetails['order'], 'sort' => $listDetails['sort'], 'type' => 'users'])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-list">
|
||||
@foreach($users as $user)
|
||||
<tr>
|
||||
<td class="text-center" style="line-height: 0;"><img class="avatar med" src="{{ $user->getAvatar(40)}}" alt="{{ $user->name }}"></td>
|
||||
<td>
|
||||
<div class="flex-container-row item-list-row items-center wrap py-s">
|
||||
<div class="px-m py-xs flex-container-row items-center flex-2 gap-l min-width-m">
|
||||
<img class="avatar med" width="40" height="40" src="{{ $user->getAvatar(40)}}" alt="{{ $user->name }}">
|
||||
<a href="{{ url("/settings/users/{$user->id}") }}">
|
||||
{{ $user->name }}
|
||||
<br>
|
||||
@ -48,20 +48,24 @@
|
||||
<span title="MFA Configured" class="text-pos">@icon('lock')</span>
|
||||
@endif
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
</div>
|
||||
<div class="flex-container-row items-center flex-3 min-width-m">
|
||||
<div class="px-m py-xs flex">
|
||||
@foreach($user->roles as $index => $role)
|
||||
<small><a href="{{ url("/settings/roles/{$role->id}") }}">{{$role->display_name}}</a>@if($index !== count($user->roles) -1),@endif</small>
|
||||
@endforeach
|
||||
</td>
|
||||
<td class="text-right text-muted">
|
||||
</div>
|
||||
<div class="px-m py-xs flex text-right text-muted">
|
||||
@if($user->last_activity_at)
|
||||
<small>{{ trans('settings.users_latest_activity') }}</small>
|
||||
<br>
|
||||
<small title="{{ $user->last_activity_at->format('Y-m-d H:i:s') }}">{{ $user->last_activity_at->diffForHumans() }}</small>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{{ $users->links() }}
|
||||
|
Loading…
Reference in New Issue
Block a user