Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW UI] Add restore choice dialogs #1108

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions _dev/src/ts/dialogs/DeleteBackupDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import DomLifecycle from '../types/DomLifecycle';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The question is a bit late, but why don't we also have the Header Stamp on the TS ? In the CORE project we have it https://github.com/PrestaShop/PrestaShop/blob/f4fab23ece8957b7dcf852f16bc49dd8c621aaac/js/admin/attachments.js#L1-L0

import api from '../api/RequestHandler';

export default class DeleteBackupDialog implements DomLifecycle {
protected readonly formId = 'backup_to_delete';

public mount = (): void => {
this.#form.addEventListener('submit', this.#onSubmit);
};

public beforeDestroy = (): void => {
this.#form.removeEventListener('submit', this.#onSubmit);
};

get #form(): HTMLFormElement {
const form = document.forms.namedItem(this.formId);
if (!form) {
throw new Error('Form not found');
}
if (!form.dataset.routeToConfirmDelete) {
throw new Error(`Missing data route to confirm delete from form dataset.`);
}

return form;
}

#onSubmit = async (event: SubmitEvent): Promise<void> => {
event.preventDefault();

const form = event.target as HTMLFormElement;

await api.post(form.dataset.routeToConfirmDelete!, new FormData(this.#form));
};
}
34 changes: 34 additions & 0 deletions _dev/src/ts/dialogs/RestoreBackupDialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import DomLifecycle from '../types/DomLifecycle';
import api from '../api/RequestHandler';

export default class RestoreBackupDialog implements DomLifecycle {
protected readonly formId = 'backup_to_restore';

public mount = (): void => {
this.#form.addEventListener('submit', this.#onSubmit);
};

public beforeDestroy = (): void => {
this.#form.removeEventListener('submit', this.#onSubmit);
};

get #form(): HTMLFormElement {
const form = document.forms.namedItem(this.formId);
if (!form) {
throw new Error('Form not found');
}
if (!form.dataset.routeToConfirmRestore) {
throw new Error(`Missing data route to confirm restore from form dataset.`);
}

return form;
}

#onSubmit = async (event: SubmitEvent): Promise<void> => {
event.preventDefault();

const form = event.target as HTMLFormElement;

await api.post(form.dataset.routeToConfirmRestore!, new FormData(this.#form));
};
}
4 changes: 2 additions & 2 deletions _dev/src/ts/pages/RestorePageBackupSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ export default class RestorePageBackupSelection extends StepPage {
let routeToSubmit: string | undefined;

if ((event.submitter as HTMLButtonElement)?.value === 'delete') {
routeToSubmit = this.#form.dataset.routeToDelete;
routeToSubmit = this.#form.dataset.routeToSubmitDelete;
} else {
routeToSubmit = this.#form.dataset.routeToSubmit;
routeToSubmit = this.#form.dataset.routeToSubmitRestore;
}

if (!routeToSubmit) {
Expand Down
4 changes: 4 additions & 0 deletions _dev/src/ts/routing/ScriptHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import RestorePageBackupSelection from '../pages/RestorePageBackupSelection';
import RestorePageRestore from '../pages/RestorePageRestore';
import RestorePagePostRestore from '../pages/RestorePagePostRestore';

import RestoreBackupDialog from '../dialogs/RestoreBackupDialog';
import DeleteBackupDialog from '../dialogs/DeleteBackupDialog';
import StartUpdateDialog from '../dialogs/StartUpdateDialog';
import SendErrorReportDialog from '../dialogs/SendErrorReportDialog';

Expand Down Expand Up @@ -38,6 +40,8 @@ export default class ScriptHandler {
'restore-page-restore': RestorePageRestore,
'restore-page-post-restore': RestorePagePostRestore,

'restore-backup-dialog': RestoreBackupDialog,
'delete-backup-dialog': DeleteBackupDialog,
'start-update-dialog': StartUpdateDialog,
'send-error-report-dialog': SendErrorReportDialog
};
Expand Down
16 changes: 12 additions & 4 deletions classes/Router/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,21 @@ public function __construct(UpgradeContainer $upgradeContainer)
'controller' => RestorePageBackupSelectionController::class,
'method' => 'save',
],
Routes::RESTORE_STEP_BACKUP_SELECTION_SUBMIT_FORM => [
Routes::RESTORE_STEP_BACKUP_SELECTION_SUBMIT_RESTORE_FORM => [
'controller' => RestorePageBackupSelectionController::class,
'method' => 'submit',
'method' => 'submitRestore',
],
Routes::RESTORE_STEP_BACKUP_SELECTION_CONFIRM_RESTORE_FORM => [
'controller' => RestorePageBackupSelectionController::class,
'method' => 'startRestore',
],
Routes::RESTORE_STEP_BACKUP_SELECTION_SUBMIT_DELETE_FORM => [
'controller' => RestorePageBackupSelectionController::class,
'method' => 'submitDelete',
],
Routes::RESTORE_STEP_BACKUP_SELECTION_DELETE_FORM => [
Routes::RESTORE_STEP_BACKUP_SELECTION_CONFIRM_DELETE_FORM => [
'controller' => RestorePageBackupSelectionController::class,
'method' => 'delete',
'method' => 'confirmDelete',
],
/* step: restore */
Routes::RESTORE_PAGE_RESTORE => [
Expand Down
6 changes: 4 additions & 2 deletions classes/Router/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ class Routes
const RESTORE_PAGE_BACKUP_SELECTION = 'restore-page-backup-selection';
const RESTORE_STEP_BACKUP_SELECTION = 'restore-step-backup-selection';
const RESTORE_STEP_BACKUP_SELECTION_SAVE_FORM = 'restore-step-backup-selection-save-form';
const RESTORE_STEP_BACKUP_SELECTION_SUBMIT_FORM = 'restore-step-backup-selection-submit-form';
const RESTORE_STEP_BACKUP_SELECTION_DELETE_FORM = 'restore-step-backup-selection-delete-form';
const RESTORE_STEP_BACKUP_SELECTION_CONFIRM_RESTORE_FORM = 'restore-step-backup-selection-confirm-restore-form';
const RESTORE_STEP_BACKUP_SELECTION_SUBMIT_RESTORE_FORM = 'restore-step-backup-selection-submit-restore-form';
const RESTORE_STEP_BACKUP_SELECTION_CONFIRM_DELETE_FORM = 'restore-step-backup-selection-confirm-delete-form';
const RESTORE_STEP_BACKUP_SELECTION_SUBMIT_DELETE_FORM = 'restore-step-backup-selection-submit-delete-form';

/* step: restore */
const RESTORE_PAGE_RESTORE = 'restore-page-restore';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
namespace PrestaShop\Module\AutoUpgrade\Controller;

use PrestaShop\Module\AutoUpgrade\AjaxResponseBuilder;
use PrestaShop\Module\AutoUpgrade\Exceptions\BackupException;
use PrestaShop\Module\AutoUpgrade\Parameters\RestoreConfiguration;
use PrestaShop\Module\AutoUpgrade\Parameters\UpgradeFileNames;
use PrestaShop\Module\AutoUpgrade\Router\Routes;
use PrestaShop\Module\AutoUpgrade\Task\TaskType;
use PrestaShop\Module\AutoUpgrade\Twig\PageSelectors;
use PrestaShop\Module\AutoUpgrade\Twig\Steps\RestoreSteps;
use PrestaShop\Module\AutoUpgrade\Twig\Steps\Stepper;
use Symfony\Component\HttpFoundation\JsonResponse;
Expand All @@ -15,6 +17,8 @@ class RestorePageBackupSelectionController extends AbstractPageWithStepControlle
{
const CURRENT_STEP = RestoreSteps::STEP_BACKUP_SELECTION;
const FORM_NAME = 'backup_choice';
const DELETE_BACKUP_FORM_NAME = 'backup_to_delete';
const RESTORE_BACKUP_FORM_NAME = 'backup_to_restore';
const FORM_FIELDS = [
RestoreConfiguration::BACKUP_NAME => RestoreConfiguration::BACKUP_NAME,
];
Expand Down Expand Up @@ -65,16 +69,50 @@ protected function getParams(): array
[
'form_backup_selection_name' => self::FORM_NAME,
'form_route_to_save' => Routes::RESTORE_STEP_BACKUP_SELECTION_SAVE_FORM,
'form_route_to_submit' => Routes::RESTORE_STEP_BACKUP_SELECTION_SUBMIT_FORM,
'form_route_to_delete' => Routes::RESTORE_STEP_BACKUP_SELECTION_DELETE_FORM,
'form_route_to_submit_restore' => Routes::RESTORE_STEP_BACKUP_SELECTION_SUBMIT_RESTORE_FORM,
'form_route_to_submit_delete' => Routes::RESTORE_STEP_BACKUP_SELECTION_SUBMIT_DELETE_FORM,
'form_fields' => self::FORM_FIELDS,
'current_backup' => $currentBackup,
'backups_available' => $backupsAvailable,
]
);
}

public function delete(): JsonResponse
/**
* @return array<string, mixed>
*
* @throws BackupException
*/
private function getDialogParams(): array
{
$backupName = $this->request->request->get(RestoreConfiguration::BACKUP_NAME);
$backupDate = $this->upgradeContainer->getBackupFinder()->parseBackupMetadata($backupName)['datetime'];

return [
'backup_name' => $backupName,
'backup_date' => $backupDate,
'form_fields' => self::FORM_FIELDS,
];
}

public function submitDelete(): JsonResponse
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if getDialogParams method throw BackupException, submitDelete too right ?

{
$onlyBackup = count($this->upgradeContainer->getBackupFinder()->getAvailableBackups()) === 1;

return $this->displayDialog('dialog-delete-backup',
array_merge(
$this->getDialogParams(),
[
'only_backup' => $onlyBackup,
'form_name' => self::DELETE_BACKUP_FORM_NAME,
'form_route_to_confirm_delete' => Routes::RESTORE_STEP_BACKUP_SELECTION_CONFIRM_DELETE_FORM,
]
),
'delete-backup-dialog'
);
}

public function confirmDelete(): JsonResponse
{
$backup = $this->request->request->get(self::FORM_FIELDS[RestoreConfiguration::BACKUP_NAME]);
$this->upgradeContainer->getBackupManager()->deleteBackup($backup);
Expand All @@ -92,10 +130,28 @@ public function save(): JsonResponse
return AjaxResponseBuilder::nextRouteResponse(Routes::RESTORE_STEP_BACKUP_SELECTION);
}

public function submitRestore(): JsonResponse
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, submitRestore throw BackupException

{
$backupName = $this->request->request->get(RestoreConfiguration::BACKUP_NAME);
$backupVersion = $this->upgradeContainer->getBackupFinder()->parseBackupMetadata($backupName)['version'];

return $this->displayDialog('dialog-restore-from-backup',
array_merge(
$this->getDialogParams(),
[
'backup_version' => $backupVersion,
'form_name' => self::RESTORE_BACKUP_FORM_NAME,
'form_route_to_confirm_restore' => Routes::RESTORE_STEP_BACKUP_SELECTION_CONFIRM_RESTORE_FORM,
]
),
'restore-backup-dialog'
);
}

/**
* @throws \Exception
*/
public function submit(): JsonResponse
public function startRestore(): JsonResponse
{
$this->saveBackupConfiguration();

Expand All @@ -117,4 +173,19 @@ private function saveBackupConfiguration(): void
$restoreConfiguration->merge($config);
$configurationStorage->save($restoreConfiguration);
}

/**
* @param array<string, mixed> $params
*/
private function displayDialog(string $dialogName, array $params, string $scriptName): JsonResponse
{
return AjaxResponseBuilder::hydrationResponse(
PageSelectors::DIALOG_PARENT_ID,
$this->getTwig()->render(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

render method throws multiple exceptions, we can add them in the code doc

'@ModuleAutoUpgrade/dialogs/' . $dialogName . '.html.twig',
$params
),
['addScript' => $scriptName]
);
}
}
9 changes: 7 additions & 2 deletions storybook/stories/components/DialogBackupDelete.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/

import DialogBackupDelete from "../../../views/templates/dialogs/dialog-backup-delete.html.twig";
import DialogBackupDelete from "../../../views/templates/dialogs/dialog-delete-backup.html.twig";

export default {
title: "Components/Dialog",
Expand All @@ -34,7 +34,12 @@ export const BackupDelete = {
args: {
backup_name: "autoupgrade_save_8.1.6",
backup_date: "15/07/2024 8:00",
is_only_backup: true,
only_backup: true,
form_name: "delete-backup",
form_route_to_confirm_delete: "/",
form_fields: {
BACKUP_NAME: "backup_name",
},
},
play: async () => {
const dialog = document.querySelector('.dialog');
Expand Down
48 changes: 48 additions & 0 deletions storybook/stories/components/DialogRestoreFromBackup.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/

import DialogRestoreFromBackup from "../../../views/templates/dialogs/dialog-restore-from-backup.html.twig";

export default {
title: "Components/Dialog",
component: DialogRestoreFromBackup,
args: {
backup_version: "1.7.8.1",
backup_name: "backup-name",
backup_date: "2024-01-01",
form_name: "backup_to_restore",
form_route_to_confirm_restore: "/",
form_fields: {
BACKUP_NAME: "backup_name",
},
},
};

export const RestoreFromBackup = {
play: async () => {
const dialog = document.querySelector('.dialog');
dialog.showModal();
},
};
2 changes: 1 addition & 1 deletion storybook/stories/pages/BackupSelection.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/

import BackupSelectionPage from "../../../views/templates/pages/rollback.html.twig";
import BackupSelectionPage from "../../../views/templates/pages/restore.html.twig";
import { Default as BackupSelectionComponent } from "../components/BackupSelection.stories";
import { BackupSelection as Stepper } from "../components/Stepper.stories";

Expand Down
2 changes: 1 addition & 1 deletion storybook/stories/pages/PostRestore.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/

import PostRestorePage from "../../../views/templates/pages/rollback.html.twig";
import PostRestorePage from "../../../views/templates/pages/restore.html.twig";
import { PostRestore as Stepper } from "../components/Stepper.stories";

export default {
Expand Down
2 changes: 1 addition & 1 deletion storybook/stories/pages/Restore.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
*/

import RestorePage from "../../../views/templates/pages/rollback.html.twig";
import RestorePage from "../../../views/templates/pages/restore.html.twig";
import { RestoreLogsProgress as LogsProgress } from "../components/LogsProgress.stories";
import { RestoreLogsViewer as LogsViewer } from "../components/LogsViewer.stories";
import { Restore as Stepper } from "../components/Stepper.stories";
Expand Down
4 changes: 2 additions & 2 deletions views/templates/components/backup-selection.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
class="form-group backup-selection"
action=""
data-route-to-save="{{ form_route_to_save }}"
data-route-to-submit="{{ form_route_to_submit }}"
data-route-to-delete="{{ form_route_to_delete }}"
data-route-to-submit-restore="{{ form_route_to_submit_restore }}"
data-route-to-submit-delete="{{ form_route_to_submit_delete }}"
id="{{ form_backup_selection_name }}"
name="{{ form_backup_selection_name }}"
>
Expand Down
Loading
Loading