Compare commits
2 Commits
8280f66b6d
...
31bc4d60e4
| Author | SHA1 | Date |
|---|---|---|
|
|
31bc4d60e4 | |
|
|
817782a766 |
|
|
@ -4,3 +4,4 @@ jilo.db
|
|||
jilo-web.db
|
||||
packaging/deb-package/
|
||||
packaging/rpm-package/
|
||||
/public_html/uploads/avatars/
|
||||
|
|
|
|||
|
|
@ -473,6 +473,20 @@ class User {
|
|||
$newFileName = md5(time() . $fileName) . '.' . $fileExtension;
|
||||
$dest_path = $avatars_path . $newFileName;
|
||||
|
||||
// ensure avatars directory exists
|
||||
if (!is_dir($avatars_path)) {
|
||||
if (!mkdir($avatars_path, 0755, true)) {
|
||||
$_SESSION['error'] .= 'Unable to create avatars directory. ';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// check if directory is writable
|
||||
if (!is_writable($avatars_path)) {
|
||||
$_SESSION['error'] .= 'Avatars directory is not writable. ';
|
||||
return false;
|
||||
}
|
||||
|
||||
// move the file to avatars folder
|
||||
if (move_uploaded_file($fileTmpPath, $dest_path)) {
|
||||
try {
|
||||
|
|
@ -486,24 +500,50 @@ class User {
|
|||
':user_id' => $userId
|
||||
]);
|
||||
// all went OK
|
||||
$_SESSION['notice'] .= 'Avatar updated successfully. ';
|
||||
$_SESSION['notice'] = 'Avatar updated successfully. ';
|
||||
return true;
|
||||
} catch (Exception $e) {
|
||||
$_SESSION['error'] .= 'Database error updating avatar. ';
|
||||
return $e->getMessage();
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] .= 'Error moving the uploaded file. ';
|
||||
$_SESSION['error'] = 'Error moving the uploaded file. Please check directory permissions. ';
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] .= 'Invalid avatar file type. ';
|
||||
$_SESSION['error'] = 'Invalid avatar file type. Only JPG, PNG, and JPEG are allowed. ';
|
||||
}
|
||||
} else {
|
||||
$_SESSION['error'] .= 'Error uploading the avatar file. ';
|
||||
// Handle different upload errors
|
||||
switch ($avatar_file['error']) {
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
$_SESSION['error'] = 'Avatar file is too large. Maximum size is 500KB. ';
|
||||
break;
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
$_SESSION['error'] = 'Avatar file was only partially uploaded. ';
|
||||
break;
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
$_SESSION['error'] = 'No avatar file was uploaded. ';
|
||||
break;
|
||||
case UPLOAD_ERR_NO_TMP_DIR:
|
||||
$_SESSION['error'] = 'Missing temporary folder for file upload. ';
|
||||
break;
|
||||
case UPLOAD_ERR_CANT_WRITE:
|
||||
$_SESSION['error'] = 'Failed to write avatar file to disk. ';
|
||||
break;
|
||||
case UPLOAD_ERR_EXTENSION:
|
||||
$_SESSION['error'] = 'File upload stopped by extension. ';
|
||||
break;
|
||||
default:
|
||||
$_SESSION['error'] = 'Unknown upload error occurred. ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
$_SESSION['error'] = 'An error occurred while processing the avatar: ' . $e->getMessage();
|
||||
return $e->getMessage();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
|
||||
<!-- user profile -->
|
||||
<div class="tm-profile-card mx-auto">
|
||||
<div class="tm-profile-header">
|
||||
<div>
|
||||
<p class="tm-profile-eyebrow">Account</p>
|
||||
<h2 class="tm-profile-title">Profile of <?= htmlspecialchars($userDetails[0]['username']) ?></h2>
|
||||
<p class="tm-profile-subtitle">Update your personal details, avatar, and access rights in one streamlined view.</p>
|
||||
<div class="action-card">
|
||||
<div class="action-card-header">
|
||||
<p class="action-eyebrow">Account</p>
|
||||
<h2 class="action-title">Profile of <?= htmlspecialchars($userDetails[0]['username']) ?></h2>
|
||||
<p class="action-subtitle">Update your personal details, avatar, and access rights in one streamlined view.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?page=profile" enctype="multipart/form-data" class="tm-profile-form" novalidate>
|
||||
<div class="action-card-body">
|
||||
<form method="POST" action="<?= htmlspecialchars($app_root) ?>?page=profile" enctype="multipart/form-data" class="action-form" novalidate>
|
||||
<?php include CSRF_TOKEN_INCLUDE; ?>
|
||||
<div class="row g-4 align-items-start">
|
||||
<div class="col-lg-4">
|
||||
|
|
@ -39,20 +36,25 @@
|
|||
<h3 class="tm-profile-section-title">Personal info</h3>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label for="name" class="form-label">Full name</label>
|
||||
<input class="form-control" type="text" name="name" id="name" value="<?= htmlspecialchars($userDetails[0]['name'] ?? '') ?>" autofocus />
|
||||
<div class="action-form-group">
|
||||
<label for="name" class="action-form-label">Full name</label>
|
||||
<input class="form-control action-form-control" type="text" name="name" id="name" value="<?= htmlspecialchars($userDetails[0]['name'] ?? '') ?>" autofocus />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="email" class="form-label">Email address</label>
|
||||
<input class="form-control" type="text" name="email" id="email" value="<?= htmlspecialchars($userDetails[0]['email'] ?? '') ?>" />
|
||||
<div class="action-form-group">
|
||||
<label for="email" class="action-form-label">Email address</label>
|
||||
<input class="form-control action-form-control" type="text" name="email" id="email" value="<?= htmlspecialchars($userDetails[0]['email'] ?? '') ?>" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tm-profile-section">
|
||||
<h3 class="tm-profile-section-title">Timezone</h3>
|
||||
<label for="timezone" class="form-label">Preferred timezone</label>
|
||||
<select class="form-control" name="timezone" id="timezone">
|
||||
<div class="action-form-group">
|
||||
<label for="timezone" class="action-form-label">Preferred timezone</label>
|
||||
<select class="form-control action-form-control" name="timezone" id="timezone">
|
||||
<?php foreach ($allTimezones as $timezone) { ?>
|
||||
<option value="<?= htmlspecialchars($timezone) ?>" <?= $timezone === $userTimezone ? 'selected' : '' ?>>
|
||||
<?= htmlspecialchars($timezone) ?> (<?= htmlspecialchars(getUTCOffset($timezone)) ?>)
|
||||
|
|
@ -60,10 +62,13 @@
|
|||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tm-profile-section">
|
||||
<h3 class="tm-profile-section-title">Bio</h3>
|
||||
<textarea class="form-control" name="bio" rows="6" placeholder="Share something about yourself, your role, or preferences."><?= htmlspecialchars($userDetails[0]['bio'] ?? '') ?></textarea>
|
||||
<div class="action-form-group">
|
||||
<textarea class="form-control action-form-control" name="bio" rows="6" placeholder="Share something about yourself, your role, or preferences."><?= htmlspecialchars($userDetails[0]['bio'] ?? '') ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tm-profile-section">
|
||||
|
|
@ -86,9 +91,9 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tm-profile-actions">
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=profile" class="btn btn-light tm-contact-back">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary tm-contact-submit">Save changes</button>
|
||||
<div class="action-actions">
|
||||
<a href="<?= htmlspecialchars($app_root) ?>?page=profile" class="btn btn-light">Cancel</a>
|
||||
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -116,11 +121,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /user profile -->
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Preview the uploaded avatar
|
||||
document.getElementById('avatar-upload').addEventListener('change', function(event) {
|
||||
const reader = new FileReader();
|
||||
|
|
@ -151,6 +157,7 @@ document.getElementById('confirm-delete').addEventListener('click', function(eve
|
|||
event.preventDefault(); // Prevent the outer form from submitting
|
||||
document.getElementById('remove-avatar-form').submit();
|
||||
});
|
||||
});
|
||||
|
||||
// Function to detect user's timezone and select it in the dropdown
|
||||
function setTimezone() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue