Skip to content
Merged
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
4 changes: 2 additions & 2 deletions ocg-server/static/js/dashboard/community/team-add-member.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ export class TeamAddMember extends LitWrapper {
@click=${() => this._close()}
></div>
<div class="modal-panel p-4 max-w-3xl">
<div class="modal-card rounded-lg">
<div class="modal-card rounded-lg modal-overflow-visible">
<div class="flex items-center justify-between p-4 md:p-5 border-b border-stone-200 rounded-t">
<h3 class="text-xl font-semibold text-stone-900">Add member</h3>
<button
Expand All @@ -254,7 +254,7 @@ export class TeamAddMember extends LitWrapper {
<span class="sr-only">Close modal</span>
</button>
</div>
<div class="modal-body p-4 md:p-8">
<div class="modal-body p-4 md:p-8 modal-overflow-visible">
<form
id="team-add-form"
hx-post="/dashboard/${this.dashboardType}/team/add"
Expand Down
8 changes: 4 additions & 4 deletions ocg-server/static/js/dashboard/event/cfs-submissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1147,11 +1147,11 @@ if (!customElements.get("review-submission-modal")) {
}

const initializeCfsSubmissions = () => {
if (!document.body || document.body.dataset[DATA_KEY] === "true") {
if (document.documentElement.dataset[DATA_KEY] === "true") {
return;
}
document.body.dataset[DATA_KEY] = "true";
document.body.addEventListener("htmx:afterSwap", (event) => {
document.documentElement.dataset[DATA_KEY] = "true";
document.addEventListener("htmx:afterSwap", (event) => {
const target = event?.detail?.target || event?.detail?.elt;
if (!(target instanceof Element) || target.id !== SUBMISSIONS_CONTENT_ID) {
return;
Expand All @@ -1165,7 +1165,7 @@ const initializeCfsSubmissions = () => {
modal.syncLabelsFromFilter();
});

document.body.addEventListener("click", (event) => {
document.addEventListener("click", (event) => {
if (!(event.target instanceof Element)) {
return;
}
Expand Down
8 changes: 3 additions & 5 deletions ocg-server/static/js/dashboard/group/attendees.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,6 @@ const initializeAttendeesFeatures = (root = document) => {

initializeAttendeesFeatures();

if (document.body) {
document.body.addEventListener("htmx:load", (event) => {
initializeAttendeesFeatures(event.target || document);
});
}
document.addEventListener("htmx:load", (event) => {
initializeAttendeesFeatures(event.target || document);
});
4 changes: 1 addition & 3 deletions ocg-server/static/js/dashboard/group/members.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,4 @@ const initializeMembersNotification = () => {

initializeMembersNotification();

if (document.body) {
document.body.addEventListener("htmx:load", initializeMembersNotification);
}
document.addEventListener("htmx:load", initializeMembersNotification);
8 changes: 3 additions & 5 deletions ocg-server/static/js/dashboard/group/sponsors.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ const initializeSponsorsFeatures = (root = document) => {

initializeSponsorsFeatures();

if (document.body) {
document.body.addEventListener("htmx:load", (event) => {
initializeSponsorsFeatures(event.target || document);
});
}
document.addEventListener("htmx:load", (event) => {
initializeSponsorsFeatures(event.target || document);
});
4 changes: 1 addition & 3 deletions ocg-server/static/js/dashboard/user/session-proposals.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,4 @@ const initializeSessionProposals = () => {

initializeSessionProposals();

if (document.body) {
document.body.addEventListener("htmx:load", initializeSessionProposals);
}
document.addEventListener("htmx:load", initializeSessionProposals);
4 changes: 1 addition & 3 deletions ocg-server/static/js/dashboard/user/submissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,4 @@ const initializeSubmissionActions = () => {

initializeSubmissionActions();

if (document.body) {
document.body.addEventListener("htmx:load", initializeSubmissionActions);
}
document.addEventListener("htmx:load", initializeSubmissionActions);
15 changes: 7 additions & 8 deletions ocg-server/static/js/event/attendance.js
Original file line number Diff line number Diff line change
Expand Up @@ -1026,16 +1026,15 @@ const initializeAttendance = (root = document) => {
}
});

if (document.body?.dataset.attendanceListenersReady === "true") {
return;
if (document.documentElement.dataset.attendanceListenersReady !== "true") {
document.documentElement.dataset.attendanceListenersReady = "true";
document.addEventListener("htmx:configRequest", handleConfigRequest);
document.addEventListener("htmx:beforeRequest", handleBeforeRequest);
document.addEventListener("htmx:afterRequest", handleAfterRequest);
document.addEventListener("click", handleAttendanceClick);
document.addEventListener("keydown", handleAttendanceKeydown);
}

document.body.dataset.attendanceListenersReady = "true";
document.body.addEventListener("htmx:configRequest", handleConfigRequest);
document.body.addEventListener("htmx:beforeRequest", handleBeforeRequest);
document.body.addEventListener("htmx:afterRequest", handleAfterRequest);
document.body.addEventListener("click", handleAttendanceClick);
document.addEventListener("keydown", handleAttendanceKeydown);
reconcilePaymentReturn();
};

Expand Down
5 changes: 3 additions & 2 deletions ocg-server/static/js/event/cfs.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const handleModalSwap = (event) => {
}
};

if (document.body) {
document.body.addEventListener("htmx:afterSwap", handleModalSwap);
if (document.documentElement.dataset.cfsModalSwapReady !== "true") {
document.documentElement.dataset.cfsModalSwapReady = "true";
document.addEventListener("htmx:afterSwap", handleModalSwap);
}
10 changes: 5 additions & 5 deletions ocg-server/static/js/group/membership.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,14 @@ const handleMembershipClick = (event) => {
const initializeMembership = (root = document) => {
getMembershipContainers(root).forEach(initializeMembershipContainer);

if (document.body?.dataset.membershipListenersReady === "true") {
if (document.documentElement.dataset.membershipListenersReady === "true") {
return;
}

document.body.dataset.membershipListenersReady = "true";
document.body.addEventListener("htmx:beforeRequest", handleBeforeRequest);
document.body.addEventListener("htmx:afterRequest", handleAfterRequest);
document.body.addEventListener("click", handleMembershipClick);
document.documentElement.dataset.membershipListenersReady = "true";
document.addEventListener("htmx:beforeRequest", handleBeforeRequest);
document.addEventListener("htmx:afterRequest", handleAfterRequest);
document.addEventListener("click", handleMembershipClick);
};

if (document.readyState === "loading") {
Expand Down
14 changes: 14 additions & 0 deletions tests/unit/dashboard/community/team-add-member.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,20 @@ describe("team-add-member", () => {
expect(focusCalls).to.equal(1);
});

it("allows the user search dropdown to overflow the modal", async () => {
const element = await mountLitComponentWithAttributes("team-add-member", {
attributes: {
"role-options": JSON.stringify([{ display_name: "Maintainer", community_role_id: "role-1" }]),
},
});

element._open();
await element.updateComplete;

expect(element.querySelector(".modal-card").classList.contains("modal-overflow-visible")).to.equal(true);
expect(element.querySelector(".modal-body").classList.contains("modal-overflow-visible")).to.equal(true);
});

it("enables submit only after both a user and role have been selected", async () => {
const element = await mountLitComponentWithAttributes("team-add-member", {
attributes: {
Expand Down
31 changes: 28 additions & 3 deletions tests/unit/dashboard/event/cfs-submissions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,7 @@ describe("review-submission-modal", () => {
await element.updateComplete;

expect(element._isOpen).to.equal(true);
expect(element.labels).to.deep.equal([
{ event_cfs_label_id: "7", name: "Backend", color: "blue" },
]);
expect(element.labels).to.deep.equal([{ event_cfs_label_id: "7", name: "Backend", color: "blue" }]);
expect(element._message).to.equal("Please expand the abstract");
expect(element._ratingComment).to.equal("Looks promising");
expect(element._ratingStars).to.equal(4);
Expand All @@ -99,6 +97,33 @@ describe("review-submission-modal", () => {
expect(element.querySelector("#cfs-submission-form")).to.not.equal(null);
});

it("opens from a review trigger after the dashboard body is swapped", async () => {
const replacementBody = document.createElement("body");
document.documentElement.replaceChild(replacementBody, document.body);

const element = await renderModal();
element.id = "review-submission-modal";
const submissionPayload = JSON.stringify(buildSubmission());
document.body.insertAdjacentHTML(
"beforeend",
`
<button
type="button"
data-action="open-cfs-submission-modal"
data-submission='${submissionPayload}'
>
Review
</button>
`,
);

document.querySelector('[data-action="open-cfs-submission-modal"]')?.click();
await element.updateComplete;

expect(element._isOpen).to.equal(true);
expect(element._submission.cfs_submission_id).to.equal(12);
});

it("tracks pending changes while keeping label order snapshots stable", async () => {
const element = await renderModal();

Expand Down
47 changes: 33 additions & 14 deletions tests/unit/dashboard/group/attendees.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,35 @@ describe("dashboard group attendees", () => {
expect(modal.classList.contains("hidden")).to.equal(false);
});

it("opens the attendee notification modal after the dashboard body is swapped", () => {
const replacementBody = document.createElement("body");
replacementBody.innerHTML = `
<button
id="open-attendee-notification-modal"
type="button"
data-event-id="event-99"
>
Notify attendees
</button>
<div id="attendee-notification-modal" class="hidden"></div>
<button id="close-attendee-notification-modal" type="button">Close</button>
<button id="cancel-attendee-notification" type="button">Cancel</button>
<div id="overlay-attendee-notification-modal"></div>
<form id="attendee-notification-form"></form>
`;
document.documentElement.replaceChild(replacementBody, document.body);

initializeAttendeesUi();
document.getElementById("open-attendee-notification-modal")?.click();

expect(document.getElementById("attendee-notification-form")?.getAttribute("hx-post")).to.equal(
"/dashboard/group/notifications/event-99",
);
expect(document.getElementById("attendee-notification-modal")?.classList.contains("hidden")).to.equal(
false,
);
});

it("opens the refund review modal with attendee payment details", () => {
const originalHtmx = window.htmx;
const processCalls = [];
Expand Down Expand Up @@ -136,10 +165,7 @@ describe("dashboard group attendees", () => {
expect(rejectButton.getAttribute("hx-put")).to.equal(
"/dashboard/group/events/event-1/attendees/user-1/refund/reject",
);
expect(processCalls).to.deep.equal([
"attendee-refund-approve",
"attendee-refund-reject",
]);
expect(processCalls).to.deep.equal(["attendee-refund-approve", "attendee-refund-reject"]);

window.htmx = originalHtmx;
});
Expand Down Expand Up @@ -344,12 +370,8 @@ describe("dashboard group attendees", () => {
document.querySelector("[data-refund-review-trigger]")?.click();

expect(modal.classList.contains("hidden")).to.equal(false);
expect(document.getElementById("attendee-refund-name")?.textContent).to.equal(
"Swapped Attendee",
);
expect(document.getElementById("attendee-refund-ticket")?.textContent).to.equal(
"Swapped Ticket",
);
expect(document.getElementById("attendee-refund-name")?.textContent).to.equal("Swapped Attendee");
expect(document.getElementById("attendee-refund-ticket")?.textContent).to.equal("Swapped Ticket");
expect(document.getElementById("attendee-refund-amount")?.textContent).to.equal("EUR 25.00");
expect(approveButton.getAttribute("hx-put")).to.equal(
"/dashboard/group/events/event-2/attendees/user-2/refund/approve",
Expand Down Expand Up @@ -463,10 +485,7 @@ describe("dashboard group attendees", () => {

document.querySelector("[data-refund-review-trigger]")?.click();

expect(processCalls).to.deep.equal([
"attendee-refund-approve",
"attendee-refund-reject",
]);
expect(processCalls).to.deep.equal(["attendee-refund-approve", "attendee-refund-reject"]);

window.htmx = originalHtmx;
});
Expand Down
24 changes: 22 additions & 2 deletions tests/unit/dashboard/group/members.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { expect } from "@open-wc/testing";

import "/static/js/dashboard/group/members.js";
import { useDashboardTestEnv } from "/tests/unit/test-utils/env.js";
import { dispatchHtmxAfterRequest } from "/tests/unit/test-utils/htmx.js";
import { dispatchHtmxAfterRequest, dispatchHtmxLoad } from "/tests/unit/test-utils/htmx.js";

describe("dashboard group members", () => {
const env = useDashboardTestEnv({
Expand All @@ -22,7 +23,7 @@ describe("dashboard group members", () => {
</form>
`;

await import(`/static/js/dashboard/group/members.js?test=${Date.now()}`);
dispatchHtmxLoad();

dispatchHtmxAfterRequest(document.getElementById("notification-form"), {
status: 204,
Expand All @@ -33,4 +34,23 @@ describe("dashboard group members", () => {
icon: "success",
});
});

it("opens the notification modal after the dashboard body is swapped", () => {
const replacementBody = document.createElement("body");
replacementBody.innerHTML = `
<button id="open-notification-modal" type="button">Open</button>
<div id="notification-modal" class="hidden"></div>
<button id="close-notification-modal" type="button">Close</button>
<button id="cancel-notification" type="button">Cancel</button>
<div id="overlay-notification-modal"></div>
<form id="notification-form"></form>
`;

document.documentElement.replaceChild(replacementBody, document.body);

dispatchHtmxLoad();
document.getElementById("open-notification-modal")?.click();

expect(document.getElementById("notification-modal")?.classList.contains("hidden")).to.equal(false);
});
});
51 changes: 51 additions & 0 deletions tests/unit/dashboard/group/sponsors.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { expect } from "@open-wc/testing";

import "/static/js/dashboard/group/sponsors.js";
import { waitForMicrotask } from "/tests/unit/test-utils/async.js";
import { useDashboardTestEnv } from "/tests/unit/test-utils/env.js";
import { dispatchHtmxLoad } from "/tests/unit/test-utils/htmx.js";
import { mockFetch } from "/tests/unit/test-utils/network.js";

describe("dashboard group sponsors", () => {
useDashboardTestEnv({
path: "/dashboard/group/sponsors",
withScroll: true,
withSwal: true,
});

let fetchMock;

beforeEach(() => {
fetchMock = mockFetch();
});

afterEach(() => {
fetchMock.restore();
});

it("updates sponsor featured toggles after the dashboard body is swapped", async () => {
const replacementBody = document.createElement("body");
replacementBody.innerHTML = `
<label class="cursor-pointer">
<input
type="checkbox"
class="sponsor-featured-toggle"
data-url="/dashboard/group/sponsors/sponsor-7/featured"
/>
</label>
<div id="dashboard-content"></div>
`;
document.documentElement.replaceChild(replacementBody, document.body);

dispatchHtmxLoad();
const checkbox = document.querySelector(".sponsor-featured-toggle");
checkbox.checked = true;
checkbox.dispatchEvent(new Event("change", { bubbles: true }));

await waitForMicrotask();

expect(fetchMock.calls).to.have.length(1);
expect(fetchMock.calls[0][0]).to.equal("/dashboard/group/sponsors/sponsor-7/featured");
expect(checkbox.dataset.currentChecked).to.equal("true");
});
});
Loading
Loading