list sitekey: copy sitekey

This commit is contained in:
realaravinth
2021-07-15 18:07:12 +05:30
parent 97db774e70
commit 863d22f62c
25 changed files with 369 additions and 224 deletions

11
Cargo.lock generated
View File

@@ -1588,6 +1588,7 @@ dependencies = [
"log", "log",
"mime", "mime",
"mime_guess", "mime_guess",
"openssl",
"pow_sha256", "pow_sha256",
"pretty_env_logger", "pretty_env_logger",
"rand 0.8.4", "rand 0.8.4",
@@ -1873,6 +1874,15 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
[[package]]
name = "openssl-src"
version = "111.15.0+1.1.1k"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a5f6ae2ac04393b217ea9f700cd04fa9bf3d93fae2872069f3d15d908af70a"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.65" version = "0.9.65"
@@ -1882,6 +1892,7 @@ dependencies = [
"autocfg", "autocfg",
"cc", "cc",
"libc", "libc",
"openssl-src",
"pkg-config", "pkg-config",
"vcpkg", "vcpkg",
] ]

View File

@@ -85,6 +85,8 @@ lettre = { version = "0.10.0-rc.3", features = [
"smtp-transport" "smtp-transport"
]} ]}
openssl = { version = "0.10.29", features = ["vendored"] }
[build-dependencies] [build-dependencies]
serde_yaml = "0.8.17" serde_yaml = "0.8.17"

View File

@@ -29,8 +29,8 @@ pub mod routes {
impl Sitekey { impl Sitekey {
pub const fn new() -> Self { pub const fn new() -> Self {
Sitekey { Sitekey {
list: "/sitekey/list", list: "/sitekeys",
add: "/sitekey/add", add: "/sitekeys/add",
view: "/sitekey/{key}", view: "/sitekey/{key}",
} }
} }

1
static/cache/img/svg/clipboard.svg vendored Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clipboard"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>

After

Width:  |  Height:  |  Size: 371 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-external-link"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>

After

Width:  |  Height:  |  Size: 388 B

View File

@@ -17,7 +17,7 @@
@mixin violet-button-hover { @mixin violet-button-hover {
background-color: $light-violet; background-color: $light-violet;
cursor: grab; cursor: pointer;
transform: translateY(-5px); transform: translateY(-5px);
} }

View File

@@ -45,7 +45,7 @@ $message-bg: #d63f3f;
} }
.err__close:hover { .err__close:hover {
cursor: grab; cursor: pointer;
width: 20px; width: 20px;
height: 20px; height: 20px;
} }

View File

@@ -0,0 +1,33 @@
/*
* 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 '../../vars';
@mixin table {
background-color: $white;
width: 90%;
padding: 0 10px;
}
@mixin table__title-text {
font-size: 1rem;
padding: 0.75rem 0.5rem;
box-sizing: border-box;
text-align: left;
width: 100%;
border-bottom: 0.1px solid $light-grey;
}

View File

@@ -1,6 +1,6 @@
.button:hover { .button:hover {
background-color: #993299; background-color: #993299;
cursor: grab; cursor: pointer;
transform: translateY(-5px); transform: translateY(-5px);
} }

View File

@@ -21,6 +21,7 @@ import * as login from './auth/login/ts/';
import * as register from './auth/register/ts/'; import * as register from './auth/register/ts/';
import * as panel from './panel/ts/index'; import * as panel from './panel/ts/index';
import * as addSiteKey from './panel/sitekey/add/ts'; import * as addSiteKey from './panel/sitekey/add/ts';
import * as listSitekeys from './panel/sitekey/list/ts';
import {MODE} from './logger'; import {MODE} from './logger';
import log from './logger'; import log from './logger';
@@ -48,6 +49,7 @@ const router = new Router();
router.register(VIEWS.panelHome, panel.index); router.register(VIEWS.panelHome, panel.index);
router.register(VIEWS.registerUser, register.index); router.register(VIEWS.registerUser, register.index);
router.register(VIEWS.loginUser, login.index); router.register(VIEWS.loginUser, login.index);
router.register(VIEWS.listSitekey, listSitekeys.index);
router.register(VIEWS.addSiteKey, addSiteKey.index); router.register(VIEWS.addSiteKey, addSiteKey.index);
try { try {

View File

@@ -23,3 +23,4 @@ import './panel/header/taskbar/mobile.scss';
import './panel/navbar/mobile.scss'; import './panel/navbar/mobile.scss';
import './panel/help-banner/mobile.scss'; import './panel/help-banner/mobile.scss';
import './panel/sitekey/add/css/mobile.scss'; import './panel/sitekey/add/css/mobile.scss';
import './panel/sitekey/list/css/mobile.scss';

View File

@@ -12,7 +12,8 @@
</li> </li>
<li class="taskbar__action"> <li class="taskbar__action">
<img class="taskbar__icon" src="<.= <img class="taskbar__icon" src="<.=
crate::FILES.get("./static/cache/img/svg/moon.svg").unwrap() .>" alt="Profile" /> crate::FILES.get("./static/cache/img/svg/moon.svg").unwrap() .>"
alt="Profile" />
</li> </li>
<li class="taskbar__action"> <li class="taskbar__action">
@@ -26,7 +27,8 @@
<li class="taskbar__action"> <li class="taskbar__action">
<a href="<.= crate::V1_API_ROUTES.auth.logout .>"> <a href="<.= crate::V1_API_ROUTES.auth.logout .>">
<img class="taskbar__icon" src="<.= <img class="taskbar__icon" src="<.=
crate::FILES.get("./static/cache/img/svg/log-out.svg").unwrap() .>" alt="Profile" crate::FILES.get("./static/cache/img/svg/log-out.svg").unwrap() .>"
/></a> alt="Profile" /></a
>
</li> </li>
</ul> </ul>

View File

@@ -48,10 +48,9 @@
} }
.taskbar__icon:hover { .taskbar__icon:hover {
cursor: grab; cursor: pointer;
background-color: $light-grey; background-color: $light-grey;
color: $green; color: $green;
background-color: $light-grey;
filter: invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg) filter: invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg)
brightness(91%) contrast(92%); brightness(91%) contrast(92%);
} }

View File

@@ -1,40 +1,63 @@
<. include!("../components/headers/index.html"); .> <. include!("../components/headers/index.html"); .> <.
<. include!("./navbar/index.html"); .> include!("./navbar/index.html"); .>
<div class="tmp-layout"> <div class="tmp-layout">
<. include!("./header/index.html"); .> <. include!("./header/index.html"); .>
<main class="panel-main"> <main class="panel-main">
<. include!("./help-banner/index.html"); .> <. include!("./help-banner/index.html"); .>
<div class="inner-container"> <div class="inner-container">
<. if sitekeys.is_empty() { .> <. if sitekeys.is_empty() { .>
<ul class="sitekey-list__box"> <ul class="sitekey-list__box">
<p> <p>
It looks like you don't have any sitekeys. Click It looks like you don't have any sitekeys. Click
<a href="<.= crate::PAGES.panel.sitekey.add .>">here</a> to add new sitekey. <a href="<.= crate::PAGES.panel.sitekey.add .>">here</a> to add new
sitekey.
</p> </p>
</ul> </ul>
<.} else {.> <.} else {.>
<ul class="sitekey-list__box">
<h1 class="sitekey-list__title">Your Sitekeys</h1> <table class="sitekey__table">
<thead class="sitekey__table-heading">
<tr>
<th colspan="4" class="sitekey__table-title-text">
Your Sitekeys
</th>
</tr>
</thead>
<tbody class="sitekey__body">
<. for sitekey in sitekeys.iter() { .> <. for sitekey in sitekeys.iter() { .>
<a href="/sitekey/<.= sitekey.key .>/" class="sitekey-list__item-container"> <tr class="sitekey__item">
<li class="sitekey-list__item"> <td class="sitekey-list__name">
<a
<span class="sitekey-list__name"> href="/sitekey/<.= sitekey.key .>/"
class="sitekey-list__sitekey-link"
>
<.= sitekey.name .> <.= sitekey.name .>
</span>
<span class="sitekey-list__key">
<.= sitekey.key .>
</span>
</li>
</a> </a>
</td>
<td class="sitekey-list__key">
<div class="sitekey__key-container">
<img class="sitekey__copy-icon" src="<.= crate::FILES
.get("./static/cache/img/svg/clipboard.svg") .unwrap() .>"
alt="copy sitekey" data-sitekey="<.= sitekey.key .>" /> <img
class="sitekey__copy-done-icon" src="<.= crate::FILES
.get("./static/cache/img/svg/check.svg") .unwrap() .>"
alt="sitekey copied" data-sitekey="<.= sitekey.key .>" />
<a
class="sitekey__widget-link"
href="<.= crate::WIDGET_ROUTES.verification_widget .>/?sitekey=<.= sitekey.key .>"
>
<.= &sitekey.key[0..5] .>
</a>
</div>
</td>
</tr>
<. } .> <. } .>
</ul> </tbody>
</table>
<.}.> <.}.>
</div> </div>
<. include!("../components/footers.html"); .> <. include!("../components/footers.html"); .>
</main>
</div>

View File

@@ -57,7 +57,7 @@
} }
.secondary-menu__heading:hover { .secondary-menu__heading:hover {
color: $green; color: $green;
cursor: grab; cursor: pointer;
} }
.secondary-menu__logo { .secondary-menu__logo {
@@ -99,7 +99,7 @@
.secondary-menu__item-link:hover { .secondary-menu__item-link:hover {
color: $green; color: $green;
cursor: grab; cursor: pointer;
filter: invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg) filter: invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg)
brightness(91%) contrast(92%); brightness(91%) contrast(92%);
} }

View File

@@ -34,7 +34,7 @@
} }
.nav__hamburger-menu:hover { .nav__hamburger-menu:hover {
cursor: grab; cursor: pointer;
} }
.nav__hamburger-menu:hover > span { .nav__hamburger-menu:hover > span {
@@ -75,5 +75,5 @@
.secondary-menu__brand-name:hover { .secondary-menu__brand-name:hover {
color: $light-text; color: $light-text;
cursor: grab; cursor: pointer;
} }

View File

@@ -16,20 +16,15 @@
*/ */
@import '../../vars'; @import '../../vars';
@import '../../components//table/main';
.notification__table { .notification__table {
background-color: $white; @include table;
width: 90%; margin: auto;
padding: 0 10px;
} }
.notification__title-text { .notification__title-text {
font-size: 1rem; @include table__title-text;
padding: 0.75rem 0.5rem;
box-sizing: border-box;
text-align: left;
width: 100%;
border-bottom: 0.1px solid $light-grey;
} }
.notification__mark-read-btn { .notification__mark-read-btn {

View File

@@ -56,7 +56,7 @@ const submit = async (e: Event) => {
const res = await fetch(formUrl, genJsonPayload(payload)); const res = await fetch(formUrl, genJsonPayload(payload));
if (res.ok) { if (res.ok) {
const data = await res.json(); const data = await res.json();
window.location.assign(VIEWS.listSitekey(data.key)); window.location.assign(VIEWS.viewSitekey(data.key));
} else { } else {
const err = await res.json(); const err = await res.json();
createError(err.error); createError(err.error);

View File

@@ -18,38 +18,87 @@
@import '../../../../reset'; @import '../../../../reset';
@import '../../../../vars'; @import '../../../../vars';
@import '../../../../components/box'; @import '../../../../components/box';
@import '../../../../components/table/main';
.sitekey-list__box { .sitekey__table {
@include box; @include table;
padding-bottom: 0px; margin: auto;
} }
.sitekey-list__title { .sitekey__table-title-text {
@include box-title; @include table__title-text;
}
.sitekey-list__item-container {
display: block;
width: 100%;
box-sizing: border-box;
border-bottom: 0.1px solid $light-grey;
padding: 20px;
color: $black-text;
}
.sitekey-list__item {
display: flex;
width: 100%;
}
.sitekey-list__item-container:hover {
background-color: $light-grey;
} }
.sitekey-list__name { .sitekey-list__name {
flex: 3; min-width: 450px;
} }
.sitekey-list__key { .sitekey-list__key {
flex: 1; width: 10px;
}
@mixin copy-icon-base {
margin: auto;
padding: 5px;
}
.sitekey__copy-icon {
@include copy-icon-base;
}
.sitekey__copy-icon:hover {
cursor: pointer;
filter: invert(17%) sepia(93%) saturate(5039%) hue-rotate(204deg)
brightness(100%) contrast(98%);
}
.sitekey__copy-done-icon {
@include copy-icon-base;
display: none;
filter: invert(58%) sepia(60%) saturate(331%) hue-rotate(76deg)
brightness(91%) contrast(92%);
}
.sitekey__key-container {
border-radius: 10px;
background: $backdrop;
margin: 2px;
padding: 5px;
display: flex;
max-width: 150px;
border: 0.1px solid rgba(0, 0, 0, 0.125);
}
.sitekey__widget-link {
border-left: 0.1px solid $light-grey;
margin: 5;
margin: auto;
padding-left: 20px;
height: 100%;
padding-right: 15px;
}
.sitekey-list__sitekey-link {
display: inline-block;
width: 100%;
text-decoration: none;
color: $blue-link;
padding: 20px;
}
.sitekey-list__sitekey-link:visited {
color: $blue-link;
}
.sitekey-list__sitekey-link:hover {
background-color: $light-grey;
cursor: pointer;
}
.sitekey__widget-link {
color: $blue-link;
}
.sitekey__widget-link:visited {
color: $blue-link;
} }

View File

@@ -0,0 +1,20 @@
/*
* 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-list__name {
min-width: 120px;
}

View File

@@ -1,23 +1,53 @@
<. include!("../../../components/headers/index.html"); .> <. include!("../../../components/headers/index.html"); .> <.
<. include!("../../navbar/index.html"); .> include!("../../navbar/index.html"); .>
<div class="tmp-layout"> <div class="tmp-layout">
<. include!("../../header/index.html"); .> <. include!("../../header/index.html"); .>
<main class="panel-main"> <main class="panel-main">
<.include!("../../help-banner/index.html"); .> <.include!("../../help-banner/index.html"); .>
<!-- Main content container --> <!-- Main content container -->
<div class="inner-container"> <div class="inner-container">
<!-- Main menu/ important actions roaster --> <!-- Main menu/ important actions roaster -->
<ul class="sitekey-list__box"> <table class="sitekey__table">
<h1 class="sitekey-list__title">Your Sitekeys</h1> <thead class="sitekey__table-heading">
<tr>
<th colspan="4" class="sitekey__table-title-text">
Your Sitekeys
</th>
</tr>
</thead>
<tbody class="sitekey__body">
<. for sitekey in sitekeys.iter() { .> <. for sitekey in sitekeys.iter() { .>
<a href="/sitekey/<.= sitekey.key .>/" class="sitekey-list__item-container"> <tr class="sitekey__item">
<li class="sitekey-list__item"> <td class="sitekey-list__name">
<span class="sitekey-list__name"><.= sitekey.name .></span> <a
<span class="sitekey-list__key"><.= sitekey.key .></span> href="/sitekey/<.= sitekey.key .>/"
</li> class="sitekey-list__sitekey-link"
>
<.= sitekey.name .>
</a> </a>
</td>
<td class="sitekey-list__key">
<div class="sitekey__key-container">
<img class="sitekey__copy-icon" src="<.= crate::FILES
.get("./static/cache/img/svg/clipboard.svg") .unwrap() .>"
alt="copy sitekey" data-sitekey="<.= sitekey.key .>" /> <img
class="sitekey__copy-done-icon" src="<.= crate::FILES
.get("./static/cache/img/svg/check.svg") .unwrap() .>"
alt="sitekey copied" data-sitekey="<.= sitekey.key .>" />
<a
class="sitekey__widget-link"
href="<.= crate::WIDGET_ROUTES.verification_widget .>/?sitekey=<.= sitekey.key .>"
>
<.= &sitekey.key[0..5] .>
</a>
</div>
</td>
</tr>
<. } .> <. } .>
</ul> </tbody>
</table>
</div> </div>
<!-- end of container --> <!-- end of container -->
<. include!("../../../components/footers.html"); .> <. include!("../../../components/footers.html"); .>
</main>
</div>

View File

@@ -15,4 +15,39 @@
* 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 const index = () => {}; export const index = () => {
registerCopySitekey();
};
const SITEKEY_COPY_ICON = `sitekey__copy-icon`;
const SITEKEY_COPY_DONE_ICON = `sitekey__copy-done-icon`;
const registerCopySitekey = () => {
const icons = document.querySelectorAll(`.${SITEKEY_COPY_ICON}`);
icons.forEach(icon => {
icon.addEventListener('click', e => copySitekey(e));
});
};
/*
* Copy sitekey to clipboard
*/
const copySitekey = async (e: Event) => {
const image = <HTMLElement>e.target;
if (!image.classList.contains(SITEKEY_COPY_ICON)) {
throw new Error(
'This method should only be called when sitekey copy button/icon is clicked',
);
}
const copyDoneIcon = <HTMLElement>(
image.parentElement.querySelector(`.${SITEKEY_COPY_DONE_ICON}`)
);
const sitekey = image.dataset.sitekey;
await navigator.clipboard.writeText(sitekey);
image.style.display = 'none';
copyDoneIcon.style.display = 'block';
setTimeout(() => {
copyDoneIcon.style.display = 'none';
image.style.display = 'block';
}, 1200);
};

View File

@@ -10,8 +10,15 @@
<!-- Main menu/ important actions roaster --> <!-- Main menu/ important actions roaster -->
<form class="sitekey-form" action="<.= crate::V1_API_ROUTES.levels.add .>" method="post"> <form class="sitekey-form" action="<.= crate::V1_API_ROUTES.levels.add .>" method="post">
<h1 class="form__title">Sitekey: <.= name .> <h1 class="form__title">Sitekey: <.= name .>
<a href="<.= crate::WIDGET_ROUTES.verification_widget .>/?sitekey=<.= key.>" <a
>Click here to see CAPTCHA widget in action</a> target="_blank"
href="<.= crate::WIDGET_ROUTES.verification_widget .>/?sitekey=<.= key.>"
>View widget
<img class="sitekey-form__widget-link"
src="<.= crate::FILES.get("./static/cache/img/svg/external-link.svg").unwrap() .>"
alt="View widget deployment"
/>
</a>
</h1> </h1>
<label class="sitekey-form__label" for="description"> <label class="sitekey-form__label" for="description">
Description Description
@@ -41,14 +48,11 @@
/> />
</label> </label>
<. for (count, level) in levels.iter().enumerate() { .> <. for (count, level) in levels.iter().enumerate() { .>
<. include!("./existing-level.html"); .> <. include!("./existing-level.html"); .>
<. } .> <. } .>
</form> </form>
</div> </div>
<!-- end of container --> <!-- end of container -->
<. include!("../../../components/footers.html"); .> <. include!("../../../components/footers.html"); .>

View File

@@ -15,72 +15,8 @@
* 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 * as listSitekeys from '../sitekey/list/ts/';
export const index = () => { export const index = () => {
// const html = document.documentElement; listSitekeys.index();
// const body = document.body;
// const menuLinks = document.querySelectorAll('.admin-menu a');
// const collapseBtn = document.querySelector('.admin-menu .collapse-btn');
// const toggleMobileMenu = document.querySelector('.toggle-mob-menu');
// const switchInput = document.querySelector('.switch input');
// const switchLabel = document.querySelector('.switch label');
// const switchLabelText = switchLabel.querySelector('span:last-child');
// const collapsedClass = 'collapsed';
// const lightModeClass = 'light-mode';
//
// /*TOGGLE HEADER STATE*/
// collapseBtn.addEventListener('click', function() {
// body.classList.toggle(collapsedClass);
// this.getAttribute('aria-expanded') == 'true'
// ? this.setAttribute('aria-expanded', 'false')
// : this.setAttribute('aria-expanded', 'true');
// this.getAttribute('aria-label') == 'collapse menu'
// ? this.setAttribute('aria-label', 'expand menu')
// : this.setAttribute('aria-label', 'collapse menu');
// });
//
// /*TOGGLE MOBILE MENU*/
// toggleMobileMenu.addEventListener('click', function() {
// body.classList.toggle('mob-menu-opened');
// this.getAttribute('aria-expanded') == 'true'
// ? this.setAttribute('aria-expanded', 'false')
// : this.setAttribute('aria-expanded', 'true');
// this.getAttribute('aria-label') == 'open menu'
// ? this.setAttribute('aria-label', 'close menu')
// : this.setAttribute('aria-label', 'open menu');
// });
//
// /*SHOW TOOLTIP ON MENU LINK HOVER*/
// for (const link of menuLinks) {
// link.addEventListener('mouseenter', function() {
// if (
// body.classList.contains(collapsedClass) &&
// window.matchMedia('(min-width: 768px)').matches
// ) {
// const tooltip = this.querySelector('span').textContent;
// this.setAttribute('title', tooltip);
// } else {
// this.removeAttribute('title');
// }
// });
// }
//
// /*TOGGLE LIGHT/DARK MODE*/
// if (localStorage.getItem('dark-mode') === 'false') {
// html.classList.add(lightModeClass);
// switchInput.checked = false;
// switchLabelText.textContent = 'Light';
// }
//
// switchInput.addEventListener('input', function() {
// html.classList.toggle(lightModeClass);
// if (html.classList.contains(lightModeClass)) {
// switchLabelText.textContent = 'Light';
// localStorage.setItem('dark-mode', 'false');
// } else {
// switchLabelText.textContent = 'Dark';
// localStorage.setItem('dark-mode', 'true');
// }
// });
//
// let a;
}; };

View File

@@ -21,8 +21,9 @@ const ROUTES = {
signoutUser: '/api/v1/signout', signoutUser: '/api/v1/signout',
panelHome: '/', panelHome: '/',
docsHome: '/docs/', docsHome: '/docs/',
listSitekey: (key: string) => `/sitekey/${key}/`, listSitekey: '/sitekeys/',
addSiteKey: '/sitekey/add', viewSitekey: (key: string) => `/sitekey/${key}/`,
addSiteKey: '/sitekeys/add',
}; };
export default ROUTES; export default ROUTES;