Enhances messages system with JS-based messages

main
Yasen Pramatarov 2025-01-23 14:06:36 +02:00
parent ffe08f913b
commit 752f519ccc
4 changed files with 79 additions and 28 deletions

View File

@ -18,6 +18,13 @@ $configObject = new Config();
$isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest';
// Check if file is writable
$isWritable = is_writable($config_file);
$configMessage = '';
if (!$isWritable) {
$configMessage = Messages::render('ERROR', 'DEFAULT', 'Config file is not writable', false);
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// Ensure no output before this point
ob_clean();
@ -39,16 +46,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
exit;
}
// Check if file is writable
if (!is_writable($config_file)) {
Messages::flash('ERROR', 'DEFAULT', 'Config file is not writable', true);
echo json_encode([
'success' => false,
'message' => 'Config file is not writable'
]);
exit;
}
// Try to update config file
$result = $configObject->editConfigFile($postData, $config_file);
if ($result === true) {
@ -70,15 +67,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
// Handle non-AJAX POST
if (!is_writable($config_file)) {
Messages::flash('ERROR', 'DEFAULT', 'Config file is not writable', true);
$result = $configObject->editConfigFile($_POST, $config_file);
if ($result === true) {
Messages::flash('NOTICE', 'DEFAULT', 'Config file updated successfully', true);
} else {
$result = $configObject->editConfigFile($_POST, $config_file);
if ($result === true) {
Messages::flash('NOTICE', 'DEFAULT', 'Config file updated successfully', true);
} else {
Messages::flash('ERROR', 'DEFAULT', "Error updating config file: $result", true);
}
Messages::flash('ERROR', 'DEFAULT', "Error updating config file: $result", true);
}
header('Location: ' . htmlspecialchars($app_root) . '?page=config');

View File

@ -5,6 +5,9 @@
<div class="row mb-4">
<div class="col-12 mb-4">
<h2>Configuration</h2>
<?php if ($configMessage): ?>
<?= $configMessage ?>
<?php endif; ?>
</div>
</div>
@ -16,7 +19,7 @@
</h5>
<?php if ($userObject->hasRight($user_id, 'edit config file')): ?>
<div>
<button type="button" class="btn btn-outline-primary btn-sm toggle-edit">
<button type="button" class="btn btn-outline-primary btn-sm toggle-edit" <?= !$isWritable ? 'disabled' : '' ?>>
<i class="fas fa-edit me-2"></i>Edit
</button>
<div class="edit-controls d-none">
@ -109,7 +112,7 @@
<script>
$(function() {
function showMessage(messageData) {
const dismissClass = messageData.dismissible ? ' alert-dismissible fade show' : '';
const dismissClass = messageData.dismissible ? ' alert-dismissible fade' : '';
const dismissButton = messageData.dismissible ?
`<button type="button" class="btn-close${messageData.small ? ' btn-close-sm' : ''}" data-bs-dismiss="alert" aria-label="Close"></button>` : '';
const smallClass = messageData.small ? ' alert-sm' : '';
@ -119,12 +122,22 @@ $(function() {
.attr('role', 'alert')
.html(`${messageData.message}${dismissButton}`);
$('#messages-container').html($alert);
// Remove any existing alerts
$('#messages-container').empty().append($alert);
// Trigger reflow to ensure transition works
$alert[0].offsetHeight;
// Show the alert with transition
$alert.addClass('show');
if (messageData.dismissible) {
setTimeout(() => {
$alert.alert('close');
}, 5000);
$alert.removeClass('show');
setTimeout(() => {
$alert.remove();
}, 200); // Same as transition duration
}, 1500);
}
}
@ -179,6 +192,12 @@ $(function() {
})
.then(response => response.json())
.then(response => {
// Show message first
if (response.messageData) {
showMessage(response.messageData);
}
// Only update UI if save was successful
if (response.success) {
// Update view mode values
Object.entries(data).forEach(([key, value]) => {
@ -219,11 +238,6 @@ $(function() {
$('.edit-mode').addClass('d-none');
}
// Show message
if (response.messageData) {
showMessage(response.messageData);
}
$btn.prop('disabled', false).html('<i class="fas fa-save me-2"></i>Save');
})
.catch(error => {

View File

@ -4,6 +4,7 @@
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/bootstrap/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/main.css">
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/messages.css">
<?php if ($page === 'logs') { ?>
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/logs.css">
<?php } ?>

View File

@ -0,0 +1,43 @@
#messages-container {
position: fixed;
top: 40px;
left: 50%;
transform: translateX(-50%);
z-index: 1050;
width: auto;
min-width: 300px;
max-width: 600px;
}
#messages-container .alert {
margin-bottom: 0;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
background-color: rgba(var(--bs-light-rgb), 0.95);
border: 1px solid rgba(0, 0, 0, 0.1);
opacity: 0;
transform: translateY(-20px);
transition: all 0.2s ease-out;
}
#messages-container .alert.show {
opacity: 1;
transform: translateY(0);
}
#messages-container .alert-success {
background-color: rgba(var(--bs-success-rgb), 0.95);
color: white;
}
#messages-container .alert-danger {
background-color: rgba(var(--bs-danger-rgb), 0.95);
color: white;
}
#messages-container .alert-info {
background-color: rgba(var(--bs-info-rgb), 0.95);
}
#messages-container .alert-warning {
background-color: rgba(var(--bs-warning-rgb), 0.95);
}