submit benchmark
This commit is contained in:
parent
35937134f2
commit
f0f265f59e
17 changed files with 437 additions and 61 deletions
|
@ -94,27 +94,19 @@ where
|
||||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||||
let (r, mut pl) = req.into_parts();
|
let (r, mut pl) = req.into_parts();
|
||||||
let mut is_authenticated = || match self.session_type {
|
let mut is_authenticated = || match self.session_type {
|
||||||
AuthenticatedSession::ActixSession => {
|
AuthenticatedSession::ActixSession => matches!(
|
||||||
if let Ok(Ok(Some(_))) = Session::from_request(&r, &mut pl)
|
Session::from_request(&r, &mut pl)
|
||||||
.into_inner()
|
.into_inner()
|
||||||
.map(|x| x.get::<String>(SURVEY_USER_ID))
|
.map(|x| x.get::<String>(SURVEY_USER_ID)),
|
||||||
{
|
Ok(Ok(Some(_)))
|
||||||
true
|
),
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AuthenticatedSession::ActixIdentity => {
|
AuthenticatedSession::ActixIdentity => matches!(
|
||||||
if let Ok(Some(_)) = Identity::from_request(&r, &mut pl)
|
Identity::from_request(&r, &mut pl)
|
||||||
.into_inner()
|
.into_inner()
|
||||||
.map(|x| x.identity())
|
.map(|x| x.identity()),
|
||||||
{
|
Ok(Some(_))
|
||||||
true
|
),
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if is_authenticated() {
|
if is_authenticated() {
|
||||||
let req = ServiceRequest::from_parts(r, pl);
|
let req = ServiceRequest::from_parts(r, pl);
|
||||||
|
|
|
@ -23,13 +23,22 @@ use sailfish::TemplateOnce;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
|
use crate::pages::errors::ErrorPage;
|
||||||
use crate::PAGES;
|
use crate::PAGES;
|
||||||
|
|
||||||
#[derive(TemplateOnce, Default)]
|
#[derive(TemplateOnce)]
|
||||||
#[template(path = "bench/index.html")]
|
#[template(path = "bench/index.html")]
|
||||||
struct Bench;
|
struct Bench<'a> {
|
||||||
|
error: Option<ErrorPage<'a>>,
|
||||||
|
}
|
||||||
const PAGE: &str = "Survey";
|
const PAGE: &str = "Survey";
|
||||||
|
|
||||||
|
impl<'a> Default for Bench<'a> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Bench { error: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref BENCH: String = Bench::default().render_once().unwrap();
|
static ref BENCH: String = Bench::default().render_once().unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
const ROUTES = {
|
const ROUTES = {
|
||||||
register: "/survey/api/v1/benches/register",
|
register: "/survey/api/v1/benches/register",
|
||||||
|
submitBench: (key: string): string => `/survey/api/v1/benches/${key}/submit`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ROUTES;
|
export default ROUTES;
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
<. include!("../components/base/top.html"); .>
|
<. include!("../components/base/top.html"); .>
|
||||||
<body class="survey__body">
|
<body class="survey__body">
|
||||||
<main class="survey__container">
|
<main class="survey__container">
|
||||||
|
<. include!("../components/error/index.html"); .>
|
||||||
<div id="pre-bench">
|
<div id="pre-bench">
|
||||||
<h1>Click to Start Benchmark</h1>
|
<h1>Click to Start Benchmark</h1>
|
||||||
|
<form class="new-campaign__form" accept-charset="utf-8">
|
||||||
|
<label class="form__label" for="name">
|
||||||
|
Device name
|
||||||
|
<input
|
||||||
|
class="form__input"
|
||||||
|
name="name"
|
||||||
|
required
|
||||||
|
id="name"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
<button id="start" type="submit">Start</button>
|
<!-- <button id="start" type="submit">Start</button> -->
|
||||||
|
<button id="start" class="form__submit" type="submit">
|
||||||
|
Start
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<noscript>
|
<noscript>
|
||||||
|
@ -20,6 +36,7 @@
|
||||||
<div id="bench">
|
<div id="bench">
|
||||||
<h1 id="status" class="name">Running benchmark</h1>
|
<h1 id="status" class="name">Running benchmark</h1>
|
||||||
|
|
||||||
|
<div id="submission-proof"></div>
|
||||||
<div id="device-info"></div>
|
<div id="device-info"></div>
|
||||||
|
|
||||||
<div id="counter"></div>
|
<div id="counter"></div>
|
||||||
|
@ -47,10 +64,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#start {
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pre-bench,
|
#pre-bench,
|
||||||
#bench {
|
#bench {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { Perf } from "./types";
|
import { Bench, Submission, SubmissionProof } from "./types";
|
||||||
import ROUTES from "../api/v1/routes";
|
import ROUTES from "../api/v1/routes";
|
||||||
|
import genJsonPaylod from "../utils/genJsonPayload";
|
||||||
|
import isBlankString from "../utils/isBlankString";
|
||||||
|
|
||||||
export const index = () => {
|
export const index = () => {
|
||||||
const FACTOR = 500000;
|
const FACTOR = 500000;
|
||||||
|
@ -25,16 +27,18 @@ export const index = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const worker = new Worker("/bench.js");
|
const worker = new Worker("/bench.js");
|
||||||
const res: Array<Perf> = [];
|
const res: Array<Bench> = [];
|
||||||
const stats = document.getElementById("stats");
|
const stats = document.getElementById("stats");
|
||||||
|
const CAMPAIGN_ID = window.location.pathname.split("/")[3];
|
||||||
|
let deviceName = "";
|
||||||
|
|
||||||
const addResult = (perf: Perf) => {
|
const addResult = (perf: Bench) => {
|
||||||
const row = document.createElement("tr");
|
const row = document.createElement("tr");
|
||||||
row.className = "data";
|
row.className = "data";
|
||||||
const diff = document.createElement("td");
|
const diff = document.createElement("td");
|
||||||
diff.innerHTML = perf.difficulty.toString();
|
diff.innerHTML = perf.difficulty.toString();
|
||||||
const duration = document.createElement("td");
|
const duration = document.createElement("td");
|
||||||
duration.innerHTML = perf.time.toString();
|
duration.innerHTML = perf.duration.toString();
|
||||||
|
|
||||||
row.appendChild(diff);
|
row.appendChild(diff);
|
||||||
row.appendChild(duration);
|
row.appendChild(duration);
|
||||||
|
@ -44,6 +48,39 @@ export const index = () => {
|
||||||
res.push(perf);
|
res.push(perf);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const submitBench = async () => {
|
||||||
|
const payload: Submission = {
|
||||||
|
device_user_provided: deviceName,
|
||||||
|
threads: window.navigator.hardwareConcurrency,
|
||||||
|
device_software_recognised: window.navigator.userAgent,
|
||||||
|
|
||||||
|
benches: res,
|
||||||
|
};
|
||||||
|
|
||||||
|
const resp = await fetch(
|
||||||
|
ROUTES.submitBench(CAMPAIGN_ID),
|
||||||
|
genJsonPaylod(payload)
|
||||||
|
);
|
||||||
|
if (resp.status == 200) {
|
||||||
|
const data: SubmissionProof = await resp.json();
|
||||||
|
const element = document.createElement("div");
|
||||||
|
const token = document.createElement("b");
|
||||||
|
token.innerText = "User Agent: ";
|
||||||
|
const tokenText = document.createTextNode(`${data.token}`);
|
||||||
|
|
||||||
|
const proof = document.createElement("b");
|
||||||
|
proof.innerText = "Proof: ";
|
||||||
|
const proofText = document.createTextNode(`${data.proof}`);
|
||||||
|
|
||||||
|
element.appendChild(token);
|
||||||
|
element.appendChild(tokenText);
|
||||||
|
element.appendChild(document.createElement("br"));
|
||||||
|
element.appendChild(proof);
|
||||||
|
element.appendChild(proofText);
|
||||||
|
document.getElementById("submission-proof").appendChild(element);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const addDeviceInfo = () => {
|
const addDeviceInfo = () => {
|
||||||
const INFO = {
|
const INFO = {
|
||||||
threads: window.navigator.hardwareConcurrency,
|
threads: window.navigator.hardwareConcurrency,
|
||||||
|
@ -71,14 +108,23 @@ export const index = () => {
|
||||||
document.getElementById("device-info").appendChild(element);
|
document.getElementById("device-info").appendChild(element);
|
||||||
};
|
};
|
||||||
|
|
||||||
const finished = () => {
|
const finished = async () => {
|
||||||
|
await submitBench();
|
||||||
const s = document.getElementById("status");
|
const s = document.getElementById("status");
|
||||||
s.innerHTML = "Benchmark finished";
|
s.innerHTML = "Benchmark finished";
|
||||||
};
|
};
|
||||||
|
|
||||||
const run = async (e: Event) => {
|
const run = async (e: Event) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
const deveceNameElement = <HTMLInputElement>document.getElementById("name");
|
||||||
|
if (isBlankString(deveceNameElement.value, "Device Name", e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceName = deveceNameElement.value;
|
||||||
|
|
||||||
await initSession();
|
await initSession();
|
||||||
|
|
||||||
document.getElementById("pre-bench").style.display = "none";
|
document.getElementById("pre-bench").style.display = "none";
|
||||||
document.getElementById("bench").style.display = "flex";
|
document.getElementById("bench").style.display = "flex";
|
||||||
|
|
||||||
|
@ -87,11 +133,11 @@ export const index = () => {
|
||||||
const counterElement = document.getElementById("counter");
|
const counterElement = document.getElementById("counter");
|
||||||
counterElement.innerText = `${iterations} more to go`;
|
counterElement.innerText = `${iterations} more to go`;
|
||||||
|
|
||||||
worker.onmessage = (event: MessageEvent) => {
|
worker.onmessage = async (event: MessageEvent) => {
|
||||||
const data: Perf = event.data;
|
const data: Bench = event.data;
|
||||||
addResult(data);
|
addResult(data);
|
||||||
if (res.length == iterations) {
|
if (res.length == iterations) {
|
||||||
finished();
|
await finished();
|
||||||
counterElement.innerText = "All Done!";
|
counterElement.innerText = "All Done!";
|
||||||
} else {
|
} else {
|
||||||
counterElement.innerText = `${iterations - res.length} more to go`;
|
counterElement.innerText = `${iterations - res.length} more to go`;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { gen_pow } from "mcaptcha-browser";
|
import { gen_pow } from "mcaptcha-browser";
|
||||||
import { Perf } from "./types";
|
import { Bench } from "./types";
|
||||||
|
|
||||||
type PoWConfig = {
|
type PoWConfig = {
|
||||||
string: string;
|
string: string;
|
||||||
|
@ -43,11 +43,11 @@ onmessage = function (event) {
|
||||||
const t0 = performance.now();
|
const t0 = performance.now();
|
||||||
gen_pow(config.salt, config.string, config.difficulty_factor);
|
gen_pow(config.salt, config.string, config.difficulty_factor);
|
||||||
const t1 = performance.now();
|
const t1 = performance.now();
|
||||||
const time = t1 - t0;
|
const duration = t1 - t0;
|
||||||
|
|
||||||
const msg: Perf = {
|
const msg: Bench = {
|
||||||
difficulty: difficulty_factor,
|
difficulty: difficulty_factor,
|
||||||
time: time,
|
duration,
|
||||||
};
|
};
|
||||||
postMessage(msg);
|
postMessage(msg);
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,8 +15,19 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export type Bench = {
|
||||||
export type Perf = {
|
difficulty: number;
|
||||||
difficulty: Number;
|
duration: number;
|
||||||
time: Number;
|
};
|
||||||
|
|
||||||
|
export type Submission = {
|
||||||
|
device_user_provided: String;
|
||||||
|
device_software_recognised: String;
|
||||||
|
threads: number;
|
||||||
|
benches: Array<Bench>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SubmissionProof = {
|
||||||
|
token: String;
|
||||||
|
proof: String;
|
||||||
};
|
};
|
||||||
|
|
54
templates/components/error/error.test.ts
Normal file
54
templates/components/error/error.test.ts
Normal 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 createError from "./index";
|
||||||
|
import * as e from "./index";
|
||||||
|
|
||||||
|
import setup from "./setUpTests";
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
it("checks if error boxes work", () => {
|
||||||
|
document.body.append(setup());
|
||||||
|
|
||||||
|
const getMsg = (num: number) => `message ${num}`;
|
||||||
|
createError(getMsg(1));
|
||||||
|
let msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
||||||
|
expect(msg.innerHTML).toContain(getMsg(1));
|
||||||
|
|
||||||
|
const btn = <HTMLButtonElement>msg.getElementsByClassName(e.ERR_CLOSE)[0];
|
||||||
|
btn.click();
|
||||||
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
||||||
|
expect(msg).toEqual(null);
|
||||||
|
|
||||||
|
const errElement = document.createElement("p");
|
||||||
|
errElement.appendChild(document.createTextNode(getMsg(2)));
|
||||||
|
createError(errElement);
|
||||||
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`).querySelector("p");
|
||||||
|
expect(msg).toEqual(errElement);
|
||||||
|
|
||||||
|
const timeOutElement = document.createElement("p");
|
||||||
|
timeOutElement.appendChild(document.createTextNode(getMsg(2)));
|
||||||
|
createError(timeOutElement, 200);
|
||||||
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`).querySelector("p");
|
||||||
|
expect(msg).toEqual(timeOutElement);
|
||||||
|
jest.runOnlyPendingTimers();
|
||||||
|
msg = document.querySelector(`.${e.ERR_MSG_CONTAINER}`);
|
||||||
|
expect(msg).toEqual(null);
|
||||||
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
<. if let Some(error) = error { .>
|
<div class="error__container">
|
||||||
<div class="error__container">
|
<. if let Some(error) = error { .>
|
||||||
<p class="error__title"><b><.= error.title .></b></p>
|
<p class="error__title"><b><.= error.title .></b></p>
|
||||||
<p class="error__msg"><.= error.message .></p>
|
<p class="error__msg"><.= error.message .></p>
|
||||||
</div>
|
<. } .>
|
||||||
<. } .>
|
</div>
|
||||||
|
|
77
templates/components/error/index.ts
Normal file
77
templates/components/error/index.ts
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const ERR_CONTAINER_ID = "err__container";
|
||||||
|
export const ERR_MSG_CONTAINER = "err__msg-container"; // class
|
||||||
|
export const ERR_CLOSE = "err__close"; // class
|
||||||
|
|
||||||
|
export const DEFAULT_LIFETIME = 5000;
|
||||||
|
|
||||||
|
const err = () => {
|
||||||
|
let element;
|
||||||
|
return (() => {
|
||||||
|
if (element === undefined) {
|
||||||
|
element = document.getElementById(ERR_CONTAINER_ID);
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
})();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create error message
|
||||||
|
*
|
||||||
|
* @param {string|HTMLElement} message: an error message
|
||||||
|
* @param {number} lifetime: duration in milliseconds after which error
|
||||||
|
* message will be deleted
|
||||||
|
*/
|
||||||
|
const createError = (
|
||||||
|
message: string | HTMLElement,
|
||||||
|
lifetime: number = DEFAULT_LIFETIME,
|
||||||
|
): void => {
|
||||||
|
const box = document.createElement("div");
|
||||||
|
|
||||||
|
const msg = () => {
|
||||||
|
if (typeof message === "string") {
|
||||||
|
return document.createTextNode(message);
|
||||||
|
} else {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
box.className = ERR_MSG_CONTAINER;
|
||||||
|
box.appendChild(msg());
|
||||||
|
|
||||||
|
const deleteBtn = document.createElement("button");
|
||||||
|
const deleteMsg = document.createTextNode("x");
|
||||||
|
deleteBtn.appendChild(deleteMsg);
|
||||||
|
deleteBtn.className = ERR_CLOSE;
|
||||||
|
box.appendChild(deleteBtn);
|
||||||
|
|
||||||
|
err().appendChild(box);
|
||||||
|
|
||||||
|
const timer = setTimeout(() => box.remove(), lifetime);
|
||||||
|
|
||||||
|
const deleteHandler = (e: Event) => {
|
||||||
|
e.preventDefault();
|
||||||
|
window.clearTimeout(timer);
|
||||||
|
box.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteBtn.addEventListener("click", e => deleteHandler(e));
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createError;
|
|
@ -14,23 +14,37 @@
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
* 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/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
$message-bg: #d63f3f;
|
||||||
|
$light-text: rgba(255, 255, 255, 0.87);
|
||||||
|
|
||||||
.error__container {
|
#err__container {
|
||||||
width: 350px;
|
display: felx;
|
||||||
background-color: #d63f3f;
|
position: fixed;
|
||||||
width: 100%;
|
top: 0;
|
||||||
padding: 10px 0;
|
right: 0;
|
||||||
opacity: 0.9;
|
width: 350px;
|
||||||
font-size: 0.8rem;
|
|
||||||
font-family: monospace, monospace;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.error__title {
|
.err__msg-container {
|
||||||
color: #fff;
|
display: flex;
|
||||||
margin-left: 10px;
|
width: 100%;
|
||||||
|
color: $light-text;
|
||||||
|
background-color: $message-bg;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
opacity: 0.9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error__msg {
|
.err__close {
|
||||||
color: #fff;
|
min-width: 10px;
|
||||||
margin-left: 10px;
|
min-height: 10px;
|
||||||
|
background-color: $message-bg;
|
||||||
|
margin-left: 20px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.err__close:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
25
templates/components/error/setUpTests.ts
Normal file
25
templates/components/error/setUpTests.ts
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* 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 * as e from "./index";
|
||||||
|
|
||||||
|
const setup = (): HTMLElement => {
|
||||||
|
const x = document.createElement("div");
|
||||||
|
x.id = e.ERR_CONTAINER_ID;
|
||||||
|
return x;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setup;
|
|
@ -23,6 +23,7 @@
|
||||||
@import "./panel/campaigns/new/main";
|
@import "./panel/campaigns/new/main";
|
||||||
@import "./panel/campaigns/get/main";
|
@import "./panel/campaigns/get/main";
|
||||||
@import "./errors/main";
|
@import "./errors/main";
|
||||||
|
@import "./components/error/main";
|
||||||
|
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
36
templates/utils/genJsonPayload.test.ts
Normal file
36
templates/utils/genJsonPayload.test.ts
Normal 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 genJsonPayload from "./genJsonPayload";
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
username: "Jhon",
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
};
|
||||||
|
|
||||||
|
it("getFromUrl workds", () => {
|
||||||
|
expect(genJsonPayload(payload)).toEqual(value);
|
||||||
|
});
|
29
templates/utils/genJsonPayload.ts
Normal file
29
templates/utils/genJsonPayload.ts
Normal 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const genJsonPayload = (payload: object): object => {
|
||||||
|
const value = {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
};
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default genJsonPayload;
|
36
templates/utils/isBlankString.test.ts
Normal file
36
templates/utils/isBlankString.test.ts
Normal 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 isBlankString from "./isBlankString";
|
||||||
|
import {mockAlert} from "../setUpTests";
|
||||||
|
|
||||||
|
|
||||||
|
import setup from "../components/error/setUpTests";
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
mockAlert();
|
||||||
|
|
||||||
|
it("getFromUrl workds", () => {
|
||||||
|
document.querySelector("body").appendChild(setup());
|
||||||
|
expect(isBlankString("test", "username")).toBe(false);
|
||||||
|
try {
|
||||||
|
isBlankString(" ", "username");
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toContain("can't be empty");
|
||||||
|
}
|
||||||
|
});
|
32
templates/utils/isBlankString.ts
Normal file
32
templates/utils/isBlankString.ts
Normal 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 createError from "../components/error/";
|
||||||
|
|
||||||
|
const isBlankString = (value: string|number, field: string, event?: Event): boolean => {
|
||||||
|
value = value.toString();
|
||||||
|
if (!value.replace(/\s/g, "").length) {
|
||||||
|
if (event !== undefined) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
const msg = `${field} can't be empty`;
|
||||||
|
createError(msg);
|
||||||
|
throw new Error(msg);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isBlankString;
|
Loading…
Reference in a new issue