mv add form into advance

This commit is contained in:
realaravinth
2021-12-10 06:16:38 +05:30
parent 5afa531bb8
commit b2297eab6d
42 changed files with 62 additions and 62 deletions

View File

@@ -0,0 +1,34 @@
<fieldset class="sitekey__level-container" id="level-group-<.= level .>">
<legend class="sitekey__level-title">
Level <.= level .>
</legend>
<label class="sitekey-form__level-label" for="visitor<.= level .>"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor<.= level .>"
id="visitor<.= level .>"
/>
</label>
<label class="sitekey-form__level-label" for="difficulty<.= level .>">
Difficulty
<input
type="number"
name="difficulty<.= level .>"
class="sitekey-form__level-input"
id="difficulty<.= level .>"
/>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
<span class="sitekey-form__add-level-btn-spacer">Add level</span>
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
/>
</label>
</fieldset>

View File

@@ -0,0 +1,119 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@import '../../../../../reset';
@import '../../../../../vars';
@import '../../../../../components/button';
@import '../../../../../components/forms';
.sitekey-form {
display: flex;
flex-direction: column;
width: 90%;
justify-content: center;
align-items: center;
// box-sizing: content-box;
background-color: $white;
margin: auto;
padding-bottom: 30px;
}
.form__title-flex-container {
display: flex;
width: 100%;
border-bottom: 0.1px solid $light-grey;
}
.form__title {
padding-left: 10px;
font-size: 1rem;
padding: 0.75rem 1.25rem;
box-sizing: border-box;
text-align: left;
width: 100%;
border-bottom: 0.1px solid $light-grey;
}
.sitekey-form__label {
@include form-label;
}
.sitekey-form__input {
@include form-input;
width: 100%;
}
// level styling
.sitekey__level-container {
width: $form-content-width;
box-sizing: border-box;
display: flex;
border: none;
}
.sitekey__level-title {
margin-bottom: 10px;
margin-top: 5px;
}
.sitekey-form__level-label {
@include form-label;
font-size: 0.9rem;
}
.sitekey-form__level-name {
@include form-label;
display: block;
}
.sitekey-form__level-input {
@include form-input;
flex: 2;
}
.sitekey-form__add-level-btn-spacer {
color: $white;
}
.sitekey-form__level-add-level-button {
@include violet-button;
}
.sitekey-form__level-add-level-button:hover {
@include violet-button-hover;
}
.sitekey-form__level-label--hidden {
@include form-label;
color: $white;
flex: 1;
}
// level styling ends
.sitekey-form__submit {
@include violet-button;
display: block;
margin-top: 50px;
width: $form-content-width;
width: 90%;
}
.sitekey-form__submit:hover {
@include violet-button-hover;
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
.sitekey__level-container {
flex-direction: column;
}
.sitekey-form__level-input {
width: 100%;
}
.sitekey-form__level-label--hidden {
width: 100%;
}
.sitekey-form__level-add-level-button {
margin: auto;
}
.sitekey-form__add-level-btn-spacer {
display: none;
}
.sitekey-form__level-label {
width: 100%;
}

View File

@@ -0,0 +1,35 @@
<fieldset class="sitekey__level-container" id="level-group-<.= level .>">
<legend class="sitekey__level-title">
Level <.= level .>
</legend>
<label class="sitekey-form__level-label" for="visitor<.= level .>"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor<.= level .>"
value=""
id="visitor<.= level .>"
/>
</label>
<label class="sitekey-form__level-label" for="difficulty<.= level .>">
Difficulty
<input
type="number"
id="difficulty<.= level .>"
class="sitekey-form__level-input"
value=""
id="difficulty<.= level .>"
/>
</label>
<label class="sitekey-form__level-label--hidden" for="remove<.= level .>">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="remove"
id="remove<.= level .>"
value="Remove"
/>
</label>
</fieldset>

View File

@@ -0,0 +1,42 @@
<form class="sitekey-form" action="<.= crate::V1_API_ROUTES.levels.add .>" method="post">
<h1 class="form__title">
<.= form_title .>
</h1>
<label class="sitekey-form__label" for="description">
Description
<input
class="sitekey-form__input"
type="text"
name="description"
id="description"
required
<. if !form_description.trim().is_empty() { .>
value="<.= form_description .>"
<. } .>
/>
</label>
<label class="sitekey-form__label" for="duration">
Cooldown Duratoin(in seconds)
<input
class="sitekey-form__input"
type="number"
name="duration"
id="duration"
min=0
required
value="<.= form_duration .>"
/>
</label>
<. for level in 1..=levels { .>
<. if level == levels { .>
<. include!("./add-level.html"); .>
<. } else { .>
<. include!("./existing-level.html"); .>
<. } .>
<. } .>
<button class="sitekey-form__submit" type="submit">Submit</button>
</form>

View File

@@ -0,0 +1,15 @@
<. include!("../../../../components/headers/index.html"); .>
<. include!("../../../navbar/index.html"); .>
<div class="tmp-layout">
<. include!("../../../header/index.html"); .>
<main class="panel-main">
<. include!("../../../help-banner/index.html"); .>
<!-- Main content container -->
<div class="inner-container">
<!-- Main menu/ important actions roaster -->
<. include!("./form.html"); .>
</div>
<!-- end of container -->
<. include!("../../../../components/footers.html"); .>

View File

@@ -0,0 +1,198 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getNumLevels from "./levels/getNumLevels";
import {getAddForm, trim, addLevel} from "./setupTests";
import setup from "../../../../../components/error/setUpTests";
document.body.innerHTML = getAddForm();
document.body.appendChild(setup());
jest.useFakeTimers();
it("addLevelButton works", () => {
expect(getNumLevels()).toBe(1);
// add a level
addLevel(2, 4);
expect(getNumLevels()).toBe(2);
// add second level
addLevel(4, 9);
expect(getNumLevels()).toBe(3);
const a = document.body.innerHTML;
expect(trim(a)).toBe(trim(finalHtml()));
// try to add duplicate level
addLevel(2, 4);
expect(getNumLevels()).toBe(3);
// try to add negative parameters
addLevel(-4, -9);
expect(getNumLevels()).toBe(3);
});
const finalHtml = () => {
return `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<h1 class="form__title">
Add Sitekey
</h1>
<label class="sitekey-form__label" for="description">
Description
<input
class="sitekey-form__input"
type="text"
name="description"
id="description"
required=""
>
</label>
<label class="sitekey-form__label" for="duration">
Cooldown Duratoin(in seconds)
<input
class="sitekey-form__input"
type="number"
name="duration"
id="duration"
min="0"
required=""
value="30"
>
</label>
<fieldset class="sitekey__level-container" id="level-group-1">
<legend class="sitekey__level-title">
Level 1
</legend>
<label class="sitekey-form__level-label" for="visitor1"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor1"
id="visitor1"
>
</label>
<label class="sitekey-form__level-label" for="difficulty1">
Difficulty
<input
type="number"
name="difficulty1"
class="sitekey-form__level-input"
id="difficulty1"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level1">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level1"
id="remove-level1"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-2">
<legend class="sitekey__level-title">
Level 2
</legend>
<label class="sitekey-form__level-label" for="visitor2"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor2"
id="visitor2"
>
</label>
<label class="sitekey-form__level-label" for="difficulty2">
Difficulty
<input
type="number"
name="difficulty2"
class="sitekey-form__level-input"
id="difficulty2"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level2">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level2"
id="remove-level2"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-3">
<legend class="sitekey__level-title">
Level 3
</legend>
<label class="sitekey-form__level-label" for="visitor3"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor3"
id="visitor3"
>
</label>
<label class="sitekey-form__level-label" for="difficulty3">
Difficulty
<input
type="number"
name="difficulty3"
class="sitekey-form__level-input"
id="difficulty3"
>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
>
</label>
</fieldset>
<button class="sitekey-form__submit" type="submit">Submit</button>
</form>
<div id="err__container">
</div>
`;
};

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import validateLevel from "./levels/validateLevel";
import getNumLevels from "./levels/getNumLevels";
import * as UpdateLevel from "./levels/updateLevel";
import {
getRemoveButtonHTML,
addRemoveLevelButtonEventListener,
} from "./removeLevelButton";
import CONST from "./const";
import log from "../../../../../logger";
/**
* Gets executed when 'Add' Button is clicked to add levels
* Used to validate levels per m_captcha::defense::Defense's
* specifications
*/
const addLevel = (e: Event) => {
const eventTarget = <HTMLElement>e.target;
const PARENT = <HTMLLabelElement>eventTarget.parentElement;
const FIELDSET = <HTMLElement>PARENT.parentElement;
const onScreenLevel = getNumLevels();
const isValid = validateLevel(onScreenLevel);
log.debug(`[addLevelButton] isValid: ${isValid}`);
if (!isValid) {
const error = `Aborting level ${onScreenLevel} addition`;
return log.error(error);
}
FIELDSET.replaceChild(getRemoveButtonHTML(onScreenLevel), PARENT);
const newLevelElement = getHtml(onScreenLevel + 1);
FIELDSET.insertAdjacentElement("afterend", newLevelElement);
UpdateLevel.register(onScreenLevel);
addRemoveLevelButtonEventListener(onScreenLevel);
addLevelButtonAddEventListener();
const main = document.querySelector("body");
const style = main.style.display;
main.style.display = "none";
main.style.display = style;
};
/** adds onclick event listener */
const addLevelButtonAddEventListener = (): void => {
const addLevelButton = <HTMLElement>(
document.querySelector(`.${CONST.ADD_LEVEL_BUTTON}`)
);
addLevelButton.addEventListener("click", addLevel);
};
/**
* Generate HTML to be added when 'Add Level' button is clicked
* Check if './add-level.html` to see if this is up to date
*/
const getHtml = (level: number) => {
log.debug(`[generating HTML getHtml]level: ${level}`);
const fieldset = document.createElement("fieldset"); // new HTMLFieldSetElement();
fieldset.className = CONST.LEVEL_CONTAINER_CLASS;
fieldset.id = `${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`;
const legend = document.createElement("legend"); // new HTMLLegendElement();
legend.className = CONST.LEGEND_CLASS;
const legendText = document.createTextNode(`Level ${level}`);
legend.appendChild(legendText);
fieldset.appendChild(legend);
const vistitorLabel = document.createElement("label"); //document.createElement('label');
vistitorLabel.className = CONST.LABEL_CLASS;
const visitorText = document.createTextNode("Visitor");
vistitorLabel.appendChild(visitorText);
const visitor = document.createElement("input"); //document.createElement('input');
const visitorId = `${CONST.VISITOR_WITHOUT_LEVEL}${level}`;
visitor.className = CONST.LEVEL_INPUT_CLASS;
visitor.type = "number";
visitor.name = visitorId;
visitor.id = visitorId;
vistitorLabel.htmlFor = visitorId;
vistitorLabel.appendChild(visitor);
fieldset.appendChild(vistitorLabel);
const difficultyLabel = document.createElement("label");
difficultyLabel.className = CONST.LABEL_CLASS;
const difficultyText = document.createTextNode("Difficulty");
difficultyLabel.appendChild(difficultyText);
const difficulty = document.createElement("input");
const difficultyID = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${level}`;
difficulty.type = "number";
difficulty.name = difficultyID;
difficulty.className = CONST.LEVEL_INPUT_CLASS;
difficulty.id = difficultyID;
difficultyLabel.htmlFor = difficultyID;
difficultyLabel.appendChild(difficulty);
fieldset.appendChild(difficultyLabel);
const addLevelLabel = document.createElement("label");
addLevelLabel.className = CONST.REMOVE_LEVEL_LABEL_CLASS;
const addLevel = document.createElement("input");
addLevel.className = CONST.ADD_LEVEL_BUTTON;
addLevel.type = "button";
const addLevelButtonID = "add";
addLevel.name = addLevelButtonID;
addLevel.id = addLevelButtonID;
addLevelLabel.htmlFor = addLevelButtonID;
const addText = document.createTextNode("Add level");
addLevelLabel.appendChild(addText);
addLevel.value = "Add";
addLevelLabel.appendChild(addLevel);
fieldset.appendChild(addLevelLabel);
return fieldset;
};
export default addLevelButtonAddEventListener;

View File

@@ -0,0 +1,55 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const LABEL_INNER_TEXT_WITHOUT_LEVEL = "Level ";
const LABEL_CLASS = "sitekey-form__level-label";
const INPUT_ID_WITHOUT_LEVEL = "level";
const LEVEL_INPUT_CLASS = "sitekey-form__level-input";
const VISITOR_WITHOUT_LEVEL = "visitor";
const DIFFICULTY_WITHOUT_LEVEL = "difficulty";
const LEVEL_CONTAINER_CLASS = "sitekey__level-container";
const LEVEL_FIELDSET_ID_WITHOUT_LEVEL = "level-group-";
const LEGEND_CLASS = "sitekey__level-title";
const REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL = "remove-level";
const REMOVE_LEVEL_BUTTON_CLASS = "sitekey-form__level-remove-level-button";
const REMOVE_LEVEL_LABEL_TEXT = "Remove Level";
const REMOVE_LEVEL_LABEL_CLASS = "sitekey-form__level-label--hidden";
const ADD_LEVEL_BUTTON = "sitekey-form__level-add-level-button";
const CONST = {
LABEL_CLASS,
INPUT_ID_WITHOUT_LEVEL,
LEVEL_INPUT_CLASS,
LABEL_INNER_TEXT_WITHOUT_LEVEL,
VISITOR_WITHOUT_LEVEL,
DIFFICULTY_WITHOUT_LEVEL,
LEVEL_CONTAINER_CLASS,
LEVEL_FIELDSET_ID_WITHOUT_LEVEL,
LEGEND_CLASS,
ADD_LEVEL_BUTTON,
REMOVE_LEVEL_LABEL_CLASS,
REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL,
REMOVE_LEVEL_LABEL_TEXT,
REMOVE_LEVEL_BUTTON_CLASS,
};
export default CONST;

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { LEVELS } from "../levels";
import getFormUrl from "../../../../../../utils/getFormUrl";
import genJsonPayload from "../../../../../../utils/genJsonPayload";
import VIEWS from "../../../../../../views/v1/routes";
import validateDescription from "./validateDescription";
import validateDuration from "./validateDuration";
import createError from "../../../../../../components/error";
export const SITE_KEY_FORM_CLASS = "sitekey-form";
export const FORM = <HTMLFormElement>(
document.querySelector(`.${SITE_KEY_FORM_CLASS}`)
);
export const addSubmitEventListener = (): void =>
FORM.addEventListener("submit", submit, true);
const submit = async (e: Event) => {
e.preventDefault();
const description = validateDescription(e);
const duration = validateDuration();
const formUrl = getFormUrl(FORM);
const levels = LEVELS.getLevels();
console.debug(`[form submition]: levels: ${levels}`);
const payload = {
levels: levels,
duration,
description,
};
console.debug(`[form submition] json payload: ${JSON.stringify(payload)}`);
const res = await fetch(formUrl, genJsonPayload(payload));
if (res.ok) {
const data = await res.json();
window.location.assign(VIEWS.viewSitekey(data.key));
} else {
const err = await res.json();
createError(err.error);
}
};
export default addSubmitEventListener;

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import validateDescription from "./validateDescription";
import {getAddForm, fillDescription} from "../setupTests";
import {mockAlert} from "../../../../../../setUpTests";
import setup from "../../../../../../components/error/setUpTests";
mockAlert();
document.body.innerHTML = getAddForm();
const emptyErr = "can't be empty";
it("validateDescription workds", () => {
document.querySelector("body").appendChild(setup());
try {
const event = new Event("submit");
validateDescription(event);
} catch (e) {
expect(e.message).toContain(emptyErr);
}
// fill and validate
fillDescription("testing");
const event = new Event("submit");
validateDescription(event);
});

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import isBlankString from "../../../../../../utils/isBlankString";
const validateDescription = (e: Event): string => {
const inputElement = <HTMLInputElement>document.getElementById("description");
const val = inputElement.value;
const filed = "Description";
isBlankString(val, filed, e);
return val;
};
export default validateDescription;

View File

@@ -0,0 +1,68 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
//const validateDuration = (e: Event) => {
// const duartionElement = <HTMLInputElement>document.getElementById('duration');
// const duration = parseInt(duartionElement.value);
// if (!isNumber(duration) || Number.isNaN(duration)) {
// throw new Error('duration can contain nubers only');
// }
//
// if (duration <= 0) {
// throw new Error('duration must be greater than zero');
// }
// return duration;
//};
//
//export default validateDuration;
import validateDuration from "./validateDuration";
import {getAddForm, fillDuration} from "../setupTests";
document.body.innerHTML = getAddForm();
const emptyErr = "can't be empty";
const NaNErr = "duration can contain nubers only";
const zeroErr = "duration must be greater than zero";
const duration = 30;
it("validateDuration workds", () => {
try {
validateDuration();
} catch (e) {
expect(e.message).toContain(emptyErr);
}
// fill string error
try {
fillDuration("testing");
validateDuration();
} catch (e) {
expect(e.message).toContain(NaNErr);
}
// zero err
try {
fillDuration(0);
validateDuration();
} catch (e) {
expect(e.message).toContain(zeroErr);
}
fillDuration(duration);
expect(validateDuration()).toBe(duration);
});

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import isNumber from "../../../../../../utils/isNumber";
const validateDuration = (): number => {
const duartionElement = <HTMLInputElement>document.getElementById("duration");
const duration = parseInt(duartionElement.value);
if (!isNumber(duration) || Number.isNaN(duration)) {
throw new Error("duration can contain nubers only");
}
if (duration <= 0) {
throw new Error("duration must be greater than zero");
}
return duration;
};
export default validateDuration;

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import addLevelButtonAddEventListener from "./addLevelButton";
import addSubmitEventListener from "./form";
export const index = (): void => {
addLevelButtonAddEventListener();
addSubmitEventListener();
};

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getLevelFields from "./getLevelFields";
import {
getAddForm,
level1,
level2,
fillAddLevel,
addLevel,
} from "../setupTests";
document.body.innerHTML = getAddForm();
const visNumErr = "visitor can contain nubers only";
const diffNumErr = "difficulty can contain nubers only";
it("get levels fields works", () => {
addLevel(level1.visitor_threshold, level1.difficulty_factor);
expect(getLevelFields(1)).toEqual(level1);
// NaN visitor
try {
fillAddLevel("test", level2.difficulty_factor);
getLevelFields(2);
} catch (e) {
expect(e.message).toBe(visNumErr);
}
// Nan difficulty_factor
try {
fillAddLevel(level2.visitor_threshold, "fooasdads");
getLevelFields(2);
} catch (e) {
expect(e.message).toBe(diffNumErr);
}
addLevel(level2.visitor_threshold, level2.difficulty_factor);
expect(getLevelFields(2)).toEqual(level2);
});

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Level } from "./index";
import CONST from "../const";
import log from "../../../../../../logger";
/** Fetches level from DOM using the ID passesd and validates */
const getLevelFields = (id: number): Level => {
log.debug(`[getLevelFields]: id: ${id}`);
const visitorID = CONST.VISITOR_WITHOUT_LEVEL + id.toString();
const difficultyID = CONST.DIFFICULTY_WITHOUT_LEVEL + id.toString();
const visitorElement = <HTMLInputElement>document.getElementById(visitorID);
const difficultyElement = <HTMLInputElement>(
document.getElementById(difficultyID)
);
const visitor_threshold = parseInt(visitorElement.value);
const difficulty_factor = parseInt(difficultyElement.value);
if (Number.isNaN(visitor_threshold)) {
throw new Error("visitor can contain nubers only");
}
if (Number.isNaN(difficulty_factor)) {
throw new Error("difficulty can contain nubers only");
}
const level: Level = {
difficulty_factor,
visitor_threshold,
};
log.debug(
`[getLevelFields.ts] visitor: ${visitor_threshold} difficulty: ${difficulty_factor}`
);
return level;
};
export default getLevelFields;

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getNumLevels from "./getNumLevels";
import {getAddForm, addLevel} from "../setupTests";
document.body.innerHTML = getAddForm();
it("get num levels works", () => {
expect(getNumLevels()).toBe(1);
addLevel(2, 4);
expect(getNumLevels()).toBe(2);
addLevel(4, 9);
expect(getNumLevels()).toBe(3);
});

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CONST from "../const";
import log from "../../../../../../logger";
/** returns number of level input fields currently in DOM */
const getNumLevels = (): number => {
let numLevels = 0;
document
.querySelectorAll(`.${CONST.LEVEL_CONTAINER_CLASS}`)
.forEach(() => numLevels++);
log.debug(`[getNumLevels]: numLevels: ${numLevels}`);
return numLevels;
};
export default getNumLevels;

View File

@@ -0,0 +1,145 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import log from "../../../../../../logger";
/** Datatype represenging an mCaptcha level */
export type Level = {
difficulty_factor: number;
visitor_threshold: number;
};
/** Datatype representing a collection of mCaptcha levels */
class Levels {
levels: Array<Level>;
constructor() {
this.levels = [];
}
add = (newLevel: Level) => {
log.debug(`[levels/index.ts] levels lenght: ${this.levels.length}`);
if (newLevel.difficulty_factor <= 0) {
throw new Error(
`Level ${this.levels.length}'s difficulty must be greater than zero`,
);
}
if (newLevel.visitor_threshold <= 0) {
throw new Error(
`Level ${this.levels.length}'s visitors must be greater than zero`,
);
}
if (this.levels.length == 0) {
this.levels.push(newLevel);
return true;
}
let count = 1;
this.levels.forEach(level => {
if (level.visitor_threshold >= newLevel.visitor_threshold) {
const msg = `Level ${this.levels.length}'s visitor count should be greater than previous levels(Level ${count} is greater)`;
throw new Error(msg);
} else if (level.difficulty_factor >= newLevel.difficulty_factor) {
const msg = `Level ${this.levels.length} difficulty should be greater than previous levels(Level ${count} is greater)`;
throw new Error(msg);
} else {
count++;
}
});
this.levels.push(newLevel);
};
get = () => this.levels;
}
/** Singleton that does manipulations on Levels object */
export const LEVELS = (function() {
const levels = new Levels();
return {
/** get levels */
getLevels: () => levels.get(),
/** add new level */
add: (newLevel: Level) => levels.add(newLevel),
/** update levels */
update: (updateLevel: Level, id: number) => {
const tmpLevel = new Levels();
id -= 1;
try {
for (let i = 0; i < levels.levels.length; i++) {
if (id == i) {
tmpLevel.add(updateLevel);
} else {
tmpLevel.add(levels.levels[i]);
}
}
levels.levels = tmpLevel.levels;
log.debug("post update:");
LEVELS.print();
return true;
} catch (e) {
log.debug(e);
return false;
}
},
print: () =>
levels.levels.forEach(level =>
log.debug(
`difficulty_factor: ${level.difficulty_factor} visitor ${level.visitor_threshold}`,
),
),
/** remove level */
remove: (id: number) => {
log.debug(`[LEVELS] received order to remove ${id} element`);
const tmpLevel = new Levels();
id -= 1;
try {
for (let i = 0; i < levels.levels.length; i++) {
if (id != i) {
tmpLevel.add(levels.levels[i]);
} else {
log.debug(`[LEVELS] removing ${i} element`);
const rmElement = levels.levels[i];
log.debug(
`[LEVELS] removing element:
difficulty_factor: ${rmElement.difficulty_factor}
visitor_threshold: ${rmElement.visitor_threshold}`,
);
}
}
levels.levels = tmpLevel.levels;
log.debug("Post remove:");
LEVELS.print();
return true;
} catch (e) {
log.debug(e);
return false;
}
},
};
})();

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {LEVELS, Level} from "./index";
import {level1, level1visErr, level1diffErr, level2} from "../setupTests";
const visitorErr = "visitor count should be greater than previous levels";
const difficultyErr = "difficulty should be greater than previous levels";
const zeroVisError = "visitors must be greater than zero";
const zeroDiffError = "difficulty must be greater than zero";
const zeroVis: Level = {
difficulty_factor: 10,
visitor_threshold: 0,
};
const zeroDiff: Level = {
difficulty_factor: 0,
visitor_threshold: 10,
};
it("LEVELS works", () => {
// add level
LEVELS.add(level1);
expect(LEVELS.getLevels()).toEqual([level1]);
// add visitor count < prev level
try {
LEVELS.add(level1visErr);
} catch (e) {
expect(e.message).toContain(visitorErr);
}
// add difficulty < prev level
try {
LEVELS.add(level1diffErr);
} catch (e) {
expect(e.message).toContain(difficultyErr);
}
// add second level
LEVELS.add(level2);
expect(LEVELS.getLevels()).toEqual([level1, level2]);
// update level
const newLevel2 = level2;
newLevel2.difficulty_factor = 8000;
LEVELS.update(newLevel2, 2);
expect(LEVELS.getLevels()).toEqual([level1, newLevel2]);
// update second level
LEVELS.remove(1);
expect(LEVELS.getLevels()).toEqual([newLevel2]);
// visitor is 0
try {
LEVELS.add(zeroVis);
} catch (e) {
expect(e.message).toContain(zeroVisError);
}
// difficulty is 0
try {
LEVELS.add(zeroDiff);
} catch (e) {
expect(e.message).toContain(zeroDiffError);
}
});

View File

@@ -0,0 +1,62 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CONST from "../const";
import getLevelFields from "./getLevelFields";
import { LEVELS } from "./index";
import createError from "../../../../../../components/error";
/** on-change event handler to update level */
const updateLevel = (e: Event): void => {
const target = <HTMLInputElement>e.target;
const id = target.id;
let level;
if (id.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
level = parseInt(id.slice(CONST.VISITOR_WITHOUT_LEVEL.length));
}
if (id.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
level = parseInt(id.slice(CONST.DIFFICULTY_WITHOUT_LEVEL.length));
}
if (Number.isNaN(level)) {
console.error("[updateLevel.ts] level # computed is not correct, got NaN");
}
try {
const updatedLevel = getLevelFields(level);
LEVELS.update(updatedLevel, level);
} catch (e) {
createError(e.message);
}
};
/** registers on-change event handlers to update levels */
export const register = (id: number): void => {
const visitorID = CONST.VISITOR_WITHOUT_LEVEL + id.toString();
const difficultyID = CONST.DIFFICULTY_WITHOUT_LEVEL + id.toString();
const visitorElement = <HTMLInputElement>document.getElementById(visitorID);
const difficultyElement = <HTMLInputElement>(
document.getElementById(difficultyID)
);
visitorElement.addEventListener("input", updateLevel, false);
difficultyElement.addEventListener("input", updateLevel, false);
};

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import validateLevel from "./validateLevel";
import {getAddForm, level1, fillAddLevel} from "../setupTests";
import setup from "../../../../../../components/error/setUpTests";
document.body.innerHTML = getAddForm();
document.body.appendChild(setup());
it("validate levels fields works", () => {
// null error
expect(validateLevel(1)).toEqual(false);
fillAddLevel(level1.visitor_threshold, level1.difficulty_factor);
expect(validateLevel(1)).toEqual(true);
// zero visitor error
fillAddLevel(0, level1.difficulty_factor);
expect(validateLevel(1)).toEqual(false);
// zero difficulty error
fillAddLevel(level1.visitor_threshold, 0);
expect(validateLevel(1)).toEqual(false);
});

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {LEVELS} from "./index";
import getLevelFields from "./getLevelFields";
import createError from "../../../../../../components/error/";
/**
* Fetches level from DOM using the ID passesd and validates
* its contents
* */
const validateLevel = (id: number): boolean => {
try {
const level = getLevelFields(id);
LEVELS.add(level);
return true;
} catch (e) {
createError(e.message);
return false;
}
};
export default validateLevel;

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { LEVELS } from "../levels/index";
import updateLevelNumbersOnDOM from "./updateDom";
import CONST from "../const";
import log from "../../../../../../logger";
const REMOVE_LEVEL_BUTTON = "sitekey-form__level-remove-level-button";
/**
* Gets executed when 'Remove' Button is clicked to remove levels
*/
const removeLevel = (e: Event) => {
const eventTarget = <HTMLElement>e.target;
const PARENT = <HTMLElement>eventTarget.parentElement;
const FIELDSET = <HTMLElement>PARENT.parentElement;
const levelNum = parseInt(
eventTarget.id.slice(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL.length)
);
if (Number.isNaN(levelNum)) {
const msg =
"[removeLevelButton.ts] error in parsing level number from remove button ID";
//log.error(msg);
throw new Error(msg);
}
updateLevelNumbersOnDOM(levelNum);
LEVELS.remove(levelNum);
FIELDSET.remove();
};
/** adds onclick event listener */
export const addRemoveLevelButtonEventListener = (level: number): void => {
const removeButton = document.getElementById(
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${level}`
);
removeButton.addEventListener("click", removeLevel);
};
/** adds onclick event listener to all remove buttons */
export const addRemoveLevelButtonEventListenerAll = (): void => {
const removeButtons = document.querySelectorAll(`.${REMOVE_LEVEL_BUTTON}`);
removeButtons.forEach((button) =>
button.addEventListener("click", removeLevel)
);
};
/**
* Generate Remove button HTML. On-click handler should be added
* seprately
*/
export const getRemoveButtonHTML = (level: number): HTMLLabelElement => {
log.log(`[generating HTML getHtml]level: ${level}`);
const btn = document.createElement("input");
btn.className = CONST.REMOVE_LEVEL_BUTTON_CLASS;
btn.type = "button";
const id = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${level}`;
btn.name = id;
btn.id = id;
btn.value = "x";
const removeLabel = document.createElement("label");
removeLabel.className = CONST.REMOVE_LEVEL_LABEL_CLASS;
const removeLabelText = document.createTextNode("RemoveLevel");
removeLabel.appendChild(removeLabelText);
removeLabel.appendChild(btn);
removeLabel.htmlFor = id;
return removeLabel;
};

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getNumLevels from "../levels/getNumLevels";
import { getAddForm, addLevel } from "../setupTests";
import CONST from "../const";
import log from "../../../../../../logger";
import { MODE } from "../../../../../../logger";
document.body.innerHTML = getAddForm();
const setUp = () => {
expect(getNumLevels()).toBe(1);
// add a level
addLevel(2, 2);
expect(getNumLevels()).toBe(2);
// add second level
addLevel(4, 4);
expect(getNumLevels()).toBe(3);
// add thrid level
addLevel(5, 5);
expect(getNumLevels()).toBe(4);
};
log.setMode(MODE.none);
it("removeLevelButton works", () => {
setUp();
for (let i = 1; i < 4; i++) {
const l1 = <HTMLButtonElement>(
document.getElementById(
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${1}`
)
);
const expecting = 4 - i;
l1.click();
const currentLevels = getNumLevels();
expect(currentLevels).toBe(expecting);
}
});

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getNumLevels from "../../levels/getNumLevels";
import CONST from "../../const";
import log from "../../../../../../../logger";
import updateLabels from "./updateLabel";
import updateInputs from "./updateInputs";
import updateRemoveButton from "./updateRemoveButton";
import updateLevelGroup from "./updateLevelGroup";
/**
* update level number on fieldset legends and their ids too
* @param {number} id - level number that was ordered to remove.
* All updates are made relative to id
* */
const updateLevelNumbersOnDOM = (id: number): void => {
const numLevels = getNumLevels();
if (id == numLevels) {
throw new Error(
"Can't remove the very fist element, it has to be first added to DOM"
);
}
// since I'm doing id+1, I have to remove id after I'm done
// with inclreasing level numbers
for (let i = id + 1; i <= numLevels; i++) {
const newLevel = i - 1;
const levelGroup = document.querySelector(
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${i}`
);
if (levelGroup === null) {
const msg = `[removeLevelButton.ts]:
error when trying to fetch level group field set ${i}. got null`;
log.error(msg);
throw new Error(msg);
}
// rename legend
const legend = levelGroup.getElementsByTagName("legend")[0];
const legendText = document.createTextNode(`Level ${newLevel}`);
const newLegend = document.createElement("legend");
newLegend.className = legend.className;
newLegend.appendChild(legendText);
legend.replaceWith(newLegend);
// rename labels
updateLabels(levelGroup, newLevel);
// rename inputs
updateInputs(levelGroup, newLevel);
if (i != numLevels) {
// update remove button
updateRemoveButton(levelGroup, newLevel);
}
// update levelGroup's ID
updateLevelGroup(levelGroup, newLevel);
// TODO change remove button ID as well
/* TODO
* change field set ID
* change legend inner Text
* change visitor lable for value
* change visitor input id
* change difficulty for value
* change difficulty input id
*/
}
};
export default updateLevelNumbersOnDOM;

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getNumLevels from "../../levels/getNumLevels";
import { getAddForm, addLevel } from "../../setupTests";
document.body.innerHTML = getAddForm();
export const setupAddlevels = (): void => {
expect(getNumLevels()).toBe(1);
// add a level
addLevel(2, 2);
expect(getNumLevels()).toBe(2);
// add second level
addLevel(4, 4);
expect(getNumLevels()).toBe(3);
// add thrid level
addLevel(5, 5);
expect(getNumLevels()).toBe(4);
};

View File

@@ -0,0 +1,241 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {getAddForm, trim} from "../../setupTests";
import updateInputs from "./updateInputs";
import CONST from "../../const";
import log from "../../../../../../../logger";
import {MODE} from "../../../../../../../logger";
import {setupAddlevels} from "./setupTests";
document.body.innerHTML = getAddForm();
log.setMode(MODE.none);
it("updateInputs works", () => {
setupAddlevels();
// removing level 2
const level = 2;
const levelGroup = document.querySelector(
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`,
);
const newLevel = 20;
updateInputs(levelGroup, newLevel);
const inputs = <NodeListOf<HTMLInputElement>>(
levelGroup.querySelectorAll(`.${CONST.LEVEL_INPUT_CLASS}`)
);
inputs.forEach(input => {
if (input.id.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
expect(input.id).toBe(`${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`);
console.log("checking visitor");
} else {
// if (input.id.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
console.log("checking difficulty");
expect(input.id).toBe(`${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`);
}
});
expect(trim(document.body.innerHTML)).toBe(trim(update()));
});
/** get initial form to test remove button functionality */
export const update = (): string => {
return `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<h1 class="form__title">
Add Sitekey
</h1>
<label class="sitekey-form__label" for="description">
Description
<input
class="sitekey-form__input"
type="text"
name="description"
id="description"
required=""
>
</label>
<label class="sitekey-form__label" for="duration">
Cooldown Duratoin(in seconds)
<input
class="sitekey-form__input"
type="number"
name="duration"
id="duration"
min="0"
required=""
value="30"
>
</label>
<fieldset class="sitekey__level-container" id="level-group-1">
<legend class="sitekey__level-title">
Level 1
</legend>
<label class="sitekey-form__level-label" for="visitor1"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor1"
id="visitor1"
>
</label>
<label class="sitekey-form__level-label" for="difficulty1">
Difficulty
<input
type="number"
name="difficulty1"
class="sitekey-form__level-input"
id="difficulty1"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level1">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level1"
id="remove-level1"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-2">
<legend class="sitekey__level-title">
Level 2
</legend>
<label class="sitekey-form__level-label" for="visitor2"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor20"
id="visitor20"
>
</label>
<label class="sitekey-form__level-label" for="difficulty2">
Difficulty
<input
type="number"
name="difficulty20"
class="sitekey-form__level-input"
id="difficulty20"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level2">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level2"
id="remove-level2"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-3">
<legend class="sitekey__level-title">
Level 3
</legend>
<label class="sitekey-form__level-label" for="visitor3"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor3"
id="visitor3"
>
</label>
<label class="sitekey-form__level-label" for="difficulty3">
Difficulty
<input
type="number"
name="difficulty3"
class="sitekey-form__level-input"
id="difficulty3"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level3">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level3"
id="remove-level3"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-4">
<legend class="sitekey__level-title">
Level 4
</legend>
<label class="sitekey-form__level-label" for="visitor4"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor4"
id="visitor4"
>
</label>
<label class="sitekey-form__level-label" for="difficulty4">
Difficulty
<input
type="number"
name="difficulty4"
class="sitekey-form__level-input"
id="difficulty4"
>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
>
</label>
</fieldset>
<button class="sitekey-form__submit" type="submit">Submit</button>
</form>
`;
};

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CONST from "../../const";
import log from "../../../../../../../logger";
/** update input IDs with new level */
const updateInput = (levelGroup: Element, newLevel: number): void => {
const inputs = <NodeListOf<HTMLInputElement>>(
levelGroup.querySelectorAll(`.${CONST.LEVEL_INPUT_CLASS}`)
);
log.log(inputs);
inputs.forEach(input => {
if (input.id.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
log.log(`${input.id}`);
log.log("changing visitor_threshold input");
const id = `${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`;
input.id = id;
input.name = id;
} else if (input.id.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
log.log("changing difficulty input");
const id = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`;
input.id = id;
input.name = id;
} else {
if (input.id != "add") {
throw new Error(`Did you add an extra input to DOM? ${input.id} ${input.className} ${input.name}`);
}
}
});
};
export default updateInput;

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 221 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { trim } from "../../setupTests";
import updateLabels from "./updateLabel";
import CONST from "../../const";
import log from "../../../../../../../logger";
import { MODE } from "../../../../../../../logger";
/** get initial form to test remove button functionality */
export const labelLevel = (level: number): string => {
return `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<fieldset class="sitekey__level-container" id="level-group-2">
<legend class="sitekey__level-title">
Level 2
</legend>
<label class="sitekey-form__level-label" for="visitor${level}"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor2"
id="visitor2"
>
</label>
<label class="sitekey-form__level-label" for="difficulty${level}">
Difficulty
<input
type="number"
name="difficulty2"
class="sitekey-form__level-input"
id="difficulty2"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level${level}">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level2"
id="remove-level2"
value="x"
>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
>
</label>
</fieldset>
</form>
`;
};
document.body.innerHTML = labelLevel(2);
log.setMode(MODE.none);
it("addLevelButton works", () => {
// removing level 2
const level = 2;
const levelGroup = document.querySelector(
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`
);
const newLevel = 20;
updateLabels(levelGroup, newLevel);
const labels = <NodeListOf<HTMLLabelElement>>(
levelGroup.querySelectorAll(`.${CONST.LABEL_CLASS}`)
);
log.log(labels);
labels.forEach((label) => {
log.log(`${label.htmlFor}`);
if (label.htmlFor.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
expect(label.htmlFor).toBe(`${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`);
} else if (label.htmlFor.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
expect(label.htmlFor).toBe(
`${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`
);
} else if (
label.htmlFor.includes(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL)
) {
expect(label.htmlFor).toBe(
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`
);
} else {
throw new Error("Did you add an extra label to DOM?");
}
});
expect(trim(document.body.innerHTML)).toBe(trim(labelLevel(newLevel)));
});

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CONST from "../../const";
import log from "../../../../../../../logger";
/** update level lables to match new level */
const updateLabels = (levelGroup: Element, newLevel: number): void => {
// rename labels
const labels = <NodeListOf<HTMLLabelElement>>(
levelGroup.querySelectorAll("label")
);
log.log(labels);
labels.forEach((label) => {
log.log(`${label.htmlFor}`);
const currentFor = label.htmlFor;
if (currentFor.includes(CONST.VISITOR_WITHOUT_LEVEL)) {
label.htmlFor = `${CONST.VISITOR_WITHOUT_LEVEL}${newLevel}`;
} else if (currentFor.includes(CONST.DIFFICULTY_WITHOUT_LEVEL)) {
label.htmlFor = `${CONST.DIFFICULTY_WITHOUT_LEVEL}${newLevel}`;
} else if (
currentFor.includes(CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL)
) {
label.htmlFor = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`;
} else {
if (currentFor != "add") {
throw new Error(
`Did you add an extra label to DOM? Found label with for: ${currentFor}`
);
}
}
});
};
export default updateLabels;

View File

@@ -0,0 +1,101 @@
/*
* Copyright (C) 221 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { trim} from "../../setupTests";
import updateLevelGroup from "./updateLevelGroup";
import CONST from "../../const";
import log from "../../../../../../../logger";
import {MODE} from "../../../../../../../logger";
/** get initial form to test remove button functionality */
export const labelLevel = (level: number): string => {
return `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<fieldset class="sitekey__level-container" id="level-group-${level}">
<legend class="sitekey__level-title">
Level 2
</legend>
<label class="sitekey-form__level-label" for="visitor"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor2"
id="visitor2"
>
</label>
<label class="sitekey-form__level-label" for="difficulty">
Difficulty
<input
type="number"
name="difficulty2"
class="sitekey-form__level-input"
id="difficulty2"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level2"
id="remove-level2"
value="x"
>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
>
</label>
</fieldset>
</form>
`;
};
document.body.innerHTML = labelLevel(2);
log.setMode(MODE.none);
it("update levelGroup works", () => {
// removing level 2
const level = 2;
const levelGroup = document.querySelector(
`#${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${level}`,
);
const newLevel = 20;
updateLevelGroup(levelGroup, newLevel);
expect(levelGroup.id).toBe(
`${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${newLevel}`,
);
expect(trim(document.body.innerHTML)).toBe(trim(labelLevel(newLevel)));
});

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CONST from "../../const";
/** update level grup to match new level */
const updateLevelGroup = (levelGroup: Element, newLevel: number): string =>
(levelGroup.id = `${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}${newLevel}`);
export default updateLevelGroup;

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 221 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {trim} from "../../setupTests";
import updateRemoveButton from "./updateRemoveButton";
import CONST from "../../const";
import log from "../../../../../../../logger";
import {MODE} from "../../../../../../../logger";
/** get initial form to test remove button functionality */
export const labelLevel = (level: number): string => {
return `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<fieldset class="sitekey__level-container" id="level-group-">
<legend class="sitekey__level-title">
Level 2
</legend>
<label class="sitekey-form__level-label" for="visitor"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor2"
id="visitor2"
>
</label>
<label class="sitekey-form__level-label" for="difficulty">
Difficulty
<input
type="number"
name="difficulty2"
class="sitekey-form__level-input"
id="difficulty2"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level${level}"
id="remove-level${level}"
value="x"
>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
>
</label>
</fieldset>
</form>
`;
};
const level = 2;
document.body.innerHTML = labelLevel(level);
log.setMode(MODE.none);
it("update remove button works", () => {
// removing level 2
const levelGroup = document.getElementById(
`${CONST.LEVEL_FIELDSET_ID_WITHOUT_LEVEL}`,
);
const newLevel = 20;
updateRemoveButton(levelGroup, newLevel);
const button = <HTMLInputElement>(
levelGroup.querySelector(`.${CONST.REMOVE_LEVEL_BUTTON_CLASS}`)
);
expect(button.id).toBe(
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`,
);
expect(button.name).toBe(
`${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`,
);
expect(trim(document.body.innerHTML)).toBe(trim(labelLevel(newLevel)));
});

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import CONST from "../../const";
/** update remove level button's ID */
const updateRemoveButton = (levelGroup: Element, newLevel: number): void => {
// rename button
const button = <HTMLInputElement>(
levelGroup.querySelector(`.${CONST.REMOVE_LEVEL_BUTTON_CLASS}`)
);
const id = `${CONST.REMOVE_LEVEL_BUTTON_ID_WITHOUT_LEVEL}${newLevel}`;
button.id = id;
button.name = id;
};
export default updateRemoveButton;

View File

@@ -0,0 +1,358 @@
/*
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import getNumLevels from "./levels/getNumLevels";
import { Level } from "./levels/index";
import CONST from "./const";
import addLevelButtonAddEventListener from "./addLevelButton";
/** get rid of all whitespaces, useful when comparing DOM states */
export const trim = (s: string): string => s.replace(/\s/g, "");
export const level1: Level = {
difficulty_factor: 200,
visitor_threshold: 500,
};
export const level1diffErr: Level = {
difficulty_factor: 100,
visitor_threshold: 600,
};
export const level1visErr: Level = {
difficulty_factor: 600,
visitor_threshold: 400,
};
export const level2: Level = {
difficulty_factor: 400,
visitor_threshold: 700,
};
/** add level to DOM by filling add level form and clicking "Add" button */
export const addLevel = (visitor: number, diff: number): void => {
fillAddLevel(visitor, diff);
const addLevelButton = <HTMLElement>(
document.querySelector(`.${CONST.ADD_LEVEL_BUTTON}`)
);
addLevelButton.click();
};
/** Fill add level form without clicking add button */
export const fillAddLevel = (
visitor: number | string,
diff: number | string
): void => {
addLevelButtonAddEventListener();
const level = getNumLevels();
const visitorField = <HTMLInputElement>(
document.getElementById(`${CONST.VISITOR_WITHOUT_LEVEL}${level}`)
);
visitorField.value = visitor.toString();
const diffField = <HTMLInputElement>(
document.getElementById(`${CONST.DIFFICULTY_WITHOUT_LEVEL}${level}`)
);
diffField.value = diff.toString();
};
/** Fill add level form without clicking add button */
export const editLevel = (
level: number,
visitor?: number,
diff?: number
): void => {
if (visitor !== undefined) {
const visitorField = <HTMLInputElement>(
document.getElementById(`${CONST.VISITOR_WITHOUT_LEVEL}${level}`)
);
visitorField.value = visitor.toString();
}
if (diff !== undefined) {
const diffField = <HTMLInputElement>(
document.getElementById(`${CONST.DIFFICULTY_WITHOUT_LEVEL}${level}`)
);
diffField.value = diff.toString();
}
};
/** Fill description in add level form */
export const fillDescription = (description: string): void => {
const inputElement = <HTMLInputElement>document.getElementById("description");
inputElement.value = description;
};
/** Fill duration in add level form */
export const fillDuration = (duration: number | string): void => {
const inputElement = <HTMLInputElement>document.getElementById("duration");
inputElement.value = duration.toString();
};
export const getAddForm = (): string => `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<h1 class="form__title">
Add Sitekey
</h1>
<label class="sitekey-form__label" for="description">
Description
<input
class="sitekey-form__input"
type="text"
name="description"
id="description"
required=""
/>
</label>
<label class="sitekey-form__label" for="duration">
Cooldown Duratoin(in seconds)
<input
class="sitekey-form__input"
type="number"
name="duration"
id="duration"
min="0"
required=""
value="30"
/>
</label>
<fieldset class="sitekey__level-container" id="level-group-1">
<legend class="sitekey__level-title">
Level 1
</legend>
<label class="sitekey-form__level-label" for="visitor1"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor1"
id="visitor1"
/>
</label>
<label class="sitekey-form__level-label" for="difficulty1">
Difficulty
<input
type="number"
name="difficulty1"
class="sitekey-form__level-input"
id="difficulty1"
/>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
/>
</label>
</fieldset>
<button class="sitekey-form__submit" type="submit">Submit</button>
</form>
`;
/** get initial form to test remove button functionality */
export const getRemoveButtonHTMLForm = (): string => {
return `
<form class="sitekey-form" action="/api/v1/mcaptcha/levels/add" method="post">
<h1 class="form__title">
Add Sitekey
</h1>
<label class="sitekey-form__label" for="description">
Description
<input
class="sitekey-form__input"
type="text"
name="description"
id="description"
required=""
>
</label>
<label class="sitekey-form__label" for="duration">
Cooldown Duratoin(in seconds)
<input
class="sitekey-form__input"
type="number"
name="duration"
id="duration"
min="0"
required=""
value="30"
>
</label>
<fieldset class="sitekey__level-container" id="level-group-1">
<legend class="sitekey__level-title">
Level 1
</legend>
<label class="sitekey-form__level-label" for="visitor1"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor1"
id="visitor1"
>
</label>
<label class="sitekey-form__level-label" for="difficulty1">
Difficulty
<input
type="number"
name="difficulty1"
class="sitekey-form__level-input"
id="difficulty1"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level1">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level1"
id="remove-level1"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-2">
<legend class="sitekey__level-title">
Level 2
</legend>
<label class="sitekey-form__level-label" for="visitor2"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor2"
id="visitor2"
>
</label>
<label class="sitekey-form__level-label" for="difficulty2">
Difficulty
<input
type="number"
name="difficulty2"
class="sitekey-form__level-input"
id="difficulty2"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level2">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level2"
id="remove-level2"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-3">
<legend class="sitekey__level-title">
Level 3
</legend>
<label class="sitekey-form__level-label" for="visitor3"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor3"
id="visitor3"
>
</label>
<label class="sitekey-form__level-label" for="difficulty3">
Difficulty
<input
type="number"
name="difficulty3"
class="sitekey-form__level-input"
id="difficulty3"
>
</label>
<label class="sitekey-form__level-label--hidden" for="remove-level3">
Remove Level
<input
class="sitekey-form__level-remove-level-button"
type="button"
name="remove-level3"
id="remove-level3"
value="x"
>
</label>
</fieldset>
<fieldset class="sitekey__level-container" id="level-group-4">
<legend class="sitekey__level-title">
Level 4
</legend>
<label class="sitekey-form__level-label" for="visitor4"
>Visitor
<input
class="sitekey-form__level-input"
type="number"
name="visitor4"
id="visitor4"
>
</label>
<label class="sitekey-form__level-label" for="difficulty4">
Difficulty
<input
type="number"
name="difficulty4"
class="sitekey-form__level-input"
id="difficulty4"
>
</label>
<label class="sitekey-form__level-label--hidden" for="add">
Add level
<input
class="sitekey-form__level-add-level-button"
type="button"
name="add"
id="add"
value="Add"
>
</label>
</fieldset>
<button class="sitekey-form__submit" type="submit">Submit</button>
</form>
`;
};