0
0
Fork 0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-04-23 20:30:22 +00:00

My Account: Built out profile page & endpoints

Text currently hard-coded, needs finalising and extracting.
This commit is contained in:
Dan Brown 2023-10-18 12:39:57 +01:00
parent a868012048
commit c1b01639c1
No known key found for this signature in database
GPG key ID: 46D9F943C24A2EF9
4 changed files with 157 additions and 1 deletions
app/Users/Controllers
lang/en
resources/views/users/account
routes

View file

@ -7,6 +7,7 @@ use BookStack\Http\Controller;
use BookStack\Permissions\PermissionApplicator;
use BookStack\Settings\UserNotificationPreferences;
use BookStack\Settings\UserShortcutMap;
use BookStack\Uploads\ImageRepo;
use BookStack\Users\UserRepo;
use Closure;
use Illuminate\Http\Request;
@ -19,6 +20,7 @@ class UserAccountController extends Controller
) {
$this->middleware(function (Request $request, Closure $next) {
$this->preventGuestAccess();
$this->preventAccessInDemoMode();
return $next($request);
});
}
@ -35,6 +37,51 @@ class UserAccountController extends Controller
]);
}
/**
* Show the profile form interface.
*/
public function showProfile()
{
return view('users.account.profile', [
'model' => user(),
'category' => 'profile',
]);
}
/**
* Handle the submission of the user profile form.
*/
public function updateProfile(Request $request, ImageRepo $imageRepo)
{
$user = user();
$validated = $this->validate($request, [
'name' => ['min:2', 'max:100'],
'email' => ['min:2', 'email', 'unique:users,email,' . $user->id],
'language' => ['string', 'max:15', 'alpha_dash'],
'profile_image' => array_merge(['nullable'], $this->getImageValidationRules()),
]);
$this->userRepo->update($user, $validated, userCan('users-manage'));
// Save profile image if in request
if ($request->hasFile('profile_image')) {
$imageUpload = $request->file('profile_image');
$imageRepo->destroyImage($user->avatar);
$image = $imageRepo->saveNew($imageUpload, 'user', $user->id);
$user->image_id = $image->id;
$user->save();
}
// Delete the profile image if reset option is in request
if ($request->has('profile_image_reset')) {
$imageRepo->destroyImage($user->avatar);
$user->image_id = 0;
$user->save();
}
return redirect('/my-account/profile');
}
/**
* Show the user-specific interface shortcuts.
*/

View file

@ -35,5 +35,5 @@ return [
'auth_change_password_success' => 'Password has been updated!',
'profile' => 'Profile Details',
'profile_overview_desc' => ' Manage your user profile details including preferred language and authentication options.',
'profile_overview_desc' => 'Manage your user profile details including preferred language and authentication options.',
];

View file

@ -0,0 +1,107 @@
@extends('users.account.layout')
@section('main')
<section class="card content-wrap auto-height">
<form action="{{ url('/my-account/profile') }}" method="post" enctype="multipart/form-data">
{{ method_field('put') }}
{{ csrf_field() }}
<div class="flex-container-row gap-l items-center wrap justify-space-between">
<h1 class="list-heading">{{ trans('preferences.profile') }}</h1>
<div>
<a href="{{ user()->getProfileUrl() }}" class="button outline">View Public Profile</a>
</div>
</div>
<p class="text-muted text-small mb-none">
Manage the details of your account that represent you to other users, in addition to
details that are used for communication and system personalisation.
</p>
<div class="setting-list">
<div class="flex-container-row gap-l items-center wrap">
<div class="flex">
<label class="setting-list-label" for="name">{{ trans('auth.name') }}</label>
<p class="text-small mb-none">
Configure your display name which will be visible to other users in the system
within the activity you perform, and content you own.
</p>
</div>
<div class="flex stretch-inputs">
@include('form.text', ['name' => 'name'])
</div>
</div>
<div>
<div class="flex-container-row gap-l items-center wrap">
<div class="flex">
<label class="setting-list-label" for="email">{{ trans('auth.email') }}</label>
<p class="text-small mb-none">
This email will be used for notifications and, depending on active system authentication, system access.
</p>
</div>
<div class="flex stretch-inputs">
@include('form.text', ['name' => 'email', 'disabled' => !userCan('users-manage')])
</div>
</div>
@if(!userCan('users-manage'))
<p class="text-small text-muted">
Unfortunately you don't have permission to change your email address.
If you want to change this, you'd need to ask an administrator to change this for you.
</p>
@endif
</div>
<div class="grid half gap-xl">
<div>
<label for="user-avatar"
class="setting-list-label">{{ trans('settings.users_avatar') }}</label>
<p class="text-small">
Select an image which will be used to represent yourself to others
in the system. Ideally this image should be square and about 256px in width and height.
</p>
</div>
<div>
@include('form.image-picker', [
'resizeHeight' => '512',
'resizeWidth' => '512',
'showRemove' => false,
'defaultImage' => url('/user_avatar.png'),
'currentImage' => user()->getAvatar(80),
'currentId' => user()->image_id,
'name' => 'profile_image',
'imageClass' => 'avatar large'
])
</div>
</div>
@include('users.parts.language-option-row', ['value' => old('language') ?? user()->getLocale()->appLocale()])
</div>
<div class="form-group text-right">
<button class="button">{{ trans('common.save') }}</button>
</div>
</form>
</section>
@if(userCan('users-manage'))
<section class="card content-wrap auto-height">
<div class="flex-container-row gap-l items-center wrap">
<div class="flex">
<h2 class="list-heading">Administrator Options</h2>
<p class="text-small">
Additional administrator-level options, like role options, can be found for your user account in the
<nobr>"Settings > Users"</nobr> area of the application.
</p>
</div>
<div class="text-m-right">
<a class="button outline" href="{{ user()->getEditUrl() }}">Open</a>
</div>
</div>
</section>
@endif
@stop

View file

@ -234,6 +234,8 @@ Route::middleware('auth')->group(function () {
// User Account
Route::get('/my-account', [UserControllers\UserAccountController::class, 'index']);
Route::get('/my-account/profile', [UserControllers\UserAccountController::class, 'showProfile']);
Route::put('/my-account/profile', [UserControllers\UserAccountController::class, 'updateProfile']);
Route::get('/my-account/shortcuts', [UserControllers\UserAccountController::class, 'showShortcuts']);
Route::put('/my-account/shortcuts', [UserControllers\UserAccountController::class, 'updateShortcuts']);
Route::get('/my-account/notifications', [UserControllers\UserAccountController::class, 'showNotifications']);