refactor(edit tag): use new modal system

This commit is contained in:
Miodec 2024-03-15 15:11:34 +01:00
parent f47340b301
commit 4220c54de2
7 changed files with 248 additions and 248 deletions

View file

@ -791,15 +791,14 @@
<div class="quotes"></div>
</div>
</div>
<div id="tagsWrapper" class="popupWrapper hidden" tabindex="-1">
<div id="tagsEdit" action="" tagid="">
<form>
<div class="title"></div>
<input type="text" title="tag" />
<button type="submit"></button>
</form>
</div>
</div>
<dialog id="editTagModal" class="modalWrapper hidden">
<form class="modal">
<div class="title"></div>
<input type="text" title="tag" />
<div class="text"></div>
<button type="submit"></button>
</form>
</dialog>
<dialog id="streakHourOffsetModal" class="modalWrapper hidden">
<div class="modal">
<div class="title">Set streak hour offset</div>

View file

@ -1469,6 +1469,12 @@
}
}
#editTagModal {
.modal {
max-width: 450px;
}
}
#streakHourOffsetModal {
.modal {
max-width: 500px;
@ -1493,9 +1499,7 @@
}
}
#tagsWrapper,
#newResultFilterPresetPopupWrapper {
#tagsEdit,
#newResultFilterPresetPopup {
max-height: 90vh;
background: var(--bg-color);
@ -1511,12 +1515,6 @@
}
}
#tagsEdit form,
#presetEdit form {
display: grid;
gap: 1rem;
}
#editProfileModal {
.modal {
max-width: 600px;

View file

@ -1,5 +1,5 @@
import * as DB from "../../db";
import * as EditTagsPopup from "../../popups/edit-tags-popup";
import * as EditTagsPopup from "../../modals/edit-tag";
import * as ModesNotice from "../../elements/modes-notice";
import * as TagController from "../../controllers/tag-controller";
import Config from "../../config";

View file

@ -2,6 +2,7 @@ import * as ShareCustomThemeModal from "../modals/share-custom-theme";
import * as CookiesModal from "../modals/cookies";
import * as StreakHourOffsetModal from "../modals/streak-hour-offset";
import * as EditPresetPopup from "../modals/edit-preset";
import * as EditTagPopup from "../modals/edit-tag";
import * as Notifications from "../elements/notifications";
@ -69,3 +70,64 @@ settingsPage
EditPresetPopup.show("remove", presetid, name);
}
});
settingsPage?.querySelector(".section.tags")?.addEventListener("click", (e) => {
const target = e.target as HTMLElement;
if (target.classList.contains("addTagButton")) {
EditTagPopup.show("add");
} else if (target.classList.contains("editButton")) {
const tagid = target.parentElement?.getAttribute("data-id");
const name = target.parentElement?.getAttribute("data-display");
if (
tagid === undefined ||
name === undefined ||
tagid === "" ||
name === "" ||
tagid === null ||
name === null
) {
Notifications.add(
"Failed to edit tag: Could not find tag id or name",
-1
);
return;
}
EditTagPopup.show("edit", tagid, name);
} else if (target.classList.contains("clearPbButton")) {
const tagid = target.parentElement?.getAttribute("data-id");
const name = target.parentElement?.getAttribute("data-display");
if (
tagid === undefined ||
name === undefined ||
tagid === "" ||
name === "" ||
tagid === null ||
name === null
) {
Notifications.add(
"Failed to clear tag PB: Could not find tag id or name",
-1
);
return;
}
EditTagPopup.show("clearPb", tagid, name);
} else if (target.classList.contains("removeButton")) {
const tagid = target.parentElement?.getAttribute("data-id");
const name = target.parentElement?.getAttribute("data-display");
if (
tagid === undefined ||
name === undefined ||
tagid === "" ||
name === "" ||
tagid === null ||
name === null
) {
Notifications.add(
"Failed to remove tag: Could not find tag id or name",
-1
);
return;
}
EditTagPopup.show("remove", tagid, name);
}
});

View file

@ -30,7 +30,6 @@ import "./controllers/route-controller";
import "./pages/about";
import "./elements/scroll-to-top";
import "./popups/mobile-test-config-popup";
import "./popups/edit-tags-popup";
import "./popups/google-sign-up-popup";
import "./popups/result-tags-popup";
import * as Account from "./pages/account";

View file

@ -0,0 +1,171 @@
import Ape from "../ape";
import * as DB from "../db";
import * as Notifications from "../elements/notifications";
import * as Loader from "../elements/loader";
import * as Settings from "../pages/settings";
import * as ConnectionState from "../states/connection";
import AnimatedModal from "../utils/animated-modal";
export function show(action: string, id?: string, name?: string): void {
if (!ConnectionState.get()) {
Notifications.add("You are offline", 0, {
duration: 2,
});
return;
}
void modal.show({
focusFirstInput: true,
beforeAnimation: async () => {
$("#editTagModal .modal .text").addClass("hidden");
if (action === "add") {
$("#editTagModal .modal").attr("data-action", "add");
$("#editTagModal .modal .title").html("Add new tag");
$("#editTagModal .modal button").html(`add`);
$("#editTagModal .modal input").val("");
$("#editTagModal .modal input").removeClass("hidden");
} else if (action === "edit" && id !== undefined && name !== undefined) {
$("#editTagModal .modal").attr("data-action", "edit");
$("#editTagModal .modal").attr("data-tag-id", id);
$("#editTagModal .modal .title").html("Edit tag");
$("#editTagModal .modal button").html(`save`);
$("#editTagModal .modal input").val(name);
$("#editTagModal .modal input").removeClass("hidden");
} else if (
action === "remove" &&
id !== undefined &&
name !== undefined
) {
$("#editTagModal .modal").attr("data-action", "remove");
$("#editTagModal .modal").attr("data-tag-id", id);
$("#editTagModal .modal .title").html("Delete tag");
$("#editTagModal .modal .text").removeClass("hidden");
$("#editTagModal .modal .text").html(
`Are you sure you want to delete tag ${name}?`
);
$("#editTagModal .modal button").html(`delete`);
$("#editTagModal .modal input").addClass("hidden");
} else if (
action === "clearPb" &&
id !== undefined &&
name !== undefined
) {
$("#editTagModal .modal").attr("data-action", "clearPb");
$("#editTagModal .modal").attr("data-tag-id", id);
$("#editTagModal .modal .title").html("Clear personal bests");
$("#editTagModal .modal .text").removeClass("hidden");
$("#editTagModal .modal .text").html(
`Are you sure you want to clear personal bests for tag ${name}?`
);
$("#editTagModal .modal button").html(`clear`);
$("#editTagModal .modal input").addClass("hidden");
}
},
});
}
function hide(): void {
void modal.hide();
}
async function apply(): Promise<void> {
const action = $("#editTagModal .modal").attr("data-action");
const propTagName = $("#editTagModal .modal input").val() as string;
const tagName = propTagName.replaceAll(" ", "_");
const tagId = $("#editTagModal .modal").attr("data-tag-id") as string;
hide();
Loader.show();
if (action === "add") {
const response = await Ape.users.createTag(tagName);
if (response.status !== 200) {
Notifications.add(
"Failed to add tag: " + response.message.replace(tagName, propTagName),
-1
);
} else {
if (response.data === null) {
Notifications.add("Tag was added but data returned was null", -1);
Loader.hide();
return;
}
Notifications.add("Tag added", 1);
DB.getSnapshot()?.tags?.push({
display: propTagName,
name: response.data.name,
_id: response.data._id,
personalBests: {
time: {},
words: {},
quote: {},
zen: {},
custom: {},
},
});
void Settings.update();
}
} else if (action === "edit") {
const response = await Ape.users.editTag(tagId, tagName);
if (response.status !== 200) {
Notifications.add("Failed to edit tag: " + response.message, -1);
} else {
Notifications.add("Tag updated", 1);
DB.getSnapshot()?.tags?.forEach((tag) => {
if (tag._id === tagId) {
tag.name = tagName;
tag.display = propTagName;
}
});
void Settings.update();
}
} else if (action === "remove") {
const response = await Ape.users.deleteTag(tagId);
if (response.status !== 200) {
Notifications.add("Failed to remove tag: " + response.message, -1);
} else {
Notifications.add("Tag removed", 1);
DB.getSnapshot()?.tags?.forEach((tag, index: number) => {
if (tag._id === tagId) {
DB.getSnapshot()?.tags?.splice(index, 1);
}
});
void Settings.update();
}
} else if (action === "clearPb") {
const response = await Ape.users.deleteTagPersonalBest(tagId);
if (response.status !== 200) {
Notifications.add("Failed to clear tag pb: " + response.message, -1);
} else {
Notifications.add("Tag PB cleared", 1);
DB.getSnapshot()?.tags?.forEach((tag) => {
if (tag._id === tagId) {
tag.personalBests = {
time: {},
words: {},
quote: {},
zen: {},
custom: {},
};
}
});
void Settings.update();
}
}
Loader.hide();
}
const modal = new AnimatedModal({
dialogId: "editTagModal",
setup: (modalEl): void => {
modalEl.addEventListener("submit", (e) => {
e.preventDefault();
void apply();
});
},
});

View file

@ -1,229 +0,0 @@
import Ape from "../ape";
import * as DB from "../db";
import * as Notifications from "../elements/notifications";
import * as Loader from "../elements/loader";
import * as Settings from "../pages/settings";
import * as ConnectionState from "../states/connection";
import * as Skeleton from "../utils/skeleton";
import { isPopupVisible } from "../utils/misc";
const wrapperId = "tagsWrapper";
export function show(action: string, id?: string, name?: string): void {
if (!ConnectionState.get()) {
Notifications.add("You are offline", 0, {
duration: 2,
});
return;
}
Skeleton.append(wrapperId, "popups");
if (action === "add") {
$("#tagsWrapper #tagsEdit").attr("action", "add");
$("#tagsWrapper #tagsEdit .title").html("Add new tag");
$("#tagsWrapper #tagsEdit button").html(`add`);
$("#tagsWrapper #tagsEdit input").val("");
$("#tagsWrapper #tagsEdit input").removeClass("hidden");
} else if (action === "edit" && id !== undefined && name !== undefined) {
$("#tagsWrapper #tagsEdit").attr("action", "edit");
$("#tagsWrapper #tagsEdit").attr("tagid", id);
$("#tagsWrapper #tagsEdit .title").html("Edit tag name");
$("#tagsWrapper #tagsEdit button").html(`save`);
$("#tagsWrapper #tagsEdit input").val(name);
$("#tagsWrapper #tagsEdit input").removeClass("hidden");
} else if (action === "remove" && id !== undefined && name !== undefined) {
$("#tagsWrapper #tagsEdit").attr("action", "remove");
$("#tagsWrapper #tagsEdit").attr("tagid", id);
$("#tagsWrapper #tagsEdit .title").html("Delete tag " + name);
$("#tagsWrapper #tagsEdit button").html(`delete`);
$("#tagsWrapper #tagsEdit input").addClass("hidden");
} else if (action === "clearPb" && id !== undefined && name !== undefined) {
$("#tagsWrapper #tagsEdit").attr("action", "clearPb");
$("#tagsWrapper #tagsEdit").attr("tagid", id);
$("#tagsWrapper #tagsEdit .title").html("Clear PB for tag " + name);
$("#tagsWrapper #tagsEdit button").html(`clear`);
$("#tagsWrapper #tagsEdit input").addClass("hidden");
}
if (!isPopupVisible(wrapperId)) {
$("#tagsWrapper")
.stop(true, true)
.css("opacity", 0)
.removeClass("hidden")
.animate({ opacity: 1 }, 125, () => {
const input = $("#tagsWrapper #tagsEdit input");
if (!input.hasClass("hidden")) {
$("#tagsWrapper #tagsEdit input").trigger("focus");
} else {
$("#tagsWrapper").trigger("focus");
}
});
}
}
function hide(): void {
if (isPopupVisible(wrapperId)) {
$("#tagsWrapper #tagsEdit").attr("action", "");
$("#tagsWrapper #tagsEdit").attr("tagid", "");
$("#tagsWrapper")
.stop(true, true)
.css("opacity", 1)
.animate(
{
opacity: 0,
},
125,
() => {
$("#tagsWrapper").addClass("hidden");
Skeleton.remove(wrapperId);
}
);
}
}
async function apply(): Promise<void> {
const action = $("#tagsWrapper #tagsEdit").attr("action");
const propTagName = $("#tagsWrapper #tagsEdit input").val() as string;
const tagName = propTagName.replaceAll(" ", "_");
const tagId = $("#tagsWrapper #tagsEdit").attr("tagid") as string;
hide();
Loader.show();
if (action === "add") {
const response = await Ape.users.createTag(tagName);
if (response.status !== 200) {
Notifications.add(
"Failed to add tag: " + response.message.replace(tagName, propTagName),
-1
);
} else {
if (response.data === null) {
Notifications.add("Tag was added but data returned was null", -1);
Loader.hide();
return;
}
Notifications.add("Tag added", 1);
DB.getSnapshot()?.tags?.push({
display: propTagName,
name: response.data.name,
_id: response.data._id,
personalBests: {
time: {},
words: {},
quote: {},
zen: {},
custom: {},
},
});
void Settings.update();
}
} else if (action === "edit") {
const response = await Ape.users.editTag(tagId, tagName);
if (response.status !== 200) {
Notifications.add("Failed to edit tag: " + response.message, -1);
} else {
Notifications.add("Tag updated", 1);
DB.getSnapshot()?.tags?.forEach((tag) => {
if (tag._id === tagId) {
tag.name = tagName;
tag.display = propTagName;
}
});
void Settings.update();
}
} else if (action === "remove") {
const response = await Ape.users.deleteTag(tagId);
if (response.status !== 200) {
Notifications.add("Failed to remove tag: " + response.message, -1);
} else {
Notifications.add("Tag removed", 1);
DB.getSnapshot()?.tags?.forEach((tag, index: number) => {
if (tag._id === tagId) {
DB.getSnapshot()?.tags?.splice(index, 1);
}
});
void Settings.update();
}
} else if (action === "clearPb") {
const response = await Ape.users.deleteTagPersonalBest(tagId);
if (response.status !== 200) {
Notifications.add("Failed to clear tag pb: " + response.message, -1);
} else {
Notifications.add("Tag PB cleared", 1);
DB.getSnapshot()?.tags?.forEach((tag) => {
if (tag._id === tagId) {
tag.personalBests = {
time: {},
words: {},
quote: {},
zen: {},
custom: {},
};
}
});
void Settings.update();
}
}
Loader.hide();
}
$("#tagsWrapper").on("click", (e) => {
if ($(e.target).attr("id") === "tagsWrapper") {
hide();
}
});
$("#tagsWrapper #tagsEdit form").on("submit", (e) => {
e.preventDefault();
void apply();
});
$(".pageSettings .section.tags").on("click", ".addTagButton", () => {
show("add");
});
$(".pageSettings .section.tags").on(
"click",
".tagsList .tag .editButton",
(e) => {
const tagid = $(e.currentTarget).parent(".tag").attr("data-id");
const name = $(e.currentTarget).parent(".tag").attr("data-display");
show("edit", tagid, name);
}
);
$(".pageSettings .section.tags").on(
"click",
".tagsList .tag .clearPbButton",
(e) => {
const tagid = $(e.currentTarget).parent(".tag").attr("data-id");
const name = $(e.currentTarget).parent(".tag").attr("data-display");
show("clearPb", tagid, name);
}
);
$(".pageSettings .section.tags").on(
"click",
".tagsList .tag .removeButton",
(e) => {
const tagid = $(e.currentTarget).parent(".tag").attr("data-id");
const name = $(e.currentTarget).parent(".tag").attr("data-display");
show("remove", tagid, name);
}
);
$(document).on("keydown", (event) => {
if (event.key === "Escape" && isPopupVisible(wrapperId)) {
hide();
event.preventDefault();
}
});
Skeleton.save(wrapperId);