mirror of
https://github.com/grocy/grocy.git
synced 2025-04-29 01:32:38 +00:00
Implemented user pictures (closes #1158)
This commit is contained in:
parent
3f718eab60
commit
8f1ce607f7
@ -156,6 +156,7 @@
|
|||||||
- Table states (visible columns, sorting, column order and so on) are now saved server side (in user settings) means that this stays the same when using different browsers
|
- Table states (visible columns, sorting, column order and so on) are now saved server side (in user settings) means that this stays the same when using different browsers
|
||||||
- Dialogs are now used everywhere where appropriate instead of jumping between pages (for example when adding/editing shopping list items)
|
- Dialogs are now used everywhere where appropriate instead of jumping between pages (for example when adding/editing shopping list items)
|
||||||
- Added a "Clear filter"-button on all pages (with filters) to quickly reset applied filters
|
- Added a "Clear filter"-button on all pages (with filters) to quickly reset applied filters
|
||||||
|
- Users can now have a picture (will then be shown next to the current user name instead of the generic user icon)
|
||||||
- Prefilled number inputs now use sensible decimal places (max. the configured decimals while hiding trailing zeros where appropriate, means if you never use partial amounts for a product, you'll never see decimals for it)
|
- Prefilled number inputs now use sensible decimal places (max. the configured decimals while hiding trailing zeros where appropriate, means if you never use partial amounts for a product, you'll never see decimals for it)
|
||||||
- Improved / more precise validation messages for number inputs
|
- Improved / more precise validation messages for number inputs
|
||||||
- Ordering now happens case-insensitive
|
- Ordering now happens case-insensitive
|
||||||
|
@ -41,7 +41,7 @@ class UsersApiController extends BaseApiController
|
|||||||
throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)');
|
throw new \Exception('Request body could not be parsed (probably invalid JSON format or missing/wrong Content-Type header)');
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->getUsersService()->CreateUser($requestBody['username'], $requestBody['first_name'], $requestBody['last_name'], $requestBody['password']);
|
$this->getUsersService()->CreateUser($requestBody['username'], $requestBody['first_name'], $requestBody['last_name'], $requestBody['password'], $requestBody['picture_file_name']);
|
||||||
return $this->EmptyApiResponse($response);
|
return $this->EmptyApiResponse($response);
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
@ -79,7 +79,7 @@ class UsersApiController extends BaseApiController
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$this->getUsersService()->EditUser($args['userId'], $requestBody['username'], $requestBody['first_name'], $requestBody['last_name'], $requestBody['password']);
|
$this->getUsersService()->EditUser($args['userId'], $requestBody['username'], $requestBody['first_name'], $requestBody['last_name'], $requestBody['password'], $requestBody['picture_file_name']);
|
||||||
return $this->EmptyApiResponse($response);
|
return $this->EmptyApiResponse($response);
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
|
@ -22,7 +22,8 @@ class UsersController extends BaseController
|
|||||||
{
|
{
|
||||||
User::checkPermission($request, User::PERMISSION_USERS_CREATE);
|
User::checkPermission($request, User::PERMISSION_USERS_CREATE);
|
||||||
return $this->renderPage($response, 'userform', [
|
return $this->renderPage($response, 'userform', [
|
||||||
'mode' => 'create'
|
'mode' => 'create',
|
||||||
|
'userfields' => $this->getUserfieldsService()->GetFields('users')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -38,7 +39,9 @@ class UsersController extends BaseController
|
|||||||
|
|
||||||
return $this->renderPage($response, 'userform', [
|
return $this->renderPage($response, 'userform', [
|
||||||
'user' => $this->getDatabase()->users($args['userId']),
|
'user' => $this->getDatabase()->users($args['userId']),
|
||||||
'mode' => 'edit'
|
'mode' => 'edit',
|
||||||
|
'userfields' => $this->getUserfieldsService()->GetFields('users'),
|
||||||
|
'userfieldValues' => $this->getUserfieldsService()->GetAllValues('users')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4606,6 +4606,9 @@
|
|||||||
"password": {
|
"password": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"picture_file_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"row_created_timestamp": {
|
"row_created_timestamp": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
@ -4631,6 +4634,9 @@
|
|||||||
"display_name": {
|
"display_name": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"picture_file_name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"row_created_timestamp": {
|
"row_created_timestamp": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
|
@ -742,9 +742,6 @@ msgstr ""
|
|||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The current picture will be deleted when you save the product"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Select file"
|
msgid "Select file"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -958,7 +955,7 @@ msgstr ""
|
|||||||
msgid "Gallery"
|
msgid "Gallery"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "The current picture will be deleted when you save the recipe"
|
msgid "The current picture will be deleted on save"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Journal for this battery"
|
msgid "Journal for this battery"
|
||||||
|
@ -43,6 +43,7 @@ abstract class AuthMiddleware extends BaseMiddleware
|
|||||||
|
|
||||||
define('GROCY_AUTHENTICATED', true);
|
define('GROCY_AUTHENTICATED', true);
|
||||||
define('GROCY_USER_USERNAME', $user->username);
|
define('GROCY_USER_USERNAME', $user->username);
|
||||||
|
define('GROCY_USER_PICTURE_FILE_NAME', $user->picture_file_name);
|
||||||
|
|
||||||
return $handler->handle($request);
|
return $handler->handle($request);
|
||||||
}
|
}
|
||||||
@ -70,6 +71,7 @@ abstract class AuthMiddleware extends BaseMiddleware
|
|||||||
define('GROCY_AUTHENTICATED', true);
|
define('GROCY_AUTHENTICATED', true);
|
||||||
define('GROCY_USER_ID', $user->id);
|
define('GROCY_USER_ID', $user->id);
|
||||||
define('GROCY_USER_USERNAME', $user->username);
|
define('GROCY_USER_USERNAME', $user->username);
|
||||||
|
define('GROCY_USER_PICTURE_FILE_NAME', $user->picture_file_name);
|
||||||
|
|
||||||
return $response = $handler->handle($request);
|
return $response = $handler->handle($request);
|
||||||
}
|
}
|
||||||
|
21
migrations/0125.sql
Normal file
21
migrations/0125.sql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
ALTER TABLE users
|
||||||
|
ADD picture_file_name TEXT;
|
||||||
|
|
||||||
|
DROP VIEW users_dto;
|
||||||
|
CREATE VIEW users_dto
|
||||||
|
AS
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
username,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
row_created_timestamp,
|
||||||
|
(CASE
|
||||||
|
WHEN IFNULL(first_name, '') = '' AND IFNULL(last_name, '') != '' THEN last_name
|
||||||
|
WHEN IFNULL(last_name, '') = '' AND IFNULL(first_name, '') != '' THEN first_name
|
||||||
|
WHEN IFNULL(last_name, '') != '' AND IFNULL(first_name, '') != '' THEN first_name || ' ' || last_name
|
||||||
|
ELSE username
|
||||||
|
END
|
||||||
|
) AS display_name,
|
||||||
|
picture_file_name
|
||||||
|
FROM users;
|
@ -379,36 +379,3 @@ $(window).on("message", function(e)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Grocy.Components.RecipePicker.GetPicker().on('change', function (e)
|
|
||||||
// {
|
|
||||||
// var value = Grocy.Components.RecipePicker.GetValue();
|
|
||||||
// if (value.toString().isEmpty())
|
|
||||||
// {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Grocy.Api.Get('objects/recipes/' + value,
|
|
||||||
// function(recipe)
|
|
||||||
// {
|
|
||||||
// $("#includes_servings").val(recipe.servings);
|
|
||||||
// },
|
|
||||||
// function(xhr)
|
|
||||||
// {
|
|
||||||
// console.error(xhr);
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Grocy.Components.ProductPicker.GetPicker().on('change', function(e)
|
|
||||||
// {
|
|
||||||
// // Just save the current recipe on every change of the product picker as a workflow could be started which leaves the page...
|
|
||||||
// Grocy.Api.Put('objects/recipes/' + Grocy.EditObjectId, $('#recipe-form').serializeJSON(), function () { }, function () { });
|
|
||||||
// });
|
|
||||||
|
|
||||||
// As the /recipe/new route immediately creates a new recipe on load,
|
|
||||||
// always replace the current location by the created recipes edit page location
|
|
||||||
// if (window.location.pathname.toLowerCase() === "/recipe/new")
|
|
||||||
// {
|
|
||||||
// window.history.replaceState(null, null, U("/recipe/" + Grocy.EditObjectId));
|
|
||||||
// }
|
|
||||||
|
@ -1,17 +1,46 @@
|
|||||||
$('#save-user-button').on('click', function(e)
|
function SaveUserPicture(result, jsonData)
|
||||||
|
{
|
||||||
|
var userId = Grocy.EditObjectId || result.created_object_id;
|
||||||
|
Grocy.Components.UserfieldsForm.Save(() =>
|
||||||
|
{
|
||||||
|
if (jsonData.hasOwnProperty("picture_file_name") && !Grocy.DeleteUserPictureOnSave)
|
||||||
|
{
|
||||||
|
Grocy.Api.UploadFile($("#user-picture")[0].files[0], 'userpictures', jsonData.picture_file_name,
|
||||||
|
(result) =>
|
||||||
|
{
|
||||||
|
window.location.href = U('/users');
|
||||||
|
},
|
||||||
|
(xhr) =>
|
||||||
|
{
|
||||||
|
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
||||||
|
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window.location.href = U('/users');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#save-user-button').on('click', function(e)
|
||||||
{
|
{
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
var jsonData = $('#user-form').serializeJSON();
|
var jsonData = $('#user-form').serializeJSON();
|
||||||
Grocy.FrontendHelpers.BeginUiBusy("user-form");
|
Grocy.FrontendHelpers.BeginUiBusy("user-form");
|
||||||
|
|
||||||
|
if ($("#user-picture")[0].files.length > 0)
|
||||||
|
{
|
||||||
|
var someRandomStuff = Math.random().toString(36).substring(2, 100) + Math.random().toString(36).substring(2, 100);
|
||||||
|
jsonData.picture_file_name = someRandomStuff + $("#user-picture")[0].files[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
if (Grocy.EditMode === 'create')
|
if (Grocy.EditMode === 'create')
|
||||||
{
|
{
|
||||||
Grocy.Api.Post('users', jsonData,
|
Grocy.Api.Post('users', jsonData,
|
||||||
function(result)
|
(result) => SaveUserPicture(result, jsonData),
|
||||||
{
|
|
||||||
window.location.href = U('/users');
|
|
||||||
},
|
|
||||||
function(xhr)
|
function(xhr)
|
||||||
{
|
{
|
||||||
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
||||||
@ -21,11 +50,25 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (Grocy.DeleteUserPictureOnSave)
|
||||||
|
{
|
||||||
|
jsonData.picture_file_name = null;
|
||||||
|
|
||||||
|
Grocy.Api.DeleteFile(Grocy.UserPictureFileName, 'userpictures', {},
|
||||||
|
function(result)
|
||||||
|
{
|
||||||
|
// Nothing to do
|
||||||
|
},
|
||||||
|
function(xhr)
|
||||||
|
{
|
||||||
|
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
||||||
|
Grocy.FrontendHelpers.ShowGenericError('Error while saving, probably this item already exists', xhr.response)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Grocy.Api.Put('users/' + Grocy.EditObjectId, jsonData,
|
Grocy.Api.Put('users/' + Grocy.EditObjectId, jsonData,
|
||||||
function(result)
|
(result) => SaveUserPicture(result, jsonData),
|
||||||
{
|
|
||||||
window.location.href = U('/users');
|
|
||||||
},
|
|
||||||
function(xhr)
|
function(xhr)
|
||||||
{
|
{
|
||||||
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
Grocy.FrontendHelpers.EndUiBusy("user-form");
|
||||||
@ -76,4 +119,23 @@ else
|
|||||||
$('#username').focus();
|
$('#username').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$("#user-picture").on("change", function(e)
|
||||||
|
{
|
||||||
|
$("#user-picture-label").removeClass("d-none");
|
||||||
|
$("#user-picture-label-none").addClass("d-none");
|
||||||
|
$("#delete-current-user-picture-on-save-hint").addClass("d-none");
|
||||||
|
$("#current-user-picture").addClass("d-none");
|
||||||
|
Grocy.DeleteUserePictureOnSave = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
Grocy.DeleteUserPictureOnSave = false;
|
||||||
|
$("#delete-current-user-picture-button").on("click", function(e)
|
||||||
|
{
|
||||||
|
Grocy.DeleteUserPictureOnSave = true;
|
||||||
|
$("#current-user-picture").addClass("d-none");
|
||||||
|
$("#delete-current-user-picture-on-save-hint").removeClass("d-none");
|
||||||
|
$("#user-picture-label").addClass("d-none");
|
||||||
|
$("#user-picture-label-none").removeClass("d-none");
|
||||||
|
});
|
||||||
|
|
||||||
Grocy.FrontendHelpers.ValidateForm('user-form');
|
Grocy.FrontendHelpers.ValidateForm('user-form');
|
||||||
|
@ -37,15 +37,15 @@ class UserfieldsService extends BaseService
|
|||||||
public function GetEntities()
|
public function GetEntities()
|
||||||
{
|
{
|
||||||
$exposedDefaultEntities = $this->getOpenApiSpec()->components->internalSchemas->ExposedEntity->enum;
|
$exposedDefaultEntities = $this->getOpenApiSpec()->components->internalSchemas->ExposedEntity->enum;
|
||||||
|
$userEntities = [];
|
||||||
$userentities = [];
|
$specialEntities = ['users'];
|
||||||
|
|
||||||
foreach ($this->getDatabase()->userentities()->orderBy('name', 'COLLATE NOCASE') as $userentity)
|
foreach ($this->getDatabase()->userentities()->orderBy('name', 'COLLATE NOCASE') as $userentity)
|
||||||
{
|
{
|
||||||
$userentities[] = 'userentity-' . $userentity->name;
|
$userEntities[] = 'userentity-' . $userentity->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_merge($exposedDefaultEntities, $userentities);
|
return array_merge($exposedDefaultEntities, $userEntities, $specialEntities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function GetField($fieldId)
|
public function GetField($fieldId)
|
||||||
|
@ -4,13 +4,14 @@ namespace Grocy\Services;
|
|||||||
|
|
||||||
class UsersService extends BaseService
|
class UsersService extends BaseService
|
||||||
{
|
{
|
||||||
public function CreateUser(string $username, string $firstName, string $lastName, string $password)
|
public function CreateUser(string $username, string $firstName, string $lastName, string $password, string $pictureFileName = null)
|
||||||
{
|
{
|
||||||
$newUserRow = $this->getDatabase()->users()->createRow([
|
$newUserRow = $this->getDatabase()->users()->createRow([
|
||||||
'username' => $username,
|
'username' => $username,
|
||||||
'first_name' => $firstName,
|
'first_name' => $firstName,
|
||||||
'last_name' => $lastName,
|
'last_name' => $lastName,
|
||||||
'password' => password_hash($password, PASSWORD_DEFAULT)
|
'password' => password_hash($password, PASSWORD_DEFAULT),
|
||||||
|
'picture_file_name' => $pictureFileName
|
||||||
]);
|
]);
|
||||||
$newUserRow = $newUserRow->save();
|
$newUserRow = $newUserRow->save();
|
||||||
$permList = [];
|
$permList = [];
|
||||||
@ -34,7 +35,7 @@ class UsersService extends BaseService
|
|||||||
$row->delete();
|
$row->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function EditUser(int $userId, string $username, string $firstName, string $lastName, string $password)
|
public function EditUser(int $userId, string $username, string $firstName, string $lastName, string $password, string $pictureFileName = null)
|
||||||
{
|
{
|
||||||
if (!$this->UserExists($userId))
|
if (!$this->UserExists($userId))
|
||||||
{
|
{
|
||||||
@ -46,7 +47,8 @@ class UsersService extends BaseService
|
|||||||
'username' => $username,
|
'username' => $username,
|
||||||
'first_name' => $firstName,
|
'first_name' => $firstName,
|
||||||
'last_name' => $lastName,
|
'last_name' => $lastName,
|
||||||
'password' => password_hash($password, PASSWORD_DEFAULT)
|
'password' => password_hash($password, PASSWORD_DEFAULT),
|
||||||
|
'picture_file_name' => $pictureFileName
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -478,7 +478,15 @@
|
|||||||
<li class="nav-item dropdown">
|
<li class="nav-item dropdown">
|
||||||
<a class="nav-link dropdown-toggle discrete-link"
|
<a class="nav-link dropdown-toggle discrete-link"
|
||||||
href="#"
|
href="#"
|
||||||
data-toggle="dropdown"><i class="fas fa-user"></i> {{ GROCY_USER_USERNAME }}</a>
|
data-toggle="dropdown">
|
||||||
|
@if(empty(GROCY_USER_PICTURE_FILE_NAME))
|
||||||
|
<i class="fas fa-user"></i>
|
||||||
|
@else
|
||||||
|
<img class="lazy rounded-circle mt-n1"
|
||||||
|
src="{{ $U('/files/userpictures/' . base64_encode(GROCY_USER_PICTURE_FILE_NAME) . '_' . base64_encode(GROCY_USER_PICTURE_FILE_NAME) . '?force_serve_as=picture&best_fit_width=16&best_fit_height=16') }}">
|
||||||
|
@endif
|
||||||
|
{{ GROCY_USER_USERNAME }}
|
||||||
|
</a>
|
||||||
|
|
||||||
<div class="dropdown-menu dropdown-menu-right">
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
<a class="dropdown-item logout-button discrete-link"
|
<a class="dropdown-item logout-button discrete-link"
|
||||||
|
@ -661,7 +661,7 @@
|
|||||||
data-src="{{ $U('/api/files/productpictures/' . base64_encode($product->picture_file_name) . '?force_serve_as=picture&best_fit_width=400') }}"
|
data-src="{{ $U('/api/files/productpictures/' . base64_encode($product->picture_file_name) . '?force_serve_as=picture&best_fit_width=400') }}"
|
||||||
class="img-fluid img-thumbnail mt-2 lazy mb-5">
|
class="img-fluid img-thumbnail mt-2 lazy mb-5">
|
||||||
<p id="delete-current-product-picture-on-save-hint"
|
<p id="delete-current-product-picture-on-save-hint"
|
||||||
class="form-text text-muted font-italic d-none mb-5">{{ $__t('The current picture will be deleted when you save the product') }}</p>
|
class="form-text text-muted font-italic d-none mb-5">{{ $__t('The current picture will be deleted on save') }}</p>
|
||||||
@else
|
@else
|
||||||
<p id="no-current-product-picture-hint"
|
<p id="no-current-product-picture-hint"
|
||||||
class="form-text text-muted font-italic mb-5">{{ $__t('No picture available') }}</p>
|
class="form-text text-muted font-italic mb-5">{{ $__t('No picture available') }}</p>
|
||||||
|
@ -319,7 +319,7 @@
|
|||||||
data-src="{{ $U('/api/files/recipepictures/' . base64_encode($recipe->picture_file_name) . '?force_serve_as=picture&best_fit_width=400') }}"
|
data-src="{{ $U('/api/files/recipepictures/' . base64_encode($recipe->picture_file_name) . '?force_serve_as=picture&best_fit_width=400') }}"
|
||||||
class="img-fluid img-thumbnail mt-2 lazy mb-5">
|
class="img-fluid img-thumbnail mt-2 lazy mb-5">
|
||||||
<p id="delete-current-recipe-picture-on-save-hint"
|
<p id="delete-current-recipe-picture-on-save-hint"
|
||||||
class="form-text text-muted font-italic d-none mb-5">{{ $__t('The current picture will be deleted when you save the recipe') }}</p>
|
class="form-text text-muted font-italic d-none mb-5">{{ $__t('The current picture will be deleted on save') }}</p>
|
||||||
@else
|
@else
|
||||||
<p id="no-current-recipe-picture-hint"
|
<p id="no-current-recipe-picture-hint"
|
||||||
class="form-text text-muted font-italic mb-5">{{ $__t('No picture available') }}</p>
|
class="form-text text-muted font-italic mb-5">{{ $__t('No picture available') }}</p>
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
@if($mode == 'edit')
|
@if($mode == 'edit')
|
||||||
<script>
|
<script>
|
||||||
Grocy.EditObjectId = {{ $user->id }};
|
Grocy.EditObjectId = {{ $user->id }};
|
||||||
|
|
||||||
|
@if(!empty($user->picture_file_name))
|
||||||
|
Grocy.UserPictureFileName = '{{ $user->picture_file_name }}';
|
||||||
|
@endif
|
||||||
</script>
|
</script>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@ -80,10 +84,57 @@
|
|||||||
<div class="invalid-feedback">{{ $__t('Passwords do not match') }}</div>
|
<div class="invalid-feedback">{{ $__t('Passwords do not match') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@include('components.userfieldsform', array(
|
||||||
|
'userfields' => $userfields,
|
||||||
|
'entity' => 'users'
|
||||||
|
))
|
||||||
|
|
||||||
<button id="save-user-button"
|
<button id="save-user-button"
|
||||||
class="btn btn-success">{{ $__t('Save') }}</button>
|
class="btn btn-success">{{ $__t('Save') }}</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-xs-12">
|
||||||
|
<div class="title-related-links">
|
||||||
|
<h4>
|
||||||
|
{{ $__t('Picture') }}
|
||||||
|
</h4>
|
||||||
|
<div class="form-group w-75 m-0">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="custom-file">
|
||||||
|
<input type="file"
|
||||||
|
class="custom-file-input"
|
||||||
|
id="user-picture"
|
||||||
|
accept="image/*">
|
||||||
|
<label id="user-picture-label"
|
||||||
|
class="custom-file-label @if(empty($user->picture_file_name)) d-none @endif"
|
||||||
|
for="user-picture">
|
||||||
|
{{ $user->picture_file_name }}
|
||||||
|
</label>
|
||||||
|
<label id="user-picture-label-none"
|
||||||
|
class="custom-file-label @if(!empty($user->picture_file_name)) d-none @endif"
|
||||||
|
for="user-picture">
|
||||||
|
{{ $__t('No file selected') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="input-group-append">
|
||||||
|
<span class="input-group-text"><i class="fas fa-trash"
|
||||||
|
id="delete-current-user-picture-button"></i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@if(!empty($user->picture_file_name))
|
||||||
|
<img id="current-user-picture"
|
||||||
|
data-src="{{ $U('/api/files/userpictures/' . base64_encode($user->picture_file_name) . '?force_serve_as=picture&best_fit_width=400') }}"
|
||||||
|
class="img-fluid img-thumbnail mt-2 lazy mb-5">
|
||||||
|
<p id="delete-current-user-picture-on-save-hint"
|
||||||
|
class="form-text text-muted font-italic d-none mb-5">{{ $__t('The current picture will be deleted on save') }}</p>
|
||||||
|
@else
|
||||||
|
<p id="no-current-user-picture-hint"
|
||||||
|
class="form-text text-muted font-italic mb-5">{{ $__t('No picture available') }}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@stop
|
@stop
|
||||||
|
Loading…
x
Reference in New Issue
Block a user