From d298ef47195ee9beb263075504b136210ecda2b1 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Mon, 28 Jun 2021 20:50:13 +0530 Subject: [PATCH] ts: error component --- templates/components/error/error.test.ts | 58 ++++++++++++++++++ templates/components/error/index.ts | 77 ++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 templates/components/error/error.test.ts create mode 100644 templates/components/error/index.ts diff --git a/templates/components/error/error.test.ts b/templates/components/error/error.test.ts new file mode 100644 index 00000000..b0a49c1f --- /dev/null +++ b/templates/components/error/error.test.ts @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Aravinth Manivannan + * + * 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 . + */ + +import createError from './index'; +import * as e from './index'; + +'use strict'; + +jest.useFakeTimers(); + +const setup = () => { + let x = document.createElement('div'); + x.id = e.ERR_CONTAINER_ID; + return x; +}; + +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)); + + let btn = 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); + + let 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); +}); diff --git a/templates/components/error/index.ts b/templates/components/error/index.ts new file mode 100644 index 00000000..958ef3cf --- /dev/null +++ b/templates/components/error/index.ts @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 Aravinth Manivannan + * + * 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 . + */ + +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, +) => { + 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;