Skip to content

Commit 18c465e

Browse files
authored
impr: add validation for preset names (@fehmer) (monkeytypegame#6969)
1 parent c08572b commit 18c465e

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

frontend/src/ts/elements/input-validation.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export type ValidationOptions<T> = (T extends string
145145

146146
export type ValidatedHtmlInputElement = HTMLInputElement & {
147147
isValid: () => boolean | undefined;
148+
setValue: (val: string | null) => void;
148149
};
149150
/**
150151
* adds an 'InputIndicator` to the given `inputElement` and updates its status depending on the given validation
@@ -197,6 +198,15 @@ export function validateWithIndicator<T>(
197198

198199
const result = inputElement as ValidatedHtmlInputElement;
199200
result.isValid = () => isValid;
201+
result.setValue = (val: string | null) => {
202+
inputElement.value = val ?? "";
203+
if (val === null) {
204+
isValid = undefined;
205+
indicator.hide();
206+
} else {
207+
inputElement.dispatchEvent(new Event("input"));
208+
}
209+
};
200210

201211
return result;
202212
}

frontend/src/ts/modals/edit-preset.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import * as Settings from "../pages/settings";
66
import * as Notifications from "../elements/notifications";
77
import * as ConnectionState from "../states/connection";
88
import AnimatedModal from "../utils/animated-modal";
9-
import { PresetType, PresetTypeSchema } from "@monkeytype/schemas/presets";
9+
import {
10+
PresetNameSchema,
11+
PresetType,
12+
PresetTypeSchema,
13+
} from "@monkeytype/schemas/presets";
1014
import { getPreset } from "../controllers/preset-controller";
1115
import {
1216
ConfigGroupName,
@@ -17,6 +21,10 @@ import {
1721
} from "@monkeytype/schemas/configs";
1822
import { getDefaultConfig } from "../constants/default-config";
1923
import { SnapshotPreset } from "../constants/default-snapshot";
24+
import {
25+
ValidatedHtmlInputElement,
26+
validateWithIndicator,
27+
} from "../elements/input-validation";
2028

2129
const state = {
2230
presetType: "full" as PresetType,
@@ -26,6 +34,8 @@ const state = {
2634
setPresetToCurrent: false,
2735
};
2836

37+
let presetNameEl: ValidatedHtmlInputElement | null = null;
38+
2939
export function show(action: string, id?: string, name?: string): void {
3040
if (!ConnectionState.get()) {
3141
Notifications.add("You are offline", 0, {
@@ -39,11 +49,22 @@ export function show(action: string, id?: string, name?: string): void {
3949
beforeAnimation: async () => {
4050
$("#editPresetModal .modal .text").addClass("hidden");
4151
addCheckBoxes();
52+
if (!presetNameEl) {
53+
presetNameEl = validateWithIndicator(
54+
document.querySelector(
55+
"#editPresetModal .modal input"
56+
) as HTMLInputElement,
57+
{
58+
schema: PresetNameSchema,
59+
}
60+
);
61+
}
4262
if (action === "add") {
4363
$("#editPresetModal .modal").attr("data-action", "add");
4464
$("#editPresetModal .modal .popupTitle").html("Add new preset");
4565
$("#editPresetModal .modal .submit").html(`add`);
46-
$("#editPresetModal .modal input").val("");
66+
presetNameEl?.setValue(null);
67+
presetNameEl?.parentElement?.classList.remove("hidden");
4768
$("#editPresetModal .modal input").removeClass("hidden");
4869
$(
4970
"#editPresetModal .modal label.changePresetToCurrentCheckbox"
@@ -57,7 +78,9 @@ export function show(action: string, id?: string, name?: string): void {
5778
$("#editPresetModal .modal").attr("data-preset-id", id);
5879
$("#editPresetModal .modal .popupTitle").html("Edit preset");
5980
$("#editPresetModal .modal .submit").html(`save`);
60-
$("#editPresetModal .modal input").val(name);
81+
presetNameEl?.setValue(name);
82+
presetNameEl?.parentElement?.classList.remove("hidden");
83+
6184
$("#editPresetModal .modal input").removeClass("hidden");
6285
$(
6386
"#editPresetModal .modal label.changePresetToCurrentCheckbox"
@@ -85,6 +108,7 @@ export function show(action: string, id?: string, name?: string): void {
85108
$("#editPresetModal .modal .inputs").addClass("hidden");
86109
$("#editPresetModal .modal .presetType").addClass("hidden");
87110
$("#editPresetModal .modal .presetNameTitle").addClass("hidden");
111+
presetNameEl?.parentElement?.classList.add("hidden");
88112
}
89113
updateUI();
90114
},
@@ -238,6 +262,11 @@ async function apply(): Promise<void> {
238262
return;
239263
}
240264

265+
if (presetNameEl?.isValid() === false) {
266+
Notifications.add("Preset name is not valid", 0);
267+
return;
268+
}
269+
241270
hide();
242271

243272
Loader.show();

0 commit comments

Comments
 (0)