2020-12-01 16:27:19 +00:00
|
|
|
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
|
2020-11-21 10:28:00 +00:00
|
|
|
// @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";
|
2020-11-21 23:06:25 +00:00
|
|
|
// @ts-ignore
|
|
|
|
import ButtonStyle from "@patternfly/patternfly/components/Button/button.css";
|
|
|
|
// @ts-ignore
|
2020-11-22 00:08:56 +00:00
|
|
|
import fa from "@fortawesome/fontawesome-free/css/solid.css";
|
2020-11-21 23:06:25 +00:00
|
|
|
|
2020-11-29 21:14:48 +00:00
|
|
|
import { convertToSlug } from "../../utils";
|
2020-11-29 17:10:12 +00:00
|
|
|
import { SpinnerButton } from "./SpinnerButton";
|
2020-11-29 21:14:48 +00:00
|
|
|
import { PRIMARY_CLASS } from "../../constants";
|
2020-11-20 21:08:00 +00:00
|
|
|
|
|
|
|
@customElement("pb-modal-button")
|
|
|
|
export class ModalButton extends LitElement {
|
|
|
|
@property()
|
2020-11-22 20:35:52 +00:00
|
|
|
href?: string;
|
2020-11-20 21:08:00 +00:00
|
|
|
|
2020-12-02 14:44:40 +00:00
|
|
|
@property({type: Boolean})
|
2020-12-01 08:15:41 +00:00
|
|
|
open = false;
|
2020-11-21 10:28:00 +00:00
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
static get styles(): CSSResult[] {
|
2020-11-22 00:03:13 +00:00
|
|
|
return [
|
|
|
|
css`
|
|
|
|
:host {
|
|
|
|
text-align: left;
|
|
|
|
}
|
2020-11-22 20:04:09 +00:00
|
|
|
::slotted(*) {
|
|
|
|
overflow-y: auto;
|
|
|
|
}
|
2020-11-22 00:03:13 +00:00
|
|
|
`,
|
|
|
|
ModalBoxStyle,
|
|
|
|
BullseyeStyle,
|
|
|
|
BackdropStyle,
|
|
|
|
ButtonStyle,
|
|
|
|
fa,
|
|
|
|
];
|
2020-11-20 21:08:00 +00:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
updateHandlers(): void {
|
2020-11-21 11:27:19 +00:00
|
|
|
// 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) => {
|
2020-12-01 16:27:19 +00:00
|
|
|
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-22 21:05:11 +00:00
|
|
|
})
|
2020-11-26 22:35:59 +00:00
|
|
|
.then((data) => {
|
|
|
|
if (data.indexOf("csrfmiddlewaretoken") !== -1) {
|
2020-12-01 16:27:19 +00:00
|
|
|
const modalSlot = this.querySelector("[slot=modal]");
|
|
|
|
if (!modalSlot) {
|
|
|
|
console.debug("passbook/modalbutton: modal slot not found?");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
modalSlot.innerHTML = data;
|
2020-12-01 08:15:41 +00:00
|
|
|
console.debug("passbook/modalbutton: re-showing form");
|
2020-11-26 22:35:59 +00:00
|
|
|
this.updateHandlers();
|
|
|
|
} else {
|
|
|
|
this.open = false;
|
2020-12-01 08:15:41 +00:00
|
|
|
console.debug("passbook/modalbutton: successful submit");
|
2020-11-26 22:35:59 +00:00
|
|
|
this.dispatchEvent(
|
|
|
|
new CustomEvent("hashchange", {
|
|
|
|
bubbles: true,
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(e);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
2020-11-21 11:27:19 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
onClick(): void {
|
2020-11-22 20:35:52 +00:00
|
|
|
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
|
|
|
})
|
2020-11-22 20:35:52 +00:00
|
|
|
.then((r) => r.text())
|
|
|
|
.then((t) => {
|
2020-12-01 16:27:19 +00:00
|
|
|
const modalSlot = this.querySelector("[slot=modal]");
|
|
|
|
if (!modalSlot) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
modalSlot.innerHTML = t;
|
2020-11-22 20:35:52 +00:00
|
|
|
this.updateHandlers();
|
|
|
|
this.open = true;
|
2020-11-29 21:14:48 +00:00
|
|
|
this.querySelectorAll<SpinnerButton>("pb-spinner-button").forEach((sb) => {
|
2020-11-29 17:10:12 +00:00
|
|
|
sb.setDone(PRIMARY_CLASS);
|
|
|
|
});
|
2020-11-22 20:35:52 +00:00
|
|
|
})
|
|
|
|
.catch((e) => {
|
|
|
|
console.error(e);
|
|
|
|
});
|
|
|
|
}
|
2020-11-21 10:28:00 +00:00
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
renderModal(): TemplateResult {
|
2020-11-20 21:08:00 +00:00
|
|
|
return html`<div class="pf-c-backdrop">
|
|
|
|
<div class="pf-l-bullseye">
|
2020-11-21 19:48:49 +00:00
|
|
|
<div
|
2020-11-22 20:04:09 +00:00
|
|
|
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"
|
|
|
|
>
|
2020-11-21 10:28:00 +00:00
|
|
|
<i class="fas fa-times" aria-hidden="true"></i>
|
|
|
|
</button>
|
2020-11-21 19:48:49 +00:00
|
|
|
<slot name="modal"> </slot>
|
2020-11-20 21:08:00 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>`;
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:27:19 +00:00
|
|
|
render(): TemplateResult {
|
|
|
|
return html` <slot name="trigger" @click=${() => this.onClick()}></slot>
|
2020-11-21 10:28:00 +00:00
|
|
|
${this.open ? this.renderModal() : ""}`;
|
2020-11-20 21:08:00 +00:00
|
|
|
}
|
|
|
|
}
|