Fixes config editing JS messages
parent
4a8185839d
commit
828020d689
|
@ -35,13 +35,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
|
||||||
// Get raw input
|
// Get raw input
|
||||||
$jsonData = file_get_contents('php://input');
|
$jsonData = file_get_contents('php://input');
|
||||||
|
//DEBUG error_log("Received JSON data: " . $jsonData);
|
||||||
|
|
||||||
$postData = json_decode($jsonData, true);
|
$postData = json_decode($jsonData, true);
|
||||||
|
|
||||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||||
Messages::flash('ERROR', 'DEFAULT', 'Invalid JSON data received', true);
|
$error = json_last_error_msg();
|
||||||
|
//DEBUG error_log("JSON decode error: " . $error);
|
||||||
|
|
||||||
|
Messages::flash('ERROR', 'DEFAULT', 'Invalid JSON data received: ' . $error, true);
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
'message' => 'Invalid JSON data received'
|
'message' => 'Invalid JSON data received: ' . $error
|
||||||
]);
|
]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
@ -50,12 +55,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
$result = $configObject->editConfigFile($postData, $config_file);
|
$result = $configObject->editConfigFile($postData, $config_file);
|
||||||
if ($result === true) {
|
if ($result === true) {
|
||||||
$messageData = Messages::getMessageData('NOTICE', 'DEFAULT', 'Config file updated successfully', true);
|
$messageData = Messages::getMessageData('NOTICE', 'DEFAULT', 'Config file updated successfully', true);
|
||||||
|
//DEBUG error_log("Config updated successfully");
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => true,
|
'success' => true,
|
||||||
'message' => 'Config file updated successfully',
|
'message' => 'Config file updated successfully',
|
||||||
'messageData' => $messageData
|
'messageData' => $messageData
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
|
//DEBUG error_log("Config update error: " . $result);
|
||||||
$messageData = Messages::getMessageData('ERROR', 'DEFAULT', "Error updating config file: $result", true);
|
$messageData = Messages::getMessageData('ERROR', 'DEFAULT', "Error updating config file: $result", true);
|
||||||
echo json_encode([
|
echo json_encode([
|
||||||
'success' => false,
|
'success' => false,
|
||||||
|
|
|
@ -1,39 +1,42 @@
|
||||||
|
|
||||||
<!-- config file -->
|
<!-- config file -->
|
||||||
<div class="container-fluid mt-2">
|
<div class="container-fluid mt-2">
|
||||||
|
<div id="messages-container"></div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
<div class="col-12 mb-5">
|
<div class="col-12 mb-4">
|
||||||
<h2>Configuration</h2>
|
<h2>Configuration</h2>
|
||||||
<?php if ($configMessage): ?>
|
<small>Jilo Web configuration file <?= htmlspecialchars($config_file) ?></small>
|
||||||
|
<?php if ($configMessage) { ?>
|
||||||
<?= $configMessage ?>
|
<?= $configMessage ?>
|
||||||
<?php endif; ?>
|
<?php } ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card shadow-sm">
|
||||||
|
<div class="card-header bg-light d-flex justify-content-between align-items-center py-3">
|
||||||
|
<h5 class="card-title mb-0">
|
||||||
|
<i class="fas fa-wrench me-2 text-secondary"></i>
|
||||||
|
Jilo Web app configuration
|
||||||
|
</h5>
|
||||||
|
<?php if ($userObject->hasRight($user_id, 'edit config file')) { ?>
|
||||||
|
<div>
|
||||||
|
<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">
|
||||||
|
<button type="button" class="btn btn-danger btn-sm save-config">
|
||||||
|
<i class="fas fa-save me-2"></i>Save
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-outline-secondary btn-sm ms-2 cancel-edit">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="card shadow-sm">
|
<div class="card-body p-4">
|
||||||
<div class="card-header bg-light d-flex justify-content-between align-items-center py-3">
|
<form id="configForm">
|
||||||
<h5 class="card-title mb-0">
|
|
||||||
<i class="fas fa-wrench me-2 text-secondary"></i>
|
|
||||||
Jilo Web app configuration
|
|
||||||
</h5>
|
|
||||||
<?php if ($userObject->hasRight($user_id, 'edit config file')) { ?>
|
|
||||||
<div>
|
|
||||||
<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">
|
|
||||||
<button type="button" class="btn btn-danger btn-sm save-config">
|
|
||||||
<i class="fas fa-save me-2"></i>Save
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-outline-secondary btn-sm ms-2 cancel-edit">
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<?php } ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="card-body p-4">
|
|
||||||
<form id="configForm">
|
|
||||||
<?php
|
<?php
|
||||||
function renderConfigItem($key, $value, $path = '') {
|
function renderConfigItem($key, $value, $path = '') {
|
||||||
$fullPath = $path ? $path . '[' . $key . ']' : $key;
|
$fullPath = $path ? $path . '[' . $key . ']' : $key;
|
||||||
|
@ -41,61 +44,60 @@ function renderConfigItem($key, $value, $path = '') {
|
||||||
$displayName = ucfirst(str_replace('_', ' ', $key));
|
$displayName = ucfirst(str_replace('_', ' ', $key));
|
||||||
|
|
||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
echo "\t\t\t\t\t\t\t\t\t<div class=\"config-section mb-4\">";
|
echo "\t\t\t\t\t\t\t\t<div class=\"config-section mb-4\">";
|
||||||
echo "\n\t\t\t\t\t\t\t\t\t\t<h6 class=\"border-bottom pb-2 mb-3\">" . htmlspecialchars($displayName) . '</h6>';
|
echo "\n\t\t\t\t\t\t\t\t\t<h6 class=\"border-bottom pb-2 mb-3\">" . htmlspecialchars($displayName) . '</h6>';
|
||||||
echo "\n\t\t\t\t\t\t\t\t\t\t<div class=\"ps-4\">\n";
|
echo "\n\t\t\t\t\t\t\t\t\t<div class=\"ps-4\">\n";
|
||||||
foreach ($value as $subKey => $subValue) {
|
foreach ($value as $subKey => $subValue) {
|
||||||
renderConfigItem($subKey, $subValue, $fullPath);
|
renderConfigItem($subKey, $subValue, $fullPath);
|
||||||
}
|
}
|
||||||
echo "\t\t\t\t\t\t\t\t\t\t</div>\n";
|
|
||||||
echo "\t\t\t\t\t\t\t\t\t</div>\n";
|
echo "\t\t\t\t\t\t\t\t\t</div>\n";
|
||||||
|
echo "\t\t\t\t\t\t\t\t</div>\n";
|
||||||
} else {
|
} else {
|
||||||
?>
|
?>
|
||||||
<div class="config-item row mb-3 align-items-center">
|
<div class="config-item row mb-3 align-items-center">
|
||||||
<div class="col-md-4 text-end">
|
<div class="col-md-4 text-end">
|
||||||
<label class="form-label mb-0"><?= htmlspecialchars($displayName) ?></label>
|
<label class="form-label mb-0"><?= htmlspecialchars($displayName) ?></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<div class="view-mode">
|
<div class="view-mode">
|
||||||
<?php if (is_bool($value) || $key === 'registration_enabled') { ?>
|
<?php if (is_bool($value) || $key === 'registration_enabled') { ?>
|
||||||
<span class="badge <?= $value ? 'bg-success' : 'bg-secondary' ?>"><?= $value ? 'Enabled' : 'Disabled' ?></span>
|
<span class="badge <?= $value ? 'bg-success' : 'bg-secondary' ?>"><?= $value ? 'Enabled' : 'Disabled' ?></span>
|
||||||
<?php } elseif ($key === 'environment') { ?>
|
<?php } elseif ($key === 'environment') { ?>
|
||||||
<span class="badge <?= $value === 'production' ? 'bg-danger' : 'bg-info' ?>"><?= htmlspecialchars($value) ?></span>
|
<span class="badge <?= $value === 'production' ? 'bg-danger' : 'bg-info' ?>"><?= htmlspecialchars($value) ?></span>
|
||||||
<?php } else {
|
<?php } else {
|
||||||
if (empty($value) && $value !== '0') { ?>
|
if (empty($value) && $value !== '0') { ?>
|
||||||
<span class="text-muted fst-italic">blank</span>
|
<span class="text-muted fst-italic">blank</span>
|
||||||
<?php } else { ?>
|
<?php } else { ?>
|
||||||
<span class="text-body"><?= htmlspecialchars($value) ?></span>
|
<span class="text-body"><?= htmlspecialchars($value) ?></span>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
<div class="edit-mode d-none">
|
<div class="edit-mode d-none">
|
||||||
<?php if (is_bool($value) || $key === 'registration_enabled') { ?>
|
<?php if (is_bool($value) || $key === 'registration_enabled') { ?>
|
||||||
<div class="form-check form-switch">
|
<div class="form-check form-switch">
|
||||||
<input class="form-check-input" type="checkbox" name="<?= htmlspecialchars($fullPath) ?>" <?= $value ? 'checked' : '' ?>>
|
<input class="form-check-input" type="checkbox" name="<?= htmlspecialchars($fullPath) ?>" <?= $value ? 'checked' : '' ?>>
|
||||||
</div>
|
|
||||||
<?php } elseif ($key === 'environment') { ?>
|
|
||||||
<select class="form-select form-select-sm" name="<?= htmlspecialchars($fullPath) ?>">
|
|
||||||
<option value="development" <?= $value === 'development' ? 'selected' : '' ?>>Development</option>
|
|
||||||
<option value="production" <?= $value === 'production' ? 'selected' : '' ?>>Production</option>
|
|
||||||
</select>
|
|
||||||
<?php } else { ?>
|
|
||||||
<input type="text" class="form-control form-control-sm" name="<?= htmlspecialchars($fullPath) ?>" value="<?= htmlspecialchars($value ?? '') ?>">
|
|
||||||
<?php } ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
<?php } elseif ($key === 'environment') { ?>
|
||||||
|
<select class="form-select form-select-sm" name="<?= htmlspecialchars($fullPath) ?>">
|
||||||
|
<option value="development" <?= $value === 'development' ? 'selected' : '' ?>>Development</option>
|
||||||
|
<option value="production" <?= $value === 'production' ? 'selected' : '' ?>>Production</option>
|
||||||
|
</select>
|
||||||
|
<?php } else { ?>
|
||||||
|
<input type="text" class="form-control form-control-sm" name="<?= htmlspecialchars($fullPath) ?>" value="<?= htmlspecialchars($value ?? '') ?>">
|
||||||
|
<?php } ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<?php }
|
<?php }
|
||||||
}
|
}
|
||||||
foreach ($config as $key => $value) {
|
foreach ($config as $key => $value) {
|
||||||
renderConfigItem($key, $value);
|
renderConfigItem($key, $value);
|
||||||
} ?>
|
} ?>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- /config file -->
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$(function() {
|
$(function() {
|
||||||
|
@ -170,72 +172,74 @@ $(function() {
|
||||||
data[name] = $(this).val();
|
data[name] = $(this).val();
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch('<?= htmlspecialchars($app_root) ?>?page=config', {
|
$.ajax({
|
||||||
|
url: '<?= htmlspecialchars($app_root) ?>?page=config',
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
contentType: 'application/json',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-Requested-With': 'XMLHttpRequest'
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
},
|
},
|
||||||
body: JSON.stringify(data)
|
success: function(response) {
|
||||||
})
|
//DEBUG console.log('Response:', response);
|
||||||
.then(response => response.json())
|
// Show message first
|
||||||
.then(response => {
|
if (response.messageData) {
|
||||||
// Show message first
|
showMessage(response.messageData);
|
||||||
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]) => {
|
||||||
|
const $item = $(`[name="${key}"]`).closest('.config-item');
|
||||||
|
const $viewMode = $item.find('.view-mode');
|
||||||
|
|
||||||
// Only update UI if save was successful
|
if ($item.length) {
|
||||||
if (response.success) {
|
if ($item.find('input[type="checkbox"]').length) {
|
||||||
// Update view mode values
|
// Boolean value
|
||||||
Object.entries(data).forEach(([key, value]) => {
|
const isEnabled = value === '1';
|
||||||
const $item = $(`[name="${key}"]`).closest('.config-item');
|
$viewMode.html(`
|
||||||
const $viewMode = $item.find('.view-mode');
|
<span class="badge ${isEnabled ? 'bg-success' : 'bg-secondary'}">
|
||||||
|
${isEnabled ? 'Enabled' : 'Disabled'}
|
||||||
if ($item.length) {
|
</span>
|
||||||
if ($item.find('input[type="checkbox"]').length) {
|
`);
|
||||||
// Boolean value
|
} else if ($item.find('select').length) {
|
||||||
const isEnabled = value === '1';
|
// Environment value
|
||||||
$viewMode.html(`
|
$viewMode.html(`
|
||||||
<span class="badge ${isEnabled ? 'bg-success' : 'bg-secondary'}">
|
<span class="badge ${value === 'production' ? 'bg-danger' : 'bg-info'}">
|
||||||
${isEnabled ? 'Enabled' : 'Disabled'}
|
${value}
|
||||||
</span>
|
</span>
|
||||||
`);
|
`);
|
||||||
} else if ($item.find('select').length) {
|
|
||||||
// Environment value
|
|
||||||
$viewMode.html(`
|
|
||||||
<span class="badge ${value === 'production' ? 'bg-danger' : 'bg-info'}">
|
|
||||||
${value}
|
|
||||||
</span>
|
|
||||||
`);
|
|
||||||
} else {
|
|
||||||
// Text value
|
|
||||||
if (value === '') {
|
|
||||||
$viewMode.html('<span class="text-muted fst-italic">blank</span>');
|
|
||||||
} else {
|
} else {
|
||||||
$viewMode.html(`<span class="text-body">${value}</span>`);
|
// Text value
|
||||||
|
if (value === '') {
|
||||||
|
$viewMode.html('<span class="text-muted fst-italic">blank</span>');
|
||||||
|
} else {
|
||||||
|
$viewMode.html(`<span class="text-body">${value}</span>`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
// Finally, exit edit mode
|
||||||
|
$('.toggle-edit').show();
|
||||||
|
$('.edit-controls').addClass('d-none');
|
||||||
|
$('.view-mode').show();
|
||||||
|
$('.edit-mode').addClass('d-none');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, error) {
|
||||||
|
//DEBUG console.error('AJAX Error:', status, error);
|
||||||
|
//DEBUG console.error('Response:', xhr.responseText);
|
||||||
|
showMessage({
|
||||||
|
type: 'danger',
|
||||||
|
message: 'Error saving config: ' + error,
|
||||||
|
dismissible: true
|
||||||
});
|
});
|
||||||
|
},
|
||||||
// Exit edit mode
|
complete: function() {
|
||||||
$('.toggle-edit').show();
|
$btn.prop('disabled', false).html('<i class="fas fa-save me-2"></i>Save');
|
||||||
$('.edit-controls').addClass('d-none');
|
|
||||||
$('.view-mode').show();
|
|
||||||
$('.edit-mode').addClass('d-none');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$btn.prop('disabled', false).html('<i class="fas fa-save me-2"></i>Save');
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
showMessage({
|
|
||||||
type: 'danger',
|
|
||||||
message: 'Error saving config: ' + error,
|
|
||||||
dismissible: true
|
|
||||||
});
|
|
||||||
$btn.prop('disabled', false).html('<i class="fas fa-save me-2"></i>Save');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<!-- /config file -->
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
<?php if ($page === 'profile') { ?>
|
<?php if ($page === 'profile') { ?>
|
||||||
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/profile.css">
|
<link rel="stylesheet" type="text/css" href="<?= htmlspecialchars($app_root) ?>static/css/profile.css">
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">
|
||||||
|
@ -49,4 +49,3 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
Loading…
Reference in New Issue