This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
authentik/web/src/elements/buttons/ModalButton.ts

175 lines
6.1 KiB
TypeScript
Raw Normal View History

import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
// @ts-ignore
import ModalBoxStyle from "@patternfly/patternfly/components/ModalBox/modal-box.css";
// @ts-ignore
import BullseyeStyle from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
// @ts-ignore
import BackdropStyle from "@patternfly/patternfly/components/Backdrop/backdrop.css";
// @ts-ignore
import ButtonStyle from "@patternfly/patternfly/components/Button/button.css";
// @ts-ignore
import fa from "@fortawesome/fontawesome-free/css/solid.css";
import { convertToSlug } from "../../utils";
import { SpinnerButton } from "./SpinnerButton";
import { PRIMARY_CLASS } from "../../constants";
2020-12-05 21:08:42 +00:00
@customElement("ak-modal-button")
export class ModalButton extends LitElement {
@property()
href?: string;
2020-12-02 14:44:40 +00:00
@property({type: Boolean})
2020-12-01 08:15:41 +00:00
open = false;
static get styles(): CSSResult[] {
return [
css`
:host {
text-align: left;
}
::slotted(*) {
overflow-y: auto;
}
`,
ModalBoxStyle,
BullseyeStyle,
BackdropStyle,
ButtonStyle,
fa,
];
}
2020-11-21 14:24:45 +00:00
constructor() {
super();
2020-11-21 19:48:49 +00:00
window.addEventListener("keyup", (e) => {
2020-11-21 14:24:45 +00:00
if (e.code === "Escape") {
this.open = false;
}
});
}
updateHandlers(): void {
// Ensure links close the modal
2020-11-26 22:35:59 +00:00
this.querySelectorAll<HTMLAnchorElement>("[slot=modal] a").forEach((a) => {
2020-11-29 18:40:28 +00:00
if (a.target == "_blank") {
return;
}
2020-11-26 22:35:59 +00:00
// Make click on a close the modal
a.addEventListener("click", (e) => {
e.preventDefault();
this.open = false;
});
});
2020-11-21 18:22:53 +00:00
// Make name field update slug field
2020-11-26 22:35:59 +00:00
this.querySelectorAll<HTMLInputElement>("input[name=name]").forEach((input) => {
input.addEventListener("input", () => {
2020-11-26 22:35:59 +00:00
const form = input.closest("form");
if (form === null) {
return;
}
const slugField = form.querySelector<HTMLInputElement>("input[name=slug]");
if (!slugField) {
return;
}
slugField.value = convertToSlug(input.value);
});
});
2020-11-21 19:48:49 +00:00
// Ensure forms sends in AJAX
2020-11-26 22:35:59 +00:00
this.querySelectorAll<HTMLFormElement>("[slot=modal] form").forEach((form) => {
form.addEventListener("submit", (e) => {
e.preventDefault();
2020-12-01 08:15:41 +00:00
const formData = new FormData(form);
2020-11-26 22:35:59 +00:00
fetch(this.href ? this.href : form.action, {
method: form.method,
body: formData,
redirect: "manual",
})
.then((response) => {
return response.text();
})
2020-11-26 22:35:59 +00:00
.then((data) => {
if (data.indexOf("csrfmiddlewaretoken") !== -1) {
const modalSlot = this.querySelector("[slot=modal]");
if (!modalSlot) {
2020-12-05 21:08:42 +00:00
console.debug("authentik/modalbutton: modal slot not found?");
return;
}
modalSlot.innerHTML = data;
2020-12-05 21:08:42 +00:00
console.debug("authentik/modalbutton: re-showing form");
2020-11-26 22:35:59 +00:00
this.updateHandlers();
} else {
this.open = false;
2020-12-05 21:08:42 +00:00
console.debug("authentik/modalbutton: successful submit");
2020-11-26 22:35:59 +00:00
this.dispatchEvent(
2020-12-05 21:08:42 +00:00
new CustomEvent("ak-refresh", {
2020-11-26 22:35:59 +00:00
bubbles: true,
})
);
}
})
.catch((e) => {
console.error(e);
});
});
});
}
onClick(): void {
if (!this.href) {
this.updateHandlers();
this.open = true;
} else {
const request = new Request(this.href);
fetch(request, {
mode: "same-origin",
2020-11-21 19:48:49 +00:00
})
.then((r) => r.text())
.then((t) => {
const modalSlot = this.querySelector("[slot=modal]");
if (!modalSlot) {
return;
}
modalSlot.innerHTML = t;
this.updateHandlers();
this.open = true;
2020-12-05 21:08:42 +00:00
this.querySelectorAll<SpinnerButton>("ak-spinner-button").forEach((sb) => {
sb.setDone(PRIMARY_CLASS);
});
})
.catch((e) => {
console.error(e);
});
}
}
renderModal(): TemplateResult {
return html`<div class="pf-c-backdrop">
<div class="pf-l-bullseye">
2020-11-21 19:48:49 +00:00
<div
class="pf-c-modal-box pf-m-lg"
2020-11-21 19:48:49 +00:00
role="dialog"
aria-modal="true"
aria-labelledby="modal-md-title"
aria-describedby="modal-md-description"
>
<button
@click=${() => (this.open = false)}
class="pf-c-button pf-m-plain"
type="button"
aria-label="Close dialog"
>
<i class="fas fa-times" aria-hidden="true"></i>
</button>
2020-11-21 19:48:49 +00:00
<slot name="modal"> </slot>
</div>
</div>
</div>`;
}
render(): TemplateResult {
return html` <slot name="trigger" @click=${() => this.onClick()}></slot>
${this.open ? this.renderModal() : ""}`;
}
}