-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #986 from Quetzacoalt91/backup-options-page
[NEW-UI] Backup options page
- Loading branch information
Showing
39 changed files
with
813 additions
and
207 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
import ModalContainer from './components/ModalContainer'; | ||
import RouteHandler from './routing/RouteHandler'; | ||
import ScriptHandler from './routing/ScriptHandler'; | ||
|
||
export const routeHandler = new RouteHandler(); | ||
|
||
export const modalContainer = new ModalContainer(); | ||
export const scriptHandler = new ScriptHandler(); | ||
|
||
export default { routeHandler, scriptHandler }; | ||
export default { routeHandler, scriptHandler, modalContainer }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import DomLifecycle from '../types/DomLifecycle'; | ||
import Hydration from '../utils/Hydration'; | ||
|
||
export default class ModalContainer implements DomLifecycle { | ||
public static readonly cancelEvent = 'cancel'; | ||
public static readonly okEvent = 'ok'; | ||
|
||
public static readonly containerId = 'ua_modal'; | ||
|
||
public mount(): void { | ||
this.modalContainer.addEventListener(Hydration.hydrationEventName, this.#displayModal); | ||
this.modalContainer.addEventListener('click', this.#onClick); | ||
this.modalContainer.addEventListener(ModalContainer.cancelEvent, this.#closeModal); | ||
this.modalContainer.addEventListener(ModalContainer.okEvent, this.#closeModal); | ||
} | ||
|
||
public beforeDestroy(): void { | ||
this.modalContainer.removeEventListener(Hydration.hydrationEventName, this.#displayModal); | ||
this.modalContainer.removeEventListener('click', this.#onClick); | ||
this.modalContainer.removeEventListener(ModalContainer.cancelEvent, this.#closeModal); | ||
this.modalContainer.removeEventListener(ModalContainer.okEvent, this.#closeModal); | ||
} | ||
|
||
public get modalContainer(): HTMLElement { | ||
const container = document.getElementById(ModalContainer.containerId); | ||
|
||
if (!container) { | ||
throw new Error('Cannot find modal container to initialize.'); | ||
} | ||
return container; | ||
} | ||
|
||
#displayModal(): void { | ||
$( | ||
document.getElementById(ModalContainer.containerId)?.getElementsByClassName('modal') || [] | ||
).modal('show'); | ||
} | ||
|
||
#onClick(ev: Event): void { | ||
const target = ev.target ? (ev.target as HTMLElement) : null; | ||
const modal = target?.closest('.modal'); | ||
|
||
if (modal) { | ||
if (target?.closest("[data-dismiss='modal']")) { | ||
modal.dispatchEvent(new Event(ModalContainer.cancelEvent, { bubbles: true })); | ||
} else if (target?.closest(".modal-footer button:not([data-dismiss='modal'])")) { | ||
modal.dispatchEvent(new Event(ModalContainer.okEvent, { bubbles: true })); | ||
} | ||
} | ||
} | ||
|
||
#closeModal(ev: Event): void { | ||
const modal = ev.target; | ||
if (modal) { | ||
$(modal).modal('hide'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import DomLifecycle from '../types/DomLifecycle'; | ||
import api from '../api/RequestHandler'; | ||
|
||
export default class StartUpdateModal implements DomLifecycle { | ||
protected readonly formId = 'form-confirm-update'; | ||
protected readonly confirmCheckboxId = 'modal-start-update-own-backup'; | ||
|
||
public mount(): void { | ||
this.#form.addEventListener('submit', this.#onSubmit); | ||
this.#form.addEventListener('change', this.#onChange); | ||
|
||
this.#updateSubmitButtonStatus( | ||
document.getElementById('modal-start-update-own-backup') as HTMLInputElement | undefined | ||
); | ||
} | ||
|
||
public beforeDestroy(): void { | ||
this.#form.removeEventListener('submit', this.#onSubmit); | ||
this.#form.removeEventListener('change', this.#onChange); | ||
} | ||
|
||
get #form(): HTMLFormElement { | ||
const form = document.forms.namedItem('form-confirm-update'); | ||
if (!form) { | ||
throw new Error('Form not found'); | ||
} | ||
|
||
// We implement the same way to check from the other scripts, even though there is only one value. | ||
// This will ease any potential refacto. | ||
['routeToSubmit'].forEach((data) => { | ||
if (!form.dataset[data]) { | ||
throw new Error(`Missing data ${data} from form dataset.`); | ||
} | ||
}); | ||
|
||
return form; | ||
} | ||
|
||
get #submitButton(): HTMLButtonElement { | ||
const submitButton = Array.from(this.#form.elements).find( | ||
(element) => element instanceof HTMLButtonElement && element.type === 'submit' | ||
) as HTMLButtonElement | null; | ||
|
||
if (!submitButton) { | ||
throw new Error(`No submit button found for form ${this.#form.id}`); | ||
} | ||
|
||
return submitButton; | ||
} | ||
|
||
readonly #onChange = async (ev: Event) => { | ||
const optionInput = ev.target as HTMLInputElement; | ||
|
||
if (optionInput.id === this.confirmCheckboxId) { | ||
this.#updateSubmitButtonStatus(optionInput); | ||
} | ||
}; | ||
|
||
readonly #onSubmit = async (event: Event) => { | ||
event.preventDefault(); | ||
|
||
await api.post(this.#form.dataset.routeToSubmit!, new FormData(this.#form)); | ||
}; | ||
|
||
#updateSubmitButtonStatus(input?: HTMLInputElement): void { | ||
if (!input || input.checked) { | ||
this.#submitButton.removeAttribute('disabled'); | ||
} else { | ||
this.#submitButton.setAttribute('disabled', 'true'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,74 @@ | ||
import api from '../api/RequestHandler'; | ||
import { modalContainer } from '../autoUpgrade'; | ||
import ModalContainer from '../components/ModalContainer'; | ||
import UpdatePage from './UpdatePage'; | ||
|
||
export default class UpdatePageBackup extends UpdatePage { | ||
protected stepCode = 'backup'; | ||
|
||
constructor() { | ||
super(); | ||
} | ||
|
||
public mount() { | ||
this.initStepper(); | ||
this.#form.addEventListener('submit', this.#onFormSubmit); | ||
this.#form.addEventListener('change', this.#onInputChange); | ||
|
||
document.getElementById('ua_container')?.addEventListener('click', this.#onClick); | ||
modalContainer.modalContainer.addEventListener(ModalContainer.okEvent, this.#onModalOk); | ||
} | ||
|
||
public beforeDestroy(): void { | ||
this.#form.removeEventListener('submit', this.#onFormSubmit); | ||
this.#form.removeEventListener('change', this.#onInputChange); | ||
|
||
document.getElementById('ua_container')?.removeEventListener('click', this.#onClick); | ||
modalContainer.modalContainer.removeEventListener(ModalContainer.okEvent, this.#onModalOk); | ||
} | ||
|
||
get #form(): HTMLFormElement { | ||
const form = document.forms.namedItem('update-backup-page-form'); | ||
if (!form) { | ||
throw new Error('Form not found'); | ||
} | ||
|
||
['routeToSave', 'routeToSubmitBackup', 'routeToSubmitUpdate', 'routeToConfirmBackup'].forEach( | ||
(data) => { | ||
if (!form.dataset[data]) { | ||
throw new Error(`Missing data ${data} from form dataset.`); | ||
} | ||
} | ||
); | ||
|
||
return form; | ||
} | ||
|
||
readonly #onClick = async (ev: Event) => { | ||
if ((ev.target as HTMLElement).id === 'update-backup-page-skip-btn') { | ||
const formData = new FormData(); | ||
// TODO: Value currently hardcoded until management of backups is implemented | ||
formData.append('backupDone', JSON.stringify(false)); | ||
await api.post(this.#form.dataset.routeToSubmitUpdate!, formData); | ||
} | ||
}; | ||
|
||
readonly #onModalOk = async (ev: Event) => { | ||
// We handle the backup confirmation modal as it is really basic | ||
if ((ev.target as HTMLElement).id === 'modal-confirm-backup') { | ||
api.post(this.#form.dataset.routeToConfirmBackup!); | ||
} | ||
// The update confirmation modal gets its logic in a dedicated script | ||
}; | ||
|
||
readonly #onInputChange = async (ev: Event) => { | ||
const optionInput = ev.target as HTMLInputElement; | ||
|
||
const data = new FormData(this.#form); | ||
optionInput.setAttribute('disabled', 'true'); | ||
await api.post(this.#form.dataset.routeToSave!, data); | ||
optionInput.removeAttribute('disabled'); | ||
}; | ||
|
||
readonly #onFormSubmit = async (event: Event) => { | ||
event.preventDefault(); | ||
|
||
await api.post(this.#form.dataset.routeToSubmitBackup!, new FormData(this.#form)); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.