Skip to content

Commit

Permalink
feat(update): added possibility to activate maintenance mode in onlin…
Browse files Browse the repository at this point in the history
…e update, closes #3321
  • Loading branch information
thorsten committed Jan 12, 2025
1 parent 29195fb commit d9a0290
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This is a log of major user-visible changes in each phpMyFAQ release.
- added configuration to edit robots.txt (Thorsten)
- added Symfony Routing for administration backend (Thorsten)
- added code snippets plugin with syntax highlighting in WYSIWYG editor (Thorsten)
- improved online update feature (Thorsten)
- migrated from WYSIWYG editor from TinyMCE to Jodit Editor (Thorsten)
- migrated from Webpack to Vite v6 (Thorsten)
- migrated from Jest to vitest (Thorsten)
Expand Down
42 changes: 39 additions & 3 deletions phpmyfaq/admin/assets/src/configuration/upgrade.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const handleCheckForUpdates = () => {
const downloadButton = document.getElementById('pmf-button-download-now');
const extractButton = document.getElementById('pmf-button-extract-package');
const installButton = document.getElementById('pmf-button-install-package');
const buttonActivate = document.getElementById('pmf-button-activate-maintenance-mode');

// Health Check
if (checkHealthButton) {
Expand All @@ -35,15 +36,16 @@ export const handleCheckForUpdates = () => {

if (responseData.success) {
card.classList.add('text-bg-success');
result.replaceWith(addElement('p', { innerText: responseData.success }));
result.replaceWith(addElement('p', { id: 'result-check-health', innerText: responseData.success }));
}
if (responseData.warning) {
card.classList.add('text-bg-warning');
result.replaceWith(addElement('p', { innerText: responseData.warning }));
result.replaceWith(addElement('p', { id: 'result-check-health', innerText: responseData.warning }));
buttonActivate.classList.remove('d-none');
}
if (responseData.error) {
card.classList.add('text-bg-danger');
result.replaceWith(addElement('p', { innerText: responseData.error }));
result.replaceWith(addElement('p', { id: 'result-check-health', innerText: responseData.error }));
}
} catch (error) {
if (error.cause && error.cause.response) {
Expand All @@ -56,6 +58,40 @@ export const handleCheckForUpdates = () => {
});
}

// Activate Maintenance Mode
if (buttonActivate) {
buttonActivate.addEventListener('click', async (event) => {
event.preventDefault();
try {
const response = await fetch('./api/configuration/activate-maintenance-mode', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json',
},
body: JSON.stringify({ csrf: buttonActivate.getAttribute('data-pmf-csrf') }),
});

if (!response.ok) {
throw new Error('Network response was not ok');
}

const responseData = await response.json();
const result = document.getElementById('result-check-health');
const card = document.getElementById('pmf-update-step-health-check');

if (responseData.success) {
card.classList.remove('text-bg-warning');
card.classList.add('text-bg-success');
result.replaceWith(addElement('p', { innerText: responseData.success }));
buttonActivate.classList.add('d-none');
}
} catch (error) {
console.error(error);
}
});
}

// Check Update
if (checkUpdateButton) {
checkUpdateButton.addEventListener('click', async (event) => {
Expand Down
7 changes: 7 additions & 0 deletions phpmyfaq/assets/templates/admin/configuration/upgrade.twig
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
<p class="card-text">
{{ 'msgHealthCheck' | translate }}
</p>
<!-- Step 0: provide activation of maintenance mode -->
<div class="d-grid gap-2 d-md-flex justify-content-between">
<button type="button" class="btn btn-secondary mb-2 d-none" id="pmf-button-activate-maintenance-mode"
data-pmf-csrf="{{ csrfActivateMaintenanceMode }}">
{{ 'msgActivateMaintenanceMode' | translate }}
</button>
</div>
<!-- Step 1: Check for system health -->
<div class="d-grid gap-2 d-md-flex justify-content-between">
<button type="button" class="btn btn-primary mb-2" id="pmf-button-check-health">
Expand Down
5 changes: 5 additions & 0 deletions phpmyfaq/src/admin-api-routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@
'methods' => 'DELETE'
],
// Configuration API
'admin.api.configuration.activate-maintenance-mode' => [
'path' => '/configuration/activate-maintenance-mode',
'controller' => [ConfigurationController::class, 'activateMaintenanceMode'],
'methods' => 'POST'
],
'admin.api.configuration.faqs-sorting-key' => [
'path' => '/configuration/faqs-sorting-key/{current}',
'controller' => [ConfigurationTabController::class, 'faqsSortingKey'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
class ConfigurationController extends AbstractController
{
/**
* @throws Exception
* @throws Exception|\Exception
*/
#[Route('admin/api/configuration/send-test-mail')]
public function sendTestMail(Request $request): JsonResponse
Expand All @@ -58,4 +58,25 @@ public function sendTestMail(Request $request): JsonResponse
return $this->json(['error' => $e->getMessage()], Response::HTTP_BAD_REQUEST);
}
}

/**
* @throws \Exception
*/
#[Route('admin/api/configuration/activate-maintenance-mode')]
public function activateMaintenanceMode(Request $request): JsonResponse
{
$this->userHasPermission(PermissionType::CONFIGURATION_EDIT);

$session = $this->container->get('session');

$data = json_decode($request->getContent());

if (!Token::getInstance($session)->verifyToken('activate-maintenance-mode', $data->csrf)) {
return $this->json(['error' => Translation::get('msgNoPermission')], Response::HTTP_UNAUTHORIZED);
}

$this->configuration->set('main.maintenanceMode', 'true');

return $this->json(['success' => Translation::get('healthCheckOkay')], Response::HTTP_OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use phpMyFAQ\Core\Exception;
use phpMyFAQ\Enums\PermissionType;
use phpMyFAQ\Enums\ReleaseType;
use phpMyFAQ\Session\Token;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
Expand All @@ -39,13 +40,17 @@ public function index(Request $request): Response
{
$this->userHasPermission(PermissionType::CONFIGURATION_EDIT);

$session = $this->container->get('session');

$isOnNightlies = $this->configuration->get('upgrade.releaseEnvironment') === ReleaseType::NIGHTLY->value;

return $this->render(
'@admin/configuration/upgrade.twig',
[
... $this->getHeader($request),
... $this->getFooter(),
'csrfActivateMaintenanceMode' => Token::getInstance($session)
->getTokenString('activate-maintenance-mode'),
'isOnNightlies' => $isOnNightlies,
'releaseEnvironment' => ucfirst((string) $this->configuration->get('upgrade.releaseEnvironment')),
'dateLastChecked' => $this->configuration->get('upgrade.dateLastChecked'),
Expand Down
1 change: 1 addition & 0 deletions phpmyfaq/translations/language_de.php
Original file line number Diff line number Diff line change
Expand Up @@ -1456,5 +1456,6 @@

// added v4.1.0-alpha - 2024-11-17 by Thorsten
$LANG_CONF['seo.contentRobotsText'] = ['area', 'Inhalt für die robots.txt', ''];
$PMF_LANG['msgActivateMaintenanceMode'] = 'Wartungs-Modus aktivieren';

return $PMF_LANG;
1 change: 1 addition & 0 deletions phpmyfaq/translations/language_en.php
Original file line number Diff line number Diff line change
Expand Up @@ -1476,5 +1476,6 @@

// added v4.1.0-alpha - 2024-11-17 by Thorsten
$LANG_CONF['seo.contentRobotsText'] = ['area', 'Content for robots.txt', ''];
$PMF_LANG['msgActivateMaintenanceMode'] = 'Activate maintenance mode';

return $PMF_LANG;

0 comments on commit d9a0290

Please sign in to comment.