>(
+ new Set([]),
+ );
+
+ const tags = useTagsLiveQuery();
+
+ createEffect(() => {
+ const resultTags = getSelectedResult()?.tags ?? [];
+ const knownTagIds = new Set(tags().map((tag) => tag._id));
+ const filtered = resultTags.filter((id) => knownTagIds.has(id));
+ setSelectedTagIds(new Set(filtered));
+ });
+
+ return (
+
+
+
+ {(tag) => (
+
+
+
+ );
+}
diff --git a/frontend/src/ts/components/modals/Modals.tsx b/frontend/src/ts/components/modals/Modals.tsx
index 49d255ad8d00..ff76948a4aeb 100644
--- a/frontend/src/ts/components/modals/Modals.tsx
+++ b/frontend/src/ts/components/modals/Modals.tsx
@@ -6,6 +6,7 @@ import { CookiesModal } from "./CookiesModal";
import { CustomTestDurationModal } from "./CustomTestDurationModal";
import { CustomTextModal } from "./CustomTextModal";
import { CustomWordAmountModal } from "./CustomWordAmountModal";
+import { EditResultTagsModal } from "./EditResultTagsModal";
import { ForgotPasswordModal } from "./ForgotPasswordModal";
import { GoogleSignupModal } from "./GoogleSignUpModal";
import { LastSignedOutResultModal } from "./LastSignedOutResultModal";
@@ -48,6 +49,7 @@ export function Modals(): JSXElement {
+
>
);
}
diff --git a/frontend/src/ts/components/pages/account/Table.tsx b/frontend/src/ts/components/pages/account/Table.tsx
index 26f538695331..121a07460b9b 100644
--- a/frontend/src/ts/components/pages/account/Table.tsx
+++ b/frontend/src/ts/components/pages/account/Table.tsx
@@ -6,8 +6,8 @@ import { Accessor, createMemo, createSignal, JSXElement, Show } from "solid-js";
import { type TagItem, useTagsLiveQuery } from "../../../collections/tags";
import { SnapshotResult } from "../../../constants/default-snapshot";
-import * as EditResultTagsModal from "../../../modals/edit-result-tags";
import { getFormatting } from "../../../states/core";
+import { showEditResultTagsModal } from "../../../states/edit-result-tags";
import { showModal } from "../../../states/modals";
import { showNoticeNotification } from "../../../states/notifications";
import { cn } from "../../../utils/cn";
@@ -261,11 +261,11 @@ function getColumns
({
);
return;
}
- EditResultTagsModal.show(
- info.row.original._id,
- info.getValue(),
- "accountPage",
- );
+
+ showEditResultTagsModal({
+ _id: info.row.original._id,
+ tags: info.getValue(),
+ });
}}
/>
);
diff --git a/frontend/src/ts/event-handlers/test.ts b/frontend/src/ts/event-handlers/test.ts
index d85fc367b256..d12d6585ef33 100644
--- a/frontend/src/ts/event-handlers/test.ts
+++ b/frontend/src/ts/event-handlers/test.ts
@@ -1,5 +1,4 @@
import { Config } from "../config/store";
-import * as EditResultTagsModal from "../modals/edit-result-tags";
import { __nonReactive } from "../collections/tags";
import {
showNoticeNotification,
@@ -12,6 +11,7 @@ import { navigate } from "../controllers/route-controller";
import { getMode2 } from "../utils/misc";
import { qs } from "../utils/dom";
import { getCurrentQuote } from "../states/test";
+import { showEditResultTagsModal } from "../states/edit-result-tags";
const testPage = qs(".pageTest");
@@ -25,7 +25,7 @@ testPage?.onChild("click", ".tags .editTagsButton", () => {
"data-active-tag-ids",
) ?? "";
const tags = activeTagIds === "" ? [] : activeTagIds.split(",");
- EditResultTagsModal.show(resultid, tags, "resultPage");
+ showEditResultTagsModal({ _id: resultid, tags, source: "resultPage" });
}
});
diff --git a/frontend/src/ts/modals/edit-result-tags.ts b/frontend/src/ts/modals/edit-result-tags.ts
deleted file mode 100644
index a92b144c65c5..000000000000
--- a/frontend/src/ts/modals/edit-result-tags.ts
+++ /dev/null
@@ -1,149 +0,0 @@
-import { showLoaderBar, hideLoaderBar } from "../states/loader-bar";
-import {
- showErrorNotification,
- showSuccessNotification,
-} from "../states/notifications";
-import { areUnsortedArraysEqual } from "../utils/arrays";
-import * as TestResult from "../test/result";
-import AnimatedModal from "../utils/animated-modal";
-import { __nonReactive } from "../collections/tags";
-import { updateTags } from "../collections/results";
-import { createErrorMessage } from "../utils/error";
-
-type State = {
- resultId: string;
- startingTags: string[];
- tags: string[];
- source: "accountPage" | "resultPage";
-};
-
-const state: State = {
- resultId: "",
- startingTags: [],
- tags: [],
- source: "accountPage",
-};
-
-export function show(
- resultId: string,
- tags: string[],
- source: "accountPage" | "resultPage",
-): void {
- if (resultId === "") {
- showErrorNotification(
- "Failed to show edit result tags modal: result id is empty",
- );
- return;
- }
-
- const knownTagIds = new Set(__nonReactive.getTags().map((it) => it._id));
- tags = tags.filter((it) => knownTagIds.has(it));
-
- state.resultId = resultId;
- state.startingTags = [...tags];
- state.tags = [...tags];
- state.source = source;
-
- void modal.show({
- beforeAnimation: async (): Promise => {
- appendButtons();
- updateActiveButtons();
- },
- });
-}
-
-function hide(): void {
- void modal.hide();
-}
-
-function appendButtons(): void {
- const buttonsEl = modal.getModal().qs(".buttons");
-
- if (buttonsEl === null) {
- showErrorNotification(
- "Failed to append buttons to edit result tags modal: could not find buttons element",
- );
- return;
- }
-
- const tagIds = new Set([
- ...__nonReactive.getTags().map((tag) => tag._id),
- ...state.tags,
- ]);
-
- buttonsEl.empty();
- for (const tagId of tagIds) {
- const tag = __nonReactive.getTag(tagId);
- const button = document.createElement("button");
- button.classList.add("toggleTag");
- button.setAttribute("data-tag-id", tagId);
- button.textContent = tag?.name ?? tag?._id ?? "unknown tag"; //this shouldnt happen?
- button.addEventListener("click", (e) => {
- toggleTag(tagId);
- updateActiveButtons();
- });
- buttonsEl.append(button);
- }
-}
-
-function updateActiveButtons(): void {
- const buttons = modal.getModal().qsa(".buttons button");
- for (const button of buttons) {
- const tagid: string = button.getAttribute("data-tag-id") ?? "";
- if (state.tags.includes(tagid)) {
- button.addClass("active");
- } else {
- button.removeClass("active");
- }
- }
-}
-
-function toggleTag(tagId: string): void {
- if (state.tags.includes(tagId)) {
- state.tags = state.tags.filter((el) => el !== tagId);
- } else {
- state.tags.push(tagId);
- }
-}
-
-async function save(): Promise {
- showLoaderBar();
- try {
- await updateTags({
- resultId: state.resultId,
- currentTagIds: state.startingTags,
- newTagIds: state.tags,
- afterUpdate: ({ tagPbs }) => {
- if (state.source === "resultPage") {
- TestResult.updateTagsAfterEdit(state.tags, tagPbs);
- }
- },
- });
- hideLoaderBar();
- } catch (e) {
- hideLoaderBar();
- const message = createErrorMessage(e, "Failed to update tags");
- showErrorNotification(message);
- return;
- }
-
- //if got no freaking idea why this is needed
- //but update tags somehow adds undefined to the end of the array
- //i tried spreading, json parsing - nothing helped.
- state.tags = state.tags.filter((el) => el !== undefined);
- showSuccessNotification("Tags updated", { durationMs: 2000 });
-}
-
-const modal = new AnimatedModal({
- dialogId: "editResultTagsModal",
- setup: async (modalEl): Promise => {
- modalEl.qs("button.saveButton")?.on("click", (e) => {
- if (areUnsortedArraysEqual(state.startingTags, state.tags)) {
- hide();
- return;
- }
- hide();
- void save();
- });
- },
-});
diff --git a/frontend/src/ts/states/edit-result-tags.ts b/frontend/src/ts/states/edit-result-tags.ts
new file mode 100644
index 000000000000..58206a3f4a77
--- /dev/null
+++ b/frontend/src/ts/states/edit-result-tags.ts
@@ -0,0 +1,23 @@
+import { Result } from "@monkeytype/schemas/results";
+import { Mode } from "@monkeytype/schemas/shared";
+import { createSignal } from "solid-js";
+import { showModal } from "./modals";
+import { showErrorNotification } from "./notifications";
+
+type IdAndTags = Pick, "_id" | "tags"> & { source?: "resultPage" };
+const [getSelectedResult, setSelectedResult] = createSignal(
+ null,
+);
+
+export { getSelectedResult };
+
+export function showEditResultTagsModal(options: IdAndTags): void {
+ if (options._id === "") {
+ showErrorNotification(
+ "Failed to show edit result tags modal: result id is empty",
+ );
+ return;
+ }
+ setSelectedResult(options);
+ showModal("EditResultTags");
+}
diff --git a/frontend/src/ts/states/modals.ts b/frontend/src/ts/states/modals.ts
index 1f83c9435279..6a2460175800 100644
--- a/frontend/src/ts/states/modals.ts
+++ b/frontend/src/ts/states/modals.ts
@@ -35,7 +35,8 @@ export type ModalId =
| "StreakHourOffset"
| "GoogleSignup"
| "ForgotPassword"
- | "UserReport";
+ | "UserReport"
+ | "EditResultTags";
export type ModalVisibility = {
visible: boolean;