improved frontend, started csv upload endpoint
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,4 +1,6 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
db/db.json
|
||||
.env
|
||||
node_modules
|
||||
package-lock.json
|
||||
package-lock.json
|
||||
sample.octet-stream
|
||||
@@ -13,6 +13,7 @@
|
||||
"dependencies": {
|
||||
"chalk": "^5.6.2",
|
||||
"cors": "^2.8.5",
|
||||
"csv-parser": "^3.2.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"express": "^4.18.2",
|
||||
"http-proxy": "^1.18.1",
|
||||
|
||||
72
server/db.js
72
server/db.js
@@ -2,6 +2,7 @@ import chalk from 'chalk'
|
||||
import path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { pathToFileURL } from 'url';
|
||||
import parse from "csv-parser"
|
||||
import Node from "../model/Node.js"
|
||||
|
||||
export default class Database {
|
||||
@@ -74,4 +75,75 @@ export default class Database {
|
||||
async getAll() {
|
||||
return { nodes: this.#nodes }
|
||||
}
|
||||
|
||||
async loadCSV(csvString) {
|
||||
if (!csvString || typeof csvString !== 'string') {
|
||||
throw new Error('loadCSVAsync: input must be a non-empty string');
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const records = [];
|
||||
|
||||
const parser = parse({
|
||||
columns: true,
|
||||
skip_empty_lines: true,
|
||||
trim: true,
|
||||
relax_column_count: true,
|
||||
bom: true
|
||||
});
|
||||
|
||||
parser.on('readable', () => {
|
||||
let row;
|
||||
while ((row = parser.read()) !== null) {
|
||||
records.push(this.cleanRow(row));
|
||||
}
|
||||
});
|
||||
|
||||
parser.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
|
||||
parser.on('end', () => {
|
||||
resolve(records);
|
||||
});
|
||||
|
||||
// Feed the CSV string
|
||||
parser.write(csvString);
|
||||
parser.end();
|
||||
});
|
||||
}
|
||||
|
||||
cleanRow(row) {
|
||||
const cleaned = {};
|
||||
|
||||
for (let [key, value] of Object.entries(row)) {
|
||||
// 1. Clean header
|
||||
key = key
|
||||
.replace(/ -MyData/g, '')
|
||||
.replace(/[^a-zA-Z0-9]/g, ' ')
|
||||
.trim()
|
||||
.replace(/\s+(.)/g, (_, c) => c.toUpperCase())
|
||||
.replace(/^(.)/, c => c.toLowerCase());
|
||||
|
||||
// 2. Empty → null
|
||||
if (value === '' || value == null) {
|
||||
cleaned[key] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 3. Type conversion
|
||||
if (key === 'registrationStatus') {
|
||||
cleaned[key] = value === 'True' ? true : value === 'False' ? false : null;
|
||||
}
|
||||
else if (['confidences', 'personId', 'uid', 'stateVoterId'].includes(key)) {
|
||||
const num = parseFloat(value);
|
||||
cleaned[key] = isNaN(num) ? null : num;
|
||||
}
|
||||
else {
|
||||
cleaned[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
return cleaned;
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,13 @@ const handlers = {
|
||||
console.log(`Received location: (${name}, ${latitude}, ${longitude}) at ${timestamp}`);
|
||||
broadcast("update-location", { name, latitude, longitude, timestamp });
|
||||
res.json({ success: true });
|
||||
},
|
||||
|
||||
async uploadCSV(req, res) {
|
||||
const csvString = req.body;
|
||||
console.log(csvString);
|
||||
await global.db.uploadCSV(csvString)
|
||||
res.json({ ok: true });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ class Server {
|
||||
|
||||
registerRoutes(router) {
|
||||
router.post('/api/location', handlers.updateLocation)
|
||||
router.post('/csv', handlers.uploadCSV)
|
||||
router.post('/login', this.login)
|
||||
router.get('/*', this.get)
|
||||
return router
|
||||
@@ -115,7 +116,7 @@ class Server {
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.db = new Database()
|
||||
global.db = new Database()
|
||||
this.auth = new AuthHandler()
|
||||
const app = express();
|
||||
app.use(cors({ origin: '*' }));
|
||||
|
||||
File diff suppressed because one or more lines are too long
6
ui/_/code/styles.css
Normal file
6
ui/_/code/styles.css
Normal file
@@ -0,0 +1,6 @@
|
||||
@font-face {
|
||||
font-family: 'Inknut Antiqua';
|
||||
src: url('/_/fonts/Inknut_Antiqua/InknutAntiqua-Regular.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Black.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Black.ttf
Executable file
Binary file not shown.
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Bold.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Bold.ttf
Executable file
Binary file not shown.
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-ExtraBold.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-ExtraBold.ttf
Executable file
Binary file not shown.
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Light.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Light.ttf
Executable file
Binary file not shown.
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Medium.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Medium.ttf
Executable file
Binary file not shown.
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Regular.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-Regular.ttf
Executable file
Binary file not shown.
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-SemiBold.ttf
Executable file
BIN
ui/_/fonts/Inknut_Antiqua/InknutAntiqua-SemiBold.ttf
Executable file
Binary file not shown.
93
ui/_/fonts/Inknut_Antiqua/OFL.txt
Executable file
93
ui/_/fonts/Inknut_Antiqua/OFL.txt
Executable file
@@ -0,0 +1,93 @@
|
||||
Copyright (c) 2014 Claus Eggers Sørensen (es@forthehearts.net)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
71
ui/_/icons/runner.svg
Normal file
71
ui/_/icons/runner.svg
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
viewBox="0 0 511.697 511.697" xml:space="preserve">
|
||||
<g transform="translate(0 1)">
|
||||
<g>
|
||||
<path style="fill:#FFE100;" d="M505.189,119.472L505.189,119.472c-7.81-7.81-13.885-9.546-21.695-1.736l-45.125,45.993
|
||||
c-6.075,6.075-14.753,6.075-20.827,0.868l-63.349-59.01c-4.339-4.339-10.414-6.942-16.488-6.942h-94.59l-79.837,75.498
|
||||
c-7.81,7.81-9.546,21.695-1.736,30.373c8.678,9.546,22.563,8.678,31.241,0l59.01-62.481h43.39L147.656,306.916H62.612
|
||||
c-13.885,0-26.902,10.414-27.769,24.298c-0.868,15.62,11.281,27.77,26.034,27.77H165.88c10.414,0,19.959-4.339,27.77-12.149
|
||||
l57.275-61.614l61.614,65.085L296.05,456.177c-2.603,12.149,2.603,25.166,13.885,30.373c15.62,6.942,32.108-1.736,36.447-17.356
|
||||
l25.166-135.376c0.868-6.075-0.868-11.281-5.207-15.62l-71.159-72.027l69.424-69.424l45.993,45.993
|
||||
c7.81,7.81,21.695,7.81,29.505,0l19.959-19.959l45.125-52.068C513.867,142.035,513.867,128.15,505.189,119.472"/>
|
||||
<path style="fill:#FFE100;" d="M462.667,118.605l-0.868-0.868c-7.81-7.81-1.736-7.81-10.414,0l-34.712,45.993
|
||||
c-6.075,6.075-14.753,6.075-20.827,0.868l-73.763-59.01c-4.339-4.339-4.339-6.942-10.414-6.942h-68.556l-79.837,75.498
|
||||
c-7.81,7.81-9.546,21.695-1.736,30.373c8.678,9.546,4.339,8.678,12.149,0l60.746-62.481h34.712L121.623,306.916h-59.01
|
||||
c-13.885,0-26.902,10.414-27.769,24.298c-0.868,15.62,11.281,27.77,26.034,27.77h95.458l69.424-72.895l60.746,64.217
|
||||
l-16.488,105.871c-2.603,12.149,2.603,25.166,13.885,30.373c15.62,6.942,16.488-1.736,19.959-17.356l20.827-144.922
|
||||
l-55.539-78.102l63.349-69.424l40.786,45.993c7.81,7.81,18.224-3.471,26.034-11.281l8.678-8.678l54.671-54.671
|
||||
C470.477,140.299,470.477,126.415,462.667,118.605"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFA800;" d="M323.819,324.272l-20.827,144.922c-2.603,11.281-3.471,19.092-10.414,19.959
|
||||
c12.149,0.868,23.431-7.81,26.034-19.959l27.77-144.922l-77.234-77.234L323.819,324.272z"/>
|
||||
<path style="fill:#FFA800;" d="M487.833,118.605l-0.868-0.868c-7.81-7.81-19.092-7.81-27.77-1.736
|
||||
c0.868,0.868,0.868,0.868,1.736,1.736l0.868,0.868c7.81,7.81,7.81,20.827,0,29.505l-54.671,54.671l-8.678,8.678
|
||||
c-4.339,4.339-8.678,9.546-13.885,12.149c7.81,6.942,20.827,6.942,28.637-0.868l19.959-19.959l54.671-54.671
|
||||
C495.643,140.299,495.643,127.282,487.833,118.605"/>
|
||||
</g>
|
||||
<g>
|
||||
<path style="fill:#FFFFFF;" d="M163.277,207.12c-0.868-0.868-1.736-1.736-2.603-2.603c-7.81-8.678-6.942-21.695,1.736-30.373
|
||||
l80.705-75.498H217.08l-79.837,75.498c-7.81,7.81-9.546,21.695-1.736,30.373S155.467,213.194,163.277,207.12"/>
|
||||
<path style="fill:#FFFFFF;" d="M34.843,331.215c0.868-13.885,13.017-24.298,26.902-24.298H35.711
|
||||
c-13.885,0-26.902,10.414-27.769,24.298c0,15.62,12.149,27.77,26.902,27.77h26.034C46.124,358.984,33.975,346.835,34.843,331.215"
|
||||
/>
|
||||
</g>
|
||||
<path style="fill:#FFE100;" d="M425.351,63.933c0-24.298-19.092-43.39-43.39-43.39c-0.868,0-26.034,19.092-26.034,43.39
|
||||
c0,0.868,1.736,43.39,26.034,43.39C406.26,107.323,425.351,88.232,425.351,63.933"/>
|
||||
<g>
|
||||
<path style="fill:#FFA800;" d="M399.318,20.543c-2.603,0-6.075,0-8.678,0.868c19.959,4.339,34.712,21.695,34.712,42.522
|
||||
s-14.753,38.183-34.712,42.522c2.603,0.868,6.075,0.868,8.678,0.868c24.298,0,43.39-19.092,43.39-43.39
|
||||
S423.616,20.543,399.318,20.543"/>
|
||||
<path style="fill:#FFA800;" d="M356.795,71.743c0,0.868,0,0.868,0,1.736C356.795,72.611,356.795,71.743,356.795,71.743"/>
|
||||
</g>
|
||||
<path d="M295.182,497.832c-5.207,0-9.546-0.868-14.753-3.471c-14.753-6.942-23.431-23.431-19.092-40.786l15.62-100.664
|
||||
l-52.068-54.671l-62.481,66.82c-1.736,1.736-3.471,2.603-6.075,2.603H34.843c-9.546,0-18.224-4.339-25.166-10.414
|
||||
c-6.942-6.942-10.414-16.488-9.546-26.034c0.868-18.224,16.488-32.976,36.447-32.976h81.573l32.108-35.58
|
||||
c3.471-3.471,8.678-3.471,12.149-0.868c3.471,3.471,3.471,8.678,0.868,12.149l-34.712,39.051c-2.603,1.736-4.339,2.603-6.942,2.603
|
||||
H36.579c-10.414,0-19.092,6.942-19.092,16.488c0,5.207,1.736,9.546,4.339,13.017c3.471,3.471,7.81,5.207,13.017,5.207h118.02
|
||||
l65.953-70.292c1.736-1.736,4.339-2.603,6.075-2.603c2.603,0,4.339,0.868,6.075,2.603l61.614,64.217
|
||||
c1.736,1.736,2.603,4.339,2.603,6.942l-16.488,105.871c-1.736,9.546,1.736,18.224,9.546,21.695c5.207,2.603,10.414,1.736,14.753,0
|
||||
c4.339-2.603,7.81-6.942,9.546-11.281l26.034-139.715l-74.63-74.631c-2.603-2.603-3.471-4.339-3.471-6.942
|
||||
c0-2.603,0.868-4.339,2.603-6.075l69.424-69.424c3.471-3.471,8.678-3.471,12.149,0l45.993,45.993
|
||||
c4.339,4.339,12.149,4.339,17.356,0l74.63-74.631c4.339-4.339,4.339-12.149,0-16.488l-0.868-0.868
|
||||
c-5.207-5.207-13.017-5.207-17.356,0l-45.125,45.993c-8.678,8.678-23.431,9.546-32.976,0.868l-63.349-59.01
|
||||
c-2.603-2.603-6.942-4.339-10.414-4.339h-91.986l-77.234,73.763c-5.207,5.207-5.207,13.017-0.868,18.224
|
||||
c2.603,2.603,6.075,4.339,9.546,4.339l0,0c3.471,0,6.942-1.736,8.678-4.339l59.01-62.481c1.736-1.736,4.339-2.603,6.075-2.603
|
||||
h43.39c3.471,0,6.942,1.736,7.81,5.207s0.868,6.942-1.736,9.546l-69.424,78.102c-3.471,3.471-8.678,4.339-12.149,0.868
|
||||
c-3.471-3.471-3.471-8.678-0.868-12.149l56.407-63.349h-19.959l-56.407,59.878c-5.207,6.075-13.017,9.546-21.695,9.546l0,0
|
||||
c-8.678,0-16.488-3.471-21.695-9.546c-10.414-11.281-9.546-30.373,1.736-42.522l79.837-76.366c1.736-3.471,3.471-4.339,6.075-4.339
|
||||
h94.59c8.678,0,16.488,3.471,22.563,8.678l63.349,59.01c2.603,2.603,6.075,2.603,8.678,0l45.125-45.993
|
||||
c11.281-11.281,30.373-11.281,42.522,0l0.868,0.868c11.281,11.281,11.281,30.373,0,41.654l-74.63,74.631
|
||||
c-11.281,11.281-30.373,11.281-41.654,0l-39.919-39.919l-57.275,57.275l72.027,72.027c1.736,1.736,2.603,5.207,2.603,7.81
|
||||
L329.026,470.93c-2.603,10.414-9.546,19.092-18.224,23.431C305.595,496.964,300.389,497.832,295.182,497.832z"/>
|
||||
<path d="M187.575,241.832c0-5.207-3.471-8.678-8.678-8.678s-8.678,3.471-8.678,8.678s3.471,8.678,8.678,8.678
|
||||
S187.575,247.038,187.575,241.832"/>
|
||||
<path d="M399.318,116.001c-28.637,0-52.068-23.431-52.068-52.068s23.431-52.068,52.068-52.068
|
||||
c28.637,0,52.068,23.431,52.068,52.068S427.955,116.001,399.318,116.001z M399.318,29.221c-19.092,0-34.712,15.62-34.712,34.712
|
||||
s15.62,34.712,34.712,34.712c19.092,0,34.712-15.62,34.712-34.712S418.409,29.221,399.318,29.221z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -1,20 +1,20 @@
|
||||
import "./LocationList.js"
|
||||
import "./Sidebar.js"
|
||||
import "./MainPanel.js"
|
||||
|
||||
class Home extends Shadow {
|
||||
render() {
|
||||
ZStack(() => {
|
||||
p("BLOCKCATCHER")
|
||||
.x(2, em).y(1, em)
|
||||
.fontSize(1.2, em)
|
||||
.fontFamily("Arial")
|
||||
|
||||
LocationList()
|
||||
HStack(() => {
|
||||
Sidebar()
|
||||
MainPanel()
|
||||
})
|
||||
})
|
||||
.backgroundColor("#aebdff")
|
||||
.backgroundColor("rgb(146, 160, 219)")
|
||||
.display("block")
|
||||
.width(100, vw).height(100, vh)
|
||||
.color("#60759f")
|
||||
.color("#203051ff")
|
||||
}
|
||||
}
|
||||
|
||||
registerShadow(Home)
|
||||
register(Home)
|
||||
@@ -14,13 +14,15 @@ class LocationList extends Shadow {
|
||||
.gap(1, em)
|
||||
})
|
||||
})
|
||||
.gap(0.5, em)
|
||||
.paddingLeft(5, em)
|
||||
.paddingTop(2, em)
|
||||
.onEvent("update-location", (e) => {
|
||||
console.log("location received: ", e.detail)
|
||||
this.list.unshift(e.detail)
|
||||
this.rerender()
|
||||
})
|
||||
.x(2, em).y(5, em)
|
||||
}
|
||||
}
|
||||
|
||||
window.registerShadow(LocationList)
|
||||
window.register(LocationList)
|
||||
25
ui/app/components/MainPanel.js
Normal file
25
ui/app/components/MainPanel.js
Normal file
@@ -0,0 +1,25 @@
|
||||
class MainPanel extends Shadow {
|
||||
render() {
|
||||
ZStack(() => {
|
||||
input("Search", "70vw")
|
||||
.marginLeft(5, em)
|
||||
.marginTop(2, em)
|
||||
.paddingVertical(0.5, em)
|
||||
.paddingHorizontal(1, em)
|
||||
.border("none")
|
||||
.background("rgb(146, 160, 219)")
|
||||
.outline("none")
|
||||
|
||||
switch(window.location.pathname) {
|
||||
case "/":
|
||||
LocationList()
|
||||
break;
|
||||
}
|
||||
})
|
||||
.width(100, "%")
|
||||
.height(100, vh)
|
||||
.backgroundColor("rgb(174, 189, 255)")
|
||||
}
|
||||
}
|
||||
|
||||
register(MainPanel)
|
||||
61
ui/app/components/Sidebar.js
Normal file
61
ui/app/components/Sidebar.js
Normal file
@@ -0,0 +1,61 @@
|
||||
class Sidebar extends Shadow {
|
||||
render() {
|
||||
VStack(() => {
|
||||
HStack(() => {
|
||||
img("./_/icons/runner.svg", "40px", "40px")
|
||||
p("Blockcatcher")
|
||||
.fontSize(1.2, em)
|
||||
.fontFamily("Inknut Antiqua")
|
||||
.marginTop(0.5, em)
|
||||
})
|
||||
.marginTop(2, em)
|
||||
.paddingLeft(6, em)
|
||||
.width(100, "%")
|
||||
.borderBottom("2px solid rgb(100 115 177)")
|
||||
|
||||
button("Walkers")
|
||||
.background("rgb(100 115 177)")
|
||||
.paddingVertical(0.5, em)
|
||||
.border("none")
|
||||
.borderRadius(6, px)
|
||||
.marginTop(3, em)
|
||||
.width(80, "%")
|
||||
|
||||
button("Voters")
|
||||
.background("transparent")
|
||||
.paddingVertical(0.5, em)
|
||||
.border("none")
|
||||
.borderRadius(6, px)
|
||||
.marginTop(1, em)
|
||||
.width(80, "%")
|
||||
.onHover(function (hovering) {
|
||||
if(hovering) {
|
||||
this.style.outline = "1px solid rgb(100 115 177)"
|
||||
} else {
|
||||
this.style.outline = ""
|
||||
}
|
||||
})
|
||||
|
||||
button("Data")
|
||||
.background("transparent")
|
||||
.paddingVertical(0.5, em)
|
||||
.border("none")
|
||||
.borderRadius(6, px)
|
||||
.marginTop(1, em)
|
||||
.width(80, "%")
|
||||
.onHover(function (hovering) {
|
||||
if(hovering) {
|
||||
this.style.outline = "1px solid rgb(100 115 177)"
|
||||
} else {
|
||||
this.style.outline = ""
|
||||
}
|
||||
})
|
||||
})
|
||||
.width(20, vw)
|
||||
.height(100, vh)
|
||||
.borderRight("2px solid rgb(100 115 177)")
|
||||
.alignItems("center")
|
||||
}
|
||||
}
|
||||
|
||||
register(Sidebar)
|
||||
@@ -4,6 +4,7 @@
|
||||
<title>Blockcatcher</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="/_/icons/logo.svg">
|
||||
<link rel="stylesheet" href="/_/code/styles.css">
|
||||
<script src="/_/code/quill.js"></script>
|
||||
<script type="module" src="/index.js"></script>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user