Add favicons and darker loading experience

parent c1f5102d
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/favicon/mstile-150x150.png"/>
<TileColor>#51b651</TileColor>
</tile>
</msapplication>
</browserconfig>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="500.000000pt" height="500.000000pt" viewBox="0 0 500.000000 500.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,500.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3661 3126 c-294 -56 -524 -234 -646 -500 -44 -95 -66 -183 -74 -291
l-6 -90 -105 -7 c-129 -10 -445 -36 -521 -44 l-56 -6 -12 48 c-74 293 -304
528 -608 620 -77 24 -106 27 -233 28 -167 1 -234 -13 -367 -74 -102 -48 -161
-87 -242 -164 -187 -179 -284 -423 -267 -679 3 -56 9 -115 12 -132 5 -29 4
-30 -73 -59 -43 -16 -97 -37 -121 -47 l-43 -19 15 -29 15 -29 111 44 c120 48
130 50 130 31 0 -7 16 -46 36 -87 109 -229 301 -391 551 -466 78 -24 105 -27
233 -27 116 0 160 4 221 21 254 69 458 237 569 467 61 126 83 219 84 362 l1
122 35 6 c62 9 351 34 475 40 66 4 130 8 142 11 19 3 22 -2 28 -49 27 -195
151 -411 312 -540 440 -355 1084 -216 1333 288 27 55 57 130 66 168 9 37 22
67 28 67 6 0 56 -7 111 -15 55 -8 103 -15 108 -15 4 0 7 15 7 33 l0 34 -112
14 -113 14 -6 130 c-5 86 -14 153 -28 199 -111 369 -428 616 -811 631 -66 3
-132 -1 -179 -9z"/>
</g>
</svg>
{
"name": "Aurora Map",
"short_name": "Aurora Map",
"icons": [
{
"src": "/favicon/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/favicon/android-chrome-384x384.png",
"sizes": "384x384",
"type": "image/png"
}
],
"theme_color": "#000000",
"background_color": "#000000",
"display": "standalone"
}
......@@ -2,29 +2,29 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="apple-touch-icon" sizes="180x180" href="%PUBLIC_URL%/favicon/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/favicon/favicon-16x16.png">
<link rel="manifest" href="%PUBLIC_URL%/favicon/site.webmanifest">
<link rel="mask-icon" href="%PUBLIC_URL%/favicon/safari-pinned-tab.svg" color="#51b651">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon/favicon.ico">
<meta name="msapplication-TileColor" content="#51b651">
<meta name="msapplication-config" content="%PUBLIC_URL%/favicon/browserconfig.xml">
<meta name="theme-color" content="#000000">
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
content="Check Aurora information live, with this fancy site!"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<title>Aurora Map</title>
<style>
html, body {
background: #111;
}
</style>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
......
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
import React from 'react';
import logo from './logo.svg';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.tsx</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
);
}
export default App;
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap');
html, body {
min-height: 100%;
width: 100%;
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
background: #111;
}
import React from 'react';
import Header from '../Header/Header';
import './reset.style.scss';
import './App.style.scss';
import Map from '../Map/Map';
const App: React.FC = () => {
return (
<div className="App">
<Header />
<Map />
</div>
);
}
export default App;
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
import React from 'react';
import HeaderStyle from './header.module.scss';
import backgroundImage from './headerBg.jpg';
import marvinLogo from './marvinLogo.png';
const Header: React.FC = () => (
<div className={HeaderStyle.header} style={{ backgroundImage: `url(${backgroundImage})` }}>
<div className={HeaderStyle.headerInner}>
<img src={marvinLogo} alt="" width="300" />
</div>
</div>
)
export default Header;
.header {
background: no-repeat middle;
background-size: cover;
text-align: center;
height: 150px;
}
.headerInner {
width: 100%;
padding: 20px;
position: absolute;
margin: 0 auto;
padding: 30px 0 0 0;
color: #DDD;
z-index: 2;
}
import React from 'react';
import Plot from 'react-plotly.js';
import { Data, Layout } from 'plotly.js';
import {auroraDataToGraphData} from '../../repositories/auroraData';
interface iPlotState {
data?: Data[];
lastUpdateAt?: string;
width: number;
height: number;
interval?: number;
}
export default class Map extends React.Component<{}, iPlotState> {
constructor(props: {}) {
super(props);
this.state = {
width: 100,
height: 100,
};
}
componentDidMount() {
this.loadData();
this.setDimentions();
this.setEventListners();
this.setIntervals();
}
componentWillUnmount() {
const { interval } = this.state;
window.removeEventListener('resize', this.setDimentions);
if (interval) window.clearInterval(interval);
}
loadData = async () => {
const { data, lastUpdateAt } = await auroraDataToGraphData();
this.setState({ data, lastUpdateAt });
}
setEventListners = () => {
window.addEventListener('resize', this.setDimentions);
}
setIntervals = () => {
const interval = window.setInterval(this.loadData, 30000)
this.setState({ interval })
}
setDimentions = () => {
const vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0)
const vh = Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0)
this.setState({
width: vw,
height: vh - 150,
});
}
layout = (): Layout => {
const { width, height } = this.state;
return {
width,
height,
margin: {
t: 0,
b: 0,
l: 0,
r: 0,
pad: 0,
},
autosize: true,
hovermode:'closest',
showlegend: false,
mapbox: {
center: {
lat: 71.28609560081495,
lon: 22.507328342526908,
},
domain: {
x: [0, 1],
y: [0, 1]
},
style: 'carto-darkmatter', // open-street-map, white-bg, carto-positron, carto-darkmatter, stamen-terrain, stamen-toner, stamen-watercolor
zoom: 3
},
} as Layout
};
render() {
const { data, lastUpdateAt } = this.state;
if (!data && lastUpdateAt) return (<div>loading</div>)
return (
<Plot
data={data!}
layout={this.layout()}
config={{ scrollZoom: false }}
/>
);
}
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import App from './Components/App/App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3">
<g fill="#61DAFB">
<path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/>
<circle cx="420.9" cy="296.5" r="45.7"/>
<path d="M520.5 78.1z"/>
</g>
</svg>
import { Data } from "plotly.js";
interface iLocation {
average_deviation: number,
average_total: number,
kp: number,
lat: number,
long: number,
quiet_mean_tot: number
}
interface iAuroraData {
last_update_at: string,
locations: {
andenes: iLocation;
beerenberg: iLocation;
jackvik_se: iLocation;
karmoy: iLocation;
nordkap: iLocation;
svalbard: iLocation;
tromso: iLocation;
}
}
type iLocationName = "andenes" | "beerenberg" | "jackvik_se" | "karmoy" | "nordkap" | "svalbard" | "tromso";
const humanizeLocationName = (location: iLocationName) => {
switch (location) {
case "andenes":
return "Andenes"
case "beerenberg":
return "Beerenberg"
case "jackvik_se":
return "Jackvik"
case "karmoy":
return "Karmoy"
case "nordkap":
return "Nordkap"
case "svalbard":
return "Svalbard"
case "tromso":
return "Tromsø"
default:
return "Unknown"
}
}
export const getAuroraData = async () => {
const response = await fetch('https://aurora.hendrikpeter.net/api/aurora_data.json')
if (response.status !== 200) throw new Error('connection error');
const responseData: iAuroraData = await response.json()
return responseData;
};
export const auroraDataToGraphData = async () => {
const { locations, last_update_at } = await getAuroraData()
const locationNames = Object.keys(locations) as iLocationName[];
const data = locationNames.map((name) => {
const location = locations[name]
return {
type:'scattermapbox',
lat:[location.lat.toString()],
lon:[location.long.toString()],
mode:'markers',
marker: {
size: ((location.kp + 1) * 3) + 5,
color: `rgba(83, 207, 85, ${Math.min((location.kp / 7) + 0.3, 1)})`,
},
text:[`${humanizeLocationName(name)} Kp${location.kp}`],
name: '',
} as Data
});
return {data, lastUpdateAt: last_update_at}
};
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment