Skip to content

Commit

Permalink
feat: refacto to use native html dialog + js
Browse files Browse the repository at this point in the history
  • Loading branch information
tblivet committed Nov 26, 2024
1 parent 099ad80 commit 4e0953b
Show file tree
Hide file tree
Showing 27 changed files with 332 additions and 203 deletions.
128 changes: 128 additions & 0 deletions _dev/src/scss/components/_dialog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
@use "../variables" as *;

$e: ".dialog";

@at-root {
::backdrop {
background-color: rgba(0, 0, 0, 0.5);
}
}

#{$ua-id} {
#{$e} {
border: none;
border: none;
box-shadow: var(--#{$ua-prefix}box-shadow-modal);
width: 508px;
max-width: calc(100% - 2rem);

&__content {
display: flex;
flex-direction: column;
gap: 1.5rem;
}

&__header {
display: flex;
gap: 1rem;
align-items: center;
width: 100%;
padding: 1.5rem;
padding-block-end: 0;
border: none;

.close {
flex-shrink: 0;
float: none;
margin: 0;
margin-inline-start: auto;
opacity: 1;
color: var(--#{$ua-prefix}base-text-color);
cursor: pointer;

&:hover {
color: var(--#{$ua-prefix}base-text-color-hover);
}

.material-icons {
font-size: 1.5rem;
}
}
}

&__body {
display: flex;
flex-direction: column;
gap: 1.5rem;
padding-block: 0;
padding-inline: 1.5rem;
font-size: 1rem;
line-height: 1.375;
}

&__footer {
padding: 1.5rem;
padding-block-start: 0;
border: none;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
gap: 1rem;
}

// Custom modals
&__spacer {
display: flex;
flex-direction: column;
gap: 1.5rem;
}

&__no-backup {
margin-block: 0;

label {
font-weight: 400;
}
}

&__rocket-icon {
width: 1.425em;
height: 1.425em;
}

&__error-report-form {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

&--md {
width: 904px;
max-width: calc(100% - 2rem);
}

&--lg {
width: 1127px;
max-width: calc(100% - 2rem);
}

&--danger {
#{$e}__header {
&::before {
content: "\e872";
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
width: 2.5rem;
height: 2.5rem;
background-color: var(--#{$ua-prefix}red-50);
border-radius: 999px;
font-family: var(--#{$ua-prefix}font-family-material-icons);
font-size: 1.5rem;
font-weight: 400;
}
}
}
}
}
1 change: 1 addition & 0 deletions _dev/src/scss/components/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
@use "button";
@use "check-requirements";
@use "content";
@use "dialog";
@use "form";
@use "local-archive";
@use "logs";
Expand Down
6 changes: 3 additions & 3 deletions _dev/src/ts/autoUpgrade.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import ModalContainer from './components/ModalContainer';
import DialogContainer from './components/DialogContainer';
import RouteHandler from './routing/RouteHandler';
import ScriptHandler from './routing/ScriptHandler';

export const routeHandler = new RouteHandler();

export const modalContainer = new ModalContainer();
export const dialogContainer = new DialogContainer();
export const scriptHandler = new ScriptHandler();

export default { routeHandler, scriptHandler, modalContainer };
export default { routeHandler, scriptHandler, dialogContainer };
61 changes: 61 additions & 0 deletions _dev/src/ts/components/DialogContainer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import DomLifecycle from '../types/DomLifecycle';
import Hydration from '../utils/Hydration';

export default class DialogContainer implements DomLifecycle {
public static readonly cancelEvent = 'cancel';
public static readonly okEvent = 'ok';

public static readonly containerId = 'ua_dialog';

public mount(): void {
this.DialogContainer.addEventListener(Hydration.hydrationEventName, this.#displayDialog);
this.DialogContainer.addEventListener('click', this.#onClick);
this.DialogContainer.addEventListener(DialogContainer.cancelEvent, this.#closeDialog);
this.DialogContainer.addEventListener(DialogContainer.okEvent, this.#closeDialog);
}

public beforeDestroy(): void {
this.DialogContainer.removeEventListener(Hydration.hydrationEventName, this.#displayDialog);
this.DialogContainer.removeEventListener('click', this.#onClick);
this.DialogContainer.removeEventListener(DialogContainer.cancelEvent, this.#closeDialog);
this.DialogContainer.removeEventListener(DialogContainer.okEvent, this.#closeDialog);
}

public get DialogContainer(): HTMLElement {
const container = document.getElementById(DialogContainer.containerId);

if (!container) {
throw new Error('Cannot find dialog container to initialize.');
}
return container;
}

#displayDialog(): void {
const dialog = document.getElementById(DialogContainer.containerId)?.getElementsByClassName('dialog')[0] as HTMLDialogElement;

Check failure on line 34 in _dev/src/ts/components/DialogContainer.ts

View workflow job for this annotation

GitHub Actions / JS linter syntax check

Replace `.getElementById(DialogContainer.containerId)` with `⏎······.getElementById(DialogContainer.containerId)⏎······`
if (dialog) {
dialog.showModal();
}
}

#onClick(ev: Event): void {
const target = ev.target ? (ev.target as HTMLElement) : null;
const dialog = target?.closest('.dialog');

if (dialog) {
if (target?.closest("[data-dismiss='dialog']")) {
dialog.dispatchEvent(new Event(DialogContainer.cancelEvent, { bubbles: true }));
} else if (!dialog.contains(target) || target === dialog) {

Check failure on line 47 in _dev/src/ts/components/DialogContainer.ts

View workflow job for this annotation

GitHub Actions / JS linter syntax check

Delete `·`
dialog.dispatchEvent(new Event(DialogContainer.cancelEvent, { bubbles: true }));
} else if (target?.closest(".dialog__footer button:not([data-dismiss='dialog'])")) {
dialog.dispatchEvent(new Event(DialogContainer.okEvent, { bubbles: true }));
}
}
}

#closeDialog(ev: Event): void {
const dialog = ev.target as HTMLDialogElement;
if (dialog) {
dialog.close();
}
}
}
61 changes: 0 additions & 61 deletions _dev/src/ts/components/ModalContainer.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import DomLifecycle from '../types/DomLifecycle';
import api from '../api/RequestHandler';

export default class StartUpdateModal implements DomLifecycle {
export default class StartUpdateDialog implements DomLifecycle {
protected readonly formId = 'form-confirm-update';
protected readonly confirmCheckboxId = 'modal-start-update-own-backup';
protected readonly confirmCheckboxId = 'dialog-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
document.getElementById('dialog-start-update-own-backup') as HTMLInputElement | undefined
);
}

Expand Down
16 changes: 8 additions & 8 deletions _dev/src/ts/pages/UpdatePageBackup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import api from '../api/RequestHandler';
import { modalContainer } from '../autoUpgrade';
import ModalContainer from '../components/ModalContainer';
import { dialogContainer } from '../autoUpgrade';
import DialogContainer from '../components/DialogContainer';
import UpdatePage from './UpdatePage';

export default class UpdatePageBackup extends UpdatePage {
Expand All @@ -12,15 +12,15 @@ export default class UpdatePageBackup extends UpdatePage {
this.#form.addEventListener('change', this.#onInputChange);

document.getElementById('ua_container')?.addEventListener('click', this.#onClick);
modalContainer.modalContainer.addEventListener(ModalContainer.okEvent, this.#onModalOk);
dialogContainer.DialogContainer.addEventListener(DialogContainer.okEvent, this.#onDialogOk);
}

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);
dialogContainer.DialogContainer.removeEventListener(DialogContainer.okEvent, this.#onDialogOk);
}

get #form(): HTMLFormElement {
Expand Down Expand Up @@ -49,12 +49,12 @@ export default class UpdatePageBackup extends UpdatePage {
}
};

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') {
readonly #onDialogOk = async (ev: Event) => {
// We handle the backup confirmation dialog as it is really basic
if ((ev.target as HTMLElement).id === 'dialog-confirm-backup') {
api.post(this.#form.dataset.routeToConfirmBackup!);
}
// The update confirmation modal gets its logic in a dedicated script
// The update confirmation dialog gets its logic in a dedicated script
};

readonly #onInputChange = async (ev: Event) => {
Expand Down
4 changes: 2 additions & 2 deletions _dev/src/ts/routing/ScriptHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import UpdatePagePostUpdate from '../pages/UpdatePagePostUpdate';
import DomLifecycle from '../types/DomLifecycle';
import { RoutesMatching } from '../types/scriptHandlerTypes';
import { routeHandler } from '../autoUpgrade';
import StartUpdateModal from '../modals/StartUpdateModal';
import StartUpdateDialog from '../dialogs/StartUpdateDialog';

export default class ScriptHandler {
#currentScript: DomLifecycle | undefined;
Expand All @@ -25,7 +25,7 @@ export default class ScriptHandler {
'update-page-update': UpdatePageUpdate,
'update-page-post-update': UpdatePagePostUpdate,

'start-update-modal': StartUpdateModal
'start-update-dialog': StartUpdateDialog
};

/**
Expand Down
6 changes: 3 additions & 3 deletions _dev/src/ts/utils/Hydration.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApiResponseHydration } from '../types/apiTypes';
import { modalContainer, routeHandler, scriptHandler } from '../autoUpgrade';
import { dialogContainer, routeHandler, scriptHandler } from '../autoUpgrade';

export default class Hydration {
/**
Expand Down Expand Up @@ -33,13 +33,13 @@ export default class Hydration {
if (elementToUpdate && data.new_content) {
if (data.new_route) {
scriptHandler.unloadRouteScript();
modalContainer.beforeDestroy();
dialogContainer.beforeDestroy();
}

elementToUpdate.innerHTML = data.new_content;

if (data.new_route) {
modalContainer.mount();
dialogContainer.mount();
scriptHandler.updateRouteScript(data.new_route);

if (!fromPopState) {
Expand Down
Loading

0 comments on commit 4e0953b

Please sign in to comment.