This commit is contained in:
Martin Donnelly 2020-04-07 16:44:31 +01:00
commit 392d9fb460
30 changed files with 6700 additions and 0 deletions

62
.eslintrc.json Normal file
View File

@ -0,0 +1,62 @@
{
"parserOptions": {
"ecmaVersion": 2019,
"sourceType": "module"
},
"env": {
"es6": true,
"browser": true
},
"plugins": [
"svelte3"
],
"overrides": [
{
"files": [
"**/*.svelte"
],
"processor": "svelte3/svelte3"
}
],
"rules": {
"arrow-spacing": "error",
"block-scoped-var": "error",
"block-spacing": "error",
"brace-style": ["error", "stroustrup", {}],
"camelcase": "error",
"comma-dangle": ["error", "never"],
"comma-spacing": ["error", { "before": false, "after": true }],
"comma-style": [1, "last"],
"consistent-this": [1, "_this"],
"curly": [1, "multi"],
"eol-last": 1,
"eqeqeq": 1,
"func-names": 1,
"indent": ["error", 2, { "SwitchCase": 1 }],
"lines-around-comment": ["error", { "beforeBlockComment": true, "allowArrayStart": true }],
"max-len": [1, 240, 2], // 2 spaces per tab, max 80 chars per line
"new-cap": 1,
"newline-before-return": "error",
"no-array-constructor": 1,
"no-inner-declarations": [1, "both"],
"no-mixed-spaces-and-tabs": 1,
"no-multi-spaces": 2,
"no-new-object": 1,
"no-shadow-restricted-names": 1,
"object-curly-spacing": ["error", "always"],
"padded-blocks": ["error", { "blocks": "never", "switches": "always" }],
"prefer-const": "error",
"prefer-template": "error",
"one-var": 0,
"quote-props": ["error", "always"],
"quotes": [1, "single"],
"radix": 1,
"semi": [1, "always"],
"space-before-blocks": [1, "always"],
"space-infix-ops": 1,
"vars-on-top": 1,
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 1 }],
"spaced-comment": ["error", "always", { "markers": ["/"] }]
}
}

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
/node_modules/
/public/build/
.DS_Store

2
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# Default ignored files
/workspace.xml

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EslintConfiguration">
<custom-configuration-file used="true" path="$PROJECT_DIR$/.eslintrc.json" />
</component>
</project>

6
.idea/misc.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/svelte-silvrtree.iml" filepath="$PROJECT_DIR$/.idea/svelte-silvrtree.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

93
README.md Normal file
View File

@ -0,0 +1,93 @@
*Looking for a shareable component template? Go here --> [sveltejs/component-template](https://github.com/sveltejs/component-template)*
---
# svelte app
This is a project template for [Svelte](https://svelte.dev) apps. It lives at https://github.com/sveltejs/template.
To create a new project based on this template using [degit](https://github.com/Rich-Harris/degit):
```bash
npx degit sveltejs/template svelte-app
cd svelte-app
```
*Note that you will need to have [Node.js](https://nodejs.org) installed.*
## Get started
Install the dependencies...
```bash
cd svelte-app
npm install
```
...then start [Rollup](https://rollupjs.org):
```bash
npm run dev
```
Navigate to [localhost:5000](http://localhost:5000). You should see your app running. Edit a component file in `src`, save it, and reload the page to see your changes.
By default, the server will only respond to requests from localhost. To allow connections from other computers, edit the `sirv` commands in package.json to include the option `--host 0.0.0.0`.
## Building and running in production mode
To create an optimised version of the app:
```bash
npm run build
```
You can run the newly built app with `npm run start`. This uses [sirv](https://github.com/lukeed/sirv), which is included in your package.json's `dependencies` so that the app will work when you deploy to platforms like [Heroku](https://heroku.com).
## Single-page app mode
By default, sirv will only respond to requests that match files in `public`. This is to maximise compatibility with static fileservers, allowing you to deploy your app anywhere.
If you're building a single-page app (SPA) with multiple routes, sirv needs to be able to respond to requests for *any* path. You can make it so by editing the `"start"` command in package.json:
```js
"start": "sirv public --single"
```
## Deploying to the web
### With [now](https://zeit.co/now)
Install `now` if you haven't already:
```bash
npm install -g now
```
Then, from within your project folder:
```bash
cd public
now deploy --name my-project
```
As an alternative, use the [Now desktop client](https://zeit.co/download) and simply drag the unzipped project folder to the taskbar icon.
### With [surge](https://surge.sh/)
Install `surge` if you haven't already:
```bash
npm install -g surge
```
Then, from within your project folder:
```bash
npm run build
surge public my-project.surge.sh
```

3276
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

25
package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "svelte-app",
"version": "1.0.0",
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^11.0.0",
"@rollup/plugin-node-resolve": "^7.0.0",
"eslint": "^6.8.0",
"eslint-plugin-svelte3": "^2.7.3",
"rollup": "^1.20.0",
"rollup-plugin-livereload": "^1.0.0",
"rollup-plugin-svelte": "^5.0.3",
"rollup-plugin-terser": "^5.1.2",
"svelte": "^3.0.0"
},
"dependencies": {
"fecha": "^4.2.0",
"moment": "^2.24.0",
"sirv-cli": "^0.4.4"
}
}

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/gfx/popout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 B

1961
public/global.css Normal file

File diff suppressed because it is too large Load Diff

21
public/index.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<title>Svelte app</title>
<link rel='icon' type='image/png' href='/favicon.png'>
<link href="//fonts.googleapis.com/css2?family=Roboto+Slab&display=swap" rel="stylesheet">
<link href="//cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css" rel="stylesheet" type="text/css"/>
<link rel='stylesheet' href='/global.css'>
<link rel='stylesheet' href='/build/bundle.css'>
<script defer src='/build/bundle.js'></script>
</head>
<body>
</body>
</html>

71
rollup.config.js Normal file
View File

@ -0,0 +1,71 @@
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
const production = !process.env.ROLLUP_WATCH;
export default {
'input': 'src/main.js',
'output': {
'sourcemap': true,
'format': 'iife',
'name': 'app',
'file': 'public/build/bundle.js'
},
'plugins': [
svelte({
// enable run-time checks when not in production
'dev': !production,
// we'll extract any component CSS out into
// a separate file - better for performance
'css': css => {
css.write('public/build/bundle.css');
}
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration -
// consult the documentation for details:
// https://github.com/rollup/plugins/tree/master/packages/commonjs
resolve({
'browser': true,
'dedupe': ['svelte']
}),
commonjs(),
// In dev mode, call `npm run start` once
// the bundle has been generated
!production && serve(),
// Watch the `public` directory and refresh the
// browser on changes when not in production
!production && livereload('public'),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser()
],
'watch': {
'clearScreen': false
}
};
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
'stdio': ['ignore', 'inherit', 'inherit'],
'shell': true
});
}
}
};
}

407
src/App.svelte Normal file
View File

@ -0,0 +1,407 @@
<script>
import Panel from './components/Panel.svelte';
import Header from './components/Header.svelte';
import Events from './components/Events.svelte';
import Password from './components/Password.svelte';
import Bitcoin from './components/Bitcoin.svelte';
import Weather from './components/Weather.svelte';
import Fx from './components/Fx.svelte';
import Train from './components/Train.svelte';
import Route from "./components/Route.svelte";
export let events = [];
function popitoutSmall(e) {
if (e.target.dataset.url) {
let newwindow = window.open(e.target.dataset.url, 'name', 'height=400,width=520');
if (window.focus) {
newwindow.focus();
}
return false;
}
}
function popitout(e) {
if (e.target.dataset.url) {
let newwindow = window.open(e.target.dataset.url, 'name', 'height=600,width=570');
if (window.focus) {
newwindow.focus();
}
return false;
}
}
</script>
<main>
<Header/>
<div class="mui-container">
<Events events="{events}"/>
<div class="mui-panel">
<div class="mui-row">
<Panel>
<div class="mui--text-title mui-text-black">Starting Points/Metasites</div>
<ul>
<li><a href="https://www.silvrtree.co.uk/today">Today</a></li>
<li><a href="https://www.silvrtree.co.uk/events">Events</a></li>
<li><a href="https://www.silvrtree.co.uk/cinema/0">Cinema</a></li>
<li><a href="https://feedly.com/#my">Feedly</a></li>
<li><a href="https://www.reddit.com">Reddit</a></li>
<li><a href="http://www.facebook.com/">Facebook</a></li>
<li><a href="http://www.yahoo.com/">Yahoo!</a></li>
<li><a href="https://stackedit.io/editor">Journal Editor</a></li>
<li><a href="http://www.unmajestic.com/home/bookmarks.php">Slack Bookmarks</a></li>
<li><a href="http://www.rssmix.com/u/7711845">Paleo Mix</a></li>
<li><a href="http://status.hivehome.com/">Hive Status</a></li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Tools</div>
<ul>
<li><a href='/cleaner'>Cleaner</a></li>
<li><a href='https://kanbanflow.com'>Kanban Flow</a></li>
<li><a href="https://www.linode.com/">Linode</a></li>
<li><a href="http://www.colorzilla.com/gradient-editor/">CSS Gradient Generator</a></li>
<li><a href="http://utilities-online.info/xmltojson">XML to JSON</a></li>
<li><a href="http://shancarter.com/data_converter">CSV to JSON</a></li>
<li><a href="http://cubic-bezier.com/">Cubic Bezier</a></li>
<li><a href="http://gskinner.com/RegExr/">RegEx Tool</a></li>
<li><a href="http://closure-compiler.appspot.com/home">Closure Compiler</a></li>
<li><a href="http://jsonlint.com/">JSON Lint</a></li>
<li><a href="http://jsoneditoronline.org/">JSON Editor</a></li>
<li><a href="http://www.base64decode.org/">Base64 Decoder</a></li>
<li><a href="http://jsbeautifier.org/">JS Beautifier</a></li>
<li><a href="http://spritepad.wearekiss.com/">Spritepad</a></li>
<li><a href="http://draeton.github.com/stitches/">Sprite Sheet Generator</a></li>
<li><a href="http://www.cleancss.com/">CSS Optimizer</a></li>
<li><a href="http://fontello.com/">Icon Font Generator</a></li>
<li><a href="http://html2jade.aaron-powell.com/">HTML to Jade</a></li>
<li><a href="http://cdnjs.com//">Cloudflare JS CDN</a></li>
<li><a href="http://www.willpeavy.com/minifier/">HTML Minifier</a></li>
<li><a href='https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet'>XSS Cheat Sheet</a></li>
<li><a href='http://jsfiddle.net/'>JSFiddle</a></li>
<li><a href="http://jsbin.com/">JS Bin</a></li>
<li><a href='https://draftin.com/documents'>Draftin</a></li>
<li><a href="https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html">Android Asset</a></li>
<li><a href="https://xkpasswd.net/s/">Password Generator</a></li>
<li><a href="https://howsecureismypassword.net/">Password Checker</a></li>
<li><a href="https://archive.today">Archive Today</a></li>
<li><a href="http://staticmapmaker.com/google/">Static Map Generator</a></li>
<li><a href="https://httpbin.org/">AJAX Endpoints</a></li>
<li><a href="https://tools.bartlweb.net/webssh/">WebSSH</a></li>
<li><a href="http://jade-lang.com/demo/">Jade Tester</a></li>
<li><a href="https://es6console.com/">ES6 Console</a></li>
<li><a href="https://crontab.guru/">Cron Guru</a></li>
<li><a href="https://fontdrop.info/">FontDrop</a> </li>
</ul>
<Password/>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Bitcoin <Bitcoin/></div>
<ul>
<li><a href="https://www.bitstamp.net">Bitstamp</a></li>
<li><a href="https://www.kraken.net">Kraken</a></li>
<li><a href="https://cryptowat.ch/">Cryptowat.ch</a></li>
<li><a href="http://www.coindesk.com/price/">BTC Chart</a></li>
<li><a href="https://bitcoinwisdom.com/">BTC Chart 2</a></li>
<li><a href="http://bitcoinity.org/markets/bitstamp/USD">BitStamp Chart</a></li>
<li><a href="http://btc-chart.com/market/bitstamp/86400">Bitstamp Chart 2</a></li>
<li><a href="https://bitbargain.co.uk">BitBargin UK</a></li>
<li><a href="https://yacuna.com/">Yacuna UK</a></li>
<li><a href="http://blockchain.info/">Blockchain</a></li>
<li><a href="http://bitminter.com/">Bitminter</a></li>
<li><a href="http://preev.com/">BTC Exchange Rate</a></li>
<li><a href="http://www.silvrtree.co.uk/watch.html">CFT Watcher</a>
<span style="cursor: pointer;" data-url="http://www.silvrtree.co.uk/watch.html">
<img on:click|stopPropagation={popitoutSmall} src="gfx/popout.png" alt="CFT Watcher" data-url="http://www.silvrtree.co.uk/watch.html">
</span>
</li>
</ul>
</Panel>
</div>
<div class="mui-row">
<Panel>
<div class="mui--text-title mui-text-black">Package Tracking</div>
<!-- Computer News -->
<ul>
<li><a href="http://m.ups.com/">UPS</a></li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Weather</div>
<ul>
<li>
<a href="http://www.accuweather.com/ukie/index-forecast.asp?postalcode=G82%201RG">Dumbarton
Weather</a>
</li>
<li>
<a href="http://www.wunderground.com/cgi-bin/findweather/getForecast?query=dumbarton,%20uk&wuSelect=WEATHER">WU
Dumbarton Weather</a>
</li>
<li>
<a href="http://weather.yahoo.com/forecast/UKXX0663.html?unit=c">Y! Dumbarton Weather</a>
</li>
<li>
<a href="http://www.accuweather.com/ukie/index-forecast.asp?postalcode=G9%202SU">Glasgow
Weather</a>
</li>
<li>
<a href="http://www.wunderground.com/cgi-bin/findweather/getForecast?query=glasgow,%20uk&wuSelect=WEATHER">WU
Glasgow Weather</a>
</li>
<li><a href="http://www.nowcast.co.uk/lightning/">Live Lightning</a>
</li>
<li>
<a href="http://www.upminsterweather.co.uk/test/live_lightning.htm">Other Live Lightning</a>
</li>
<li>
<a href="http://www.meteorologica.info/freedata_lightning.htm">Closer Live Lightning</a>
</li>
<li>
<a href="http://www.malvernwx.co.uk/lightning_data/lightning.htm">Multiple Lightning</a>
</li>
<li>
<a href="http://www.blitzortung.org/Webpages/index.php">European Lightning</a>
</li>
<li>
<a href="http://www.madpaddler.net/wxlightning.php">East Kilbride Lightning</a>
</li>
<li>
<a href="http://www.bordersweather.co.uk/wxlightning.php">Borders Lightning</a>
</li>
<li><a href='http://www.lightningmaps.org/blitzortung/europe/index.php?bo_page=map&lang=en'>Best Live Lightning</a></li>
<li><a href="http://www.madpaddler.net/wxais.php">Ships</a></li>
<li><a href='http://www.raintoday.co.uk/'>Rain Today</a></li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Free Email WEBpages</div>
<!-- Free Email WEBpages -->
<ul>
<li><a href="http://gmail.google.com/">Gmail</a></li>
<li>
<a href="http://www.unmajestic.com/webmail/">Unmajestic Webmail</a>
</li>
<li>
<a href="http://www.artizanconsulting.co.uk/webmail/">Artizan Webmail</a>
</li>
<li><a href="http://mail.yahoo.com">Yahoo Mail</a></li>
<li>
<a href="https://www.guerrillamail.com/">Guerrilla Mail Anti Spam</a>
</li>
</ul>
</Panel>
</div>
<div class="mui-row">
<Panel>
<div class="mui--text-title mui-text-black">Contracting</div>
<ul>
<li><a href='https://outsauce.backofficeportal.com/Secure/Candidate/Default.aspx'>Outsauce Timesheets</a></li>
<li><a href='https://worksheets.computerfutures.com/'>CF Timesheets</a></li>
<li><a href="http://www.monster.co.uk/">monster</a></li>
<li><a href="http://www.cwjobs.co.uk/">cwjobs</a></li>
<li><a href="http://www.s1jobs.com/myaccount/">s1jobs</a></li>
<li><a href="http://www.jobserve.com/">jobserve</a></li>
<li><a href="http://www.jobsite.co.uk/jbe/myprofile/">jobsite</a>
</li>
<li>
<a href="http://www.itjobswatch.co.uk/contracts/scotland/asp.do">IT Jobs Watch Scotland</a>
</li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Entertainment</div>
<!-- Entertainment -->
<ul>
<li>
<a href="http://genre.amazingradio.co.uk:8000/stream.mp3?arplayer=1">Amazing Radio Chill</a>
</li>
<li>
<a href="http://www.cineworld.co.uk/cinemas/28?fallback=false&isMobileAgent=false">Cineworld</a>
</li>
<li>
<a href="http://www.showcasecinemas.co.uk/showtimes/default.asp?selectTheatre=8508">Showcase</a>
</li>
<li><a href="http://www.imdb.com/">Imdb</a></li>
<li><a href="http://www.epguides.com/">EPGuides</a></li>
<li><a href="http://eztv.it">Eztv</a></li>
<li><a href="http://www.mininova.org">Mininova</a></li>
<li><a href="http://www.scrapetorrent.com">Scrapetorrent</a></li>
<li>
<a href="http://glasgow.myvillage.com/events">Whats on In Glasgow</a>
</li>
<li><a href="http://www.5pm.co.uk/Search/Event/">Local Events</a>
</li>
<li><a href="http://necta.jansenit.com:8000/necta192.mp3">Nectarine</a>
</li>
<li><a href="/playlists/str.pls">STR - Space Travel Radio</a>
</li>
<li><a href="/playlists/musik.drumstep.pls">musik.drumstep</a>
</li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Travel <Fx/></div>
<!-- Travel -->
<div>
<Train fromStation="dbe" toStation="glq"/>
<Train fromStation="glq" toStation="dbe"/>
</div>
<div>
<Route/>
</div>
<ul>
<li>
<a href='http://www.journeycheck.com/firstscotrail'>Journey Check</a>
</li>
<li>
<a href="https://www.virgintrainseastcoast.com/trainmapper/">Train Mapper</a>
</li>
<li>
<a href="https://trafficscotland.org/whatsnearme/#">Traffic Scotland</a>
</li>
<li>
<a href="http://www.theaa.com/traffic-news/glasgow%20uk/">AA Traffic News</a>
</li>
<li>
<a href="http://ojp.nationalrail.co.uk/service/ldbboard/dep/DBE/WES/To?ar=true">DBE->WES</a>
/
<a href="http://www.traintime.uk/index.php?view=desktop&from=DBE&to=WES">Advanced</a>
</li>
<li>
<a href="http://ojp.nationalrail.co.uk/service/ldbboard/dep/WES/DBE/To?ar=true">WES->DBE</a>
<span style="cursor: pointer;"><img
on:click|stopPropagation={popitout} src="gfx/popout.png" data-url="http://ojp.nationalrail.co.uk/service/ldbboard/dep/WES/DBE/To?ar=true#skip-content-hold"></span>
/
<a href="http://www.traintime.uk/index.php?view=desktop&from=WES&to=DBE">Advanced</a>
</li>
<li>
<a href="http://www.livedepartureboards.co.uk/ldb/summary.aspx?T=DBE">DBE Board</a>
/
<a href="http://www.stationboard.uk/index.php?view=desktop&station1=DBE&direction=departures">Advanced</a>
</li>
<li>
<a href="http://www.livedepartureboards.co.uk/ldb/summary.aspx?T=GLQ">GLQ Trains</a> /
<a href="http://www.stationboard.uk/index.php?view=desktop&station1=GLQ&direction=departures">Adv</a> /
<a href="http://www.traintime.uk/index.php?view=desktop&from=GLQ&to=DBE">GLQ->DBE</a>
</li>
<li><a href="http://www.kayak.co.uk/">Kayak</a></li>
<li><a href="http://www.travelocity.co.uk/">Travelocity</a></li>
<li><a href="http://www.travel.com/sitemap.htm">Travel.com</a></li>
<li>
<a href="http://www.landings.com/_landings/pages/commercial.html">Airlines</a>
</li>
<li><a href="http://www.flightstats.com">Landings</a></li>
<li>
<a href="http://www.lib.utexas.edu/Libs/PCL/Map_collection/map_sites/map_sites.html#general">Maps</a>
</li>
<li><a href="http://www.sitesatlas.com/Maps/">Maps2</a></li>
<li><a href="http://www.itn.net/">ITN</a></li>
<li><a href="http://bahn.hafas.de/bin/query.exe/en">HAFAS</a></li>
<li><a href="http://bahn.hafas.de/bin/query.exe/en">DieBahn</a></li>
<li><a href="http://www.cwrr.com/nmra/travelreg.html">RailUSA</a>
</li>
<li>
<a href="http://www.trainweb.com/frames_travel.html">TrainWeb</a>
</li>
<li><a href="http://www.cwrr.com/nmra/travelw2.html">RailWorld</a>
</li>
<li><a href="http://www.xe.net/currency/">Currency Converter</a>
</li>
<li>
<a href="http://www.cia.gov/cia/publications/factbook/index.html">CIA</a>
</li>
<li><a href="http://maps.google.com/">GMaps</a></li>
<li><a href='https://unop.uk/tube/'>Tube Status</a></li>
</ul>
</Panel>
</div>
<div class="mui-row">
<Panel>
<div class="mui--text-title mui-text-black">Computer Software, etc.</div>
<ul>
<li><a href="">Portable Apps</a></li>
<li><a href="http://www.newfreeware.com/">NewFreeware</a></li>
<li>
<a href="http://www.makeuseof.com/tag/portable-software-usb/">Portable Software</a>
</li>
<li>
<a href="http://www.portablefreeware.com/">Portable Freeware Collection</a>
</li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Reference &amp; Special sites</div>
<!-- Reference and Special sites -->
<ul>
<li><a href="http://www.glossarist.com/default.asp">Glossaries</a>
</li>
<li><a href="http://www.convert-me.com/en/">Converters</a></li>
<li>
<a href="http://decoder.americom.com/cgi-bin/decoder.cgi">DECODE</a>
</li>
<li><a href="http://www.rxlist.com/">Drugs</a></li>
<li><a href="http://www.ncbi.nlm.nih.gov/PubMed/">Medline</a></li>
<li>
<a href="http://www.logos.it/dictionary/owa/sp?lg=EN">Translation</a>
</li>
<li><a href="http://www.onelook.com/">One Look</a></li>
<li><a href="http://www.defenselink.mil/">US Military</a></li>
<li><a href="http://www.fedworld.gov/">US Fed</a></li>
<li><a href="http://www.ih2000.net/ira/legal.htm">Legal</a></li>
<li><a href="http://www.nih.gov/">NIH</a></li>
<li><a href="http://www.refdesk.com/">RefDESK</a></li>
<li><a href="http://www.britannica.com/">Britannica</a></li>
<li><a href="http://www.capitolimpact.com/gw/">States</a></li>
<li><a href="http://www.packtrack.com/">PackTrack</a></li>
<li><a href="http://www.acronymfinder.com/">Acronym</a></li>
<li><a href="http://www.visualthesaurus.com/">V-Thes</a></li>
<li>
<a href="http://www.timelineindex.com/content/home/forced">Timelines</a>
</li>
<li><a href="http://en.wikipedia.org/wiki/Main_Page">Wikipedia</a>
</li>
</ul>
</Panel>
<Panel>
<div class="mui--text-title mui-text-black">Earth and Beyond</div>
<!-- Good Reading Misc. -->
<ul>
<li><a href="http://enbarsenal.com">ENB Arsenal</a></li>
<li><a href="http://enb.wikia.com/">ENB Wikia</a></li>
<li><a href="http://enb.gearlist.co.uk/">Gear List</a></li>
<li><a href='http://forum.enb-emulator.com/'>Emu Forum</a></li>
<li><a href="http://net-7.org/wiki/index.php?title=Main_Page">Net 7 Wiki</a></li>
<li><a href="http://spaceengineers.wikia.com/wiki/Space_Engineers_Wiki">Space Engineers Wiki</a></li>
<li><a href="http://forums.keenswh.com/">Space Engineers Forum</a></li>
</ul>
</Panel>
</div>
</div>
<Weather/>
</div>
</main>
<style >
</style>

View File

@ -0,0 +1,125 @@
<script>
import {get, writable} from 'svelte/store';
import {onMount} from 'svelte';
const data = {
'lastGBP': 0.0,
'lastUSD': 0.0,
'lows': {'gbp': 0, 'usd': 0},
'highs': {'gbp': 0, 'usd': 0},
'eclass': '',
'balance': 0.0,
'trend': 0
};
let lastUSD = 0, lastGBP, owned, eclass="", trendClass="";
const btcData = writable(data);
const balance = writable(0);
btcData.subscribe(btcObj => {
lastUSD = btcObj.lastUSD;
lastGBP = btcObj.lastGBP;
eclass = btcObj.eclass;
});
onMount(async () => {
await update();
});
function recalc(freshBTC) {
let data = get(btcData);
data.gbp = freshBTC.bpi.GBP.rate_float;
data.usd = freshBTC.bpi.USD.rate_float;
data.trend = freshBTC.trend;
let lastGBP = data.lastGBP;
let lastUSD;
const g = data.gbp;
const u = data.usd;
const lows = data.lows;
const highs = data.highs;
let eclass = data.eclass;
const balance = data.balance;
let trend = data.trend;
if ((trend === undefined) || (trend === null)) trend = 1;
if (g !== undefined) {
if (data.lastGBP !== 0)
eclass = g > lastGBP ? 'up' : 'down';
else {
lows.gbp = g;
lows.usd = u;
highs.gbp = g;
highs.usd = u;
eclass = '';
}
lastGBP = g;
lastUSD = u;
if (g < lows.gbp) lows.gbp = g;
if (u < lows.usd) lows.usd = u;
if (highs.gbp < g) highs.gbp = g;
if (highs.usd < u) highs.usd = u;
if (trend > 1.00)
trendClass = 'trendUp';
else if (trend < 1.00)
trendClass = 'trendDown';
else
trendClass = '';
data = {
lastGBP,
lastUSD,
lows,
highs,
eclass,
balance,
trend
};
}
data.stub = Math.random(Number.MAX_SAFE_INTEGER).toString(32);
btcData.set(data);
}
async function update() {
await getBtc();
const now = new Date();
const mod = 300000 - (now.getTime() % 300000);
const btcupdateFn = function () {
update();
};
setTimeout(btcupdateFn.bind(this), mod + 10);
}
async function getBtc() {
const res = await fetch("http://localhost:9000/btc");
const json = await res.json();
if (json) {
recalc(json);
}
}
// &#36;${parseFloat(btcdata.lastUSD.toFixed(2)) } / &pound;${parseFloat(btcdata.lastGBP.toFixed(2))} <div>&#8383;${balance} &pound;${parseFloat(owned.toFixed(2))}</div>
</script>
{#if lastUSD!==0}
<span id="trend" class="{trendClass}"> </span>
<span id="btc" class="{eclass}">&#36;{lastUSD.toFixed(2)} / &pound;{lastGBP.toFixed(2)}
</span>
{/if}

View File

@ -0,0 +1,49 @@
<script>
import { onMount} from 'svelte';
export let events;
onMount(async () => {
// calculate the dates
update();
});
const update = () => {
const now = new Date;
const mod = 3600000 - (now.getTime() % 3600000);
events = events.map((item) => {
item.days = Math.ceil(getDays(now, item.event));
item.weeks = Math.ceil(getDays(now, item.event) / 7);
return item;
});
const clockFn = function () {
update();
};
setTimeout(clockFn.bind(this), mod + 10);
};
const getDays = (startdate, enddate) => {
let r, s, e;
s = startdate.getTime();
e = enddate.getTime();
r = (e - s) / (24 * 60 * 60 * 1000);
return r;
}
</script>
<div id="container" class="mui-panel">
<div class="mui-row" id="events">
{#each events as event}
<div class='mui-col-xs-12 mui-col-md-3'>
{event.label} {event.days} days / {event.weeks} weeks
</div>
{/each}
</div>
</div>

61
src/components/Fx.svelte Normal file
View File

@ -0,0 +1,61 @@
<script>
import {onMount} from 'svelte';
let fxData={};
onMount(async () => {
await update();
});
async function update() {
await getFX();
const now = new Date();
const mod = 1800000 - (now.getTime() % 1800000);
const fxUpdateFn = function () {
update();
};
setTimeout(fxUpdateFn.bind(this), mod + 10);
}
function reduceFX(data) {
if (data.rates !== undefined) {
const gpbex = (1 / data.rates.GBP);
const sekex = (gpbex * data.rates.SEK);
fxData = {
'usd': 1,
'gbp': data.rates.GBP,
'sek': data.rates.SEK,
'gpbe': gpbex,
'sekex': sekex
};
}
}
async function getFX() {
const res = await fetch("http://localhost:9000/fx");
const json = await res.json();
if (json) reduceFX(json);
}
</script>
<style>
* {
font-size: 90%;
}
</style>
{#if fxData.gpbe}
<span>
&pound;1 = &dollar;{parseFloat(fxData.gpbe.toFixed(2))} = { parseFloat(fxData.sekex.toFixed(2))} SEK
</span>
{/if}

View File

@ -0,0 +1,5 @@
<div class="mui-appbar mui--appbar-line-height">
<div class="mui-container-fluid">
Slack
</div>
</div>

View File

@ -0,0 +1,3 @@
<div class="mui-col-md-4">
<slot></slot>
</div>

View File

@ -0,0 +1,73 @@
<script>
Array.prototype.random = function () {
return this[Math.floor((Math.random() * this.length))];
};
let longPassword;
let shortPassword;
const alpha = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const whitespace = ['.', '~', '#', '!', '$', '+', '-', '+'];
const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const left = ['Alabama', 'Alaska', 'Arizona', 'Maryland', 'Nevada', 'Mexico', 'Texas', 'Utah', 'Glasgow', 'Inverness', 'Edinburgh', 'Dumbarton',
'Balloch', 'Renton', 'Cardross', 'Dundee', 'Paisley',
'Hamilton', 'Greenock', 'Falkirk',
'Irvine',
'Renfrew',
'Erskine',
'London',
'Hammersmith',
'Islington',
'Silver', 'Black', 'Yellow', 'Purple', 'White', 'Pink', 'Red', 'Orange', 'Brown', 'Green', 'Blue', 'Amber', 'Aqua',
'Azure', 'Bronze', 'Coral', 'Copper', 'Crimson', 'Cyan', 'Ginger', 'Gold', 'Indigo', 'Jade', 'Ruby', 'Cedar', 'Cream', 'Peach', 'Sepcia',
'Mercyful', 'Cyber', 'Ultra', 'Hunter', 'Electric', 'Steel', 'Fire', 'Smoke', 'Thunder', 'Pewter', 'Stone', 'Iron', 'Shadow', 'Grey', 'Mocha',
'Wood', 'Space', 'Manic', 'Grunt', 'X-Ray', 'Sabbra','Atomic'
];
const right = ['Aganju', 'Cygni', 'Akeron', 'Antares', 'Aragoth', 'Ardus', 'Carpenter', 'Cooper', 'Dahin', 'Capella', 'Endriago', 'Gallina',
'Fenris', 'Freya', 'Glenn', 'Grissom', 'Jotunheim', 'Kailaasa', 'Lagarto', 'Muspelheim', 'Nifleheim', 'Primus', 'Vega', 'Ragnarok', 'Shepard',
'Slayton', 'Tarsis', 'Mercury', 'Venus', 'Mars', 'Earth', 'Terra', 'Jupiter', 'Saturn', 'Uranus', 'Neptune', 'Pluto', 'Europa', 'Ganymede',
'Callisto', 'Titan', 'Juno', 'Eridanus', 'Scorpius', 'Crux', 'Cancer', 'Taurus', 'Lyra', 'Andromeda', 'Virgo', 'Aquarius', 'Cygnus', 'Corvus',
'Taurus', 'Draco', 'Perseus', 'Pegasus', 'Gemini', 'Columbia', 'Bootes', 'Orion', 'Deneb', 'Merope', 'Agate', 'Amber', 'Beryl', 'Calcite',
'Citrine', 'Coral', 'Diamond', 'Emerald', 'Garnet', 'Jade', 'Lapis', 'Moonstone', 'Obsidian', 'Onyx', 'Opal', 'Pearl', 'Quartz', 'Ruby',
'Sapphire', 'Topaz', 'Iron', 'Lead', 'Nickel', 'Copper', 'Zinc', 'Tin', 'Manes', 'Argon', 'Neon', 'Alpha', 'Bravo', 'Charlie', 'Delta',
'Echo', 'Foxtrot', 'Golf', 'Hotel', 'India', 'Juliett', 'Kilo', 'Lima', 'Mike', 'November', 'Oscar', 'Papa', 'Quebec', 'Romeo', 'Sierra',
'Tango', 'Uniform', 'Victor', 'Whisky', 'Xray', 'Yankee', 'Zulu', 'Fate', 'Miner', 'Blaster', 'Click', 'Noise', 'Cadabra', 'Shotgun'];
function randomAmount(i) {
let str = '';
for (let t = 0; t < i; t++)
str = str + alpha.random();
return str;
}
function generatePassword(e) {
// const ws = whitespace.random();
const ws = '.';
longPassword = (`${left.random() } ${ right.random() } ${ numberCluster()}`).split(' ').join(ws);
shortPassword = (`${randomAmount(5) } ${ randomAmount(5)}`).split(' ').join(ws);
}
function numberCluster() {
return numbers.random() + numbers.random() + numbers.random();
}
</script>
<div id="passwords">
<button on:click={generatePassword} class="mui-btn mui-btn--flat" id='newPassword'>Generate Password</button>
{#if longPassword}
<div id='passwordOut' class='password'>
<div>Long: {longPassword}</div><div>Short: {shortPassword}</div>
</div>
{/if}
</div>

154
src/components/Route.svelte Normal file
View File

@ -0,0 +1,154 @@
<script>
import {route} from './store';
let visible = false;
let fromStation;
let toStation;
let url;
let routeData = {};
let services = [];
route.subscribe(async (v) => {
console.log('>> route', v);
fromStation = v.fromStation;
toStation = v.toStation;
visible = (fromStation !== '') ? !visible : false;
// url = `https://traintimes.silvrtree.co.uk/gettrains?from=${ fromStation }&to=${ toStation}`;
url = `http://localhost:8100/gettrains?from=${fromStation}&to=${toStation}`;
if (fromStation !== '' && visible) {
await update();
}
});
function reduceRoute(data) {
const newData = {};
newData.fromName = data.locationName;
newData.toName = data.filterLocationName;
newData.services = [];
if (typeof data.trainServices === 'object' && data.trainServices !== null)
for (const item of data.trainServices) {
const dest = item.destination[0];
const via = dest.via !== null ? `<em>${dest.via}</em>` : '';
const platform = item.platform !== null ? item.platform : '💠';
const time = item.sta !== null ? item.sta : `D ${item.std}`;
const status = item.eta !== null ? item.eta : item.etd;
const cls = (status.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
newData.services.push({
'location': dest.locationName,
'time': time,
'via': via,
'class': cls,
'status': status,
'platform': platform,
'cancelReason': item.cancelReason,
'type': 'train',
'isCancelled': item.isCancelled,
icon: ''
});
}
if (typeof data.busServices === 'object' && data.busServices !== null)
for (const item of data.busServices) {
const dest = item.destination[0];
const via = dest.via !== null ? `<em>${dest.via}</em>` : '';
const platform = item.platform !== null ? item.platform : '';
const time = item.sta !== null ? item.sta : `D ${item.std}`;
const status = item.eta !== null ? item.eta : item.etd;
const cls = (status.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
newData.services.push({
'location': dest.locationName,
'time': time,
'via': via,
'class': cls,
'status': status,
'platform': platform,
'cancelReason': item.cancelReason,
'type': 'bus',
'isCancelled': item.isCancelled,
icon: '🚌 '
});
}
routeData = newData;
services = newData.services;
console.log(routeData);
}
async function update() {
await getRoute();
const now = new Date();
const mod = 180000 - (now.getTime() % 180000);
const routeUpdateFn = function () {
update();
};
if(visible) setTimeout(routeUpdateFn.bind(this), mod + 10);
}
async function getRoute() {
console.log('Get route', url);
const res = await fetch(url);
const json = await res.json();
if (json) {
console.log(json);
// data = json;
reduceRoute(json);
}
}
</script>
<style>
.routeBox {
border:1px dotted silver;
}
</style>
{#if visible}
<div class="routeBox">
<div>{routeData.fromName} TO {routeData.toName}</div>
<table class="mui-table mui-table-bordered">
<thead>
<tr>
<th>Destination</th>
<th>Time</th>
<th>Status</th>
<th>Platform</th>
</tr>
</thead>
<tbody>
{#each services as item}
<tr>
<td>{item.icon}{item.location} {@html item.via}</td>
<td class={item.class}>{item.time}</td>
{#if !item.isCancelled}
<td class={item.class}>{item.status}</td>
<td>{item.platform}</td>
{:else}
<td colspan="2" class="delayed">{item.cancelReason}</td>
{/if}
</tr>
{/each}
</tbody>
</table>
</div>
{/if}

View File

@ -0,0 +1,65 @@
<script>
import {onMount} from 'svelte';
import { route } from './store';
export let fromStation;
export let toStation;
let url;
let data = { 'eta':'OFF', 'sta': 'OFF' };
let display = { title:'TRAIN', status:'delayed', output:'OFF'};
// $: url = `https://traintimes.silvrtree.co.uk/getnexttraintimes?from=${ fromStation }&to=${ toStation}`;
$: {
url = `http://localhost:8100/getnexttraintimes?from=${ fromStation }&to=${ toStation}`;
display.title = `${ fromStation.toUpperCase() }${ toStation.toUpperCase()}`;
}
// recalc stuff
$: {
display.output = (data.eta.toLowerCase() === 'on time') ? data.sta : data.eta;
display.status = (data.eta.toLowerCase() === 'on time') ? 'ontime' : 'delayed';
}
onMount(async () => {
await update();
});
async function update() {
await getTrain();
const now = new Date();
const mod = 120000 - (now.getTime() % 120000);
const trainUpdateFn = function () {
update();
};
setTimeout(trainUpdateFn.bind(this), mod + 10);
}
async function getTrain() {
const res = await fetch(url);
const json = await res.json();
if (json) {
console.log(json);
data = json;
}
}
function clickHandler(){
console.log('click', data);
route.set({fromStation, toStation});
}
</script>
<style>
</style>
<div on:click={clickHandler} class='mui-col-xs-12 mui-col-md-6'>{display.title}:&nbsp;<span class="{display.status}">{display.output}</span></div>

View File

@ -0,0 +1,178 @@
<script>
import {onMount} from 'svelte';
import {format} from 'fecha';
let weatherData;
onMount(async () => {
await update();
});
async function update() {
await getWeather();
const now = new Date();
const mod = 1800000 - (now.getTime() % 1800000);
const weatherUpdateFn = function () {
update();
};
setTimeout(weatherUpdateFn.bind(this), mod + 10);
}
function reduceOpenWeather(item) {
// Openweather returns timestamps in seconds. Moment requires them in milliseconds.
const ts = new Date(item.dt * 1000);
const weatherBlock = item.weather[0];
return {
'timestamp': item.dt,
'icon': `wi-owm-${weatherBlock.id}`,
'summary': weatherBlock.description,
'tempHigh': parseInt(item.temp.max, 10),
'tempLow': parseInt(item.temp.min, 10),
'tempMorn' : parseInt(item.temp.morn, 10),
'tempDay' : parseInt(item.temp.day, 10),
'tempEve' : parseInt(item.temp.eve, 10),
'tempNight' : parseInt(item.temp.night, 10),
'datelong': format(ts, 'isoDateTime'),
'time': item.dt,
'date': format(ts, 'D/M'),
'day': format(ts, 'ddd'),
'tempHighClass': `temp${parseInt(item.temp.max, 10)}`,
'tempLowClass': `temp${parseInt(item.temp.min, 10)}`
};
}
async function getWeather() {
const res = await fetch("http://localhost:9000/weather");
const json = await res.json();
if (json) {
weatherData = json.list.map((item) => {
// Reduce the data
return reduceOpenWeather(item);
});
}
}
</script>
<style>
.card {
position: relative;
background-color: #fff;
min-height: 72px;
}
.mui--text-display3 {
font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial;
}
.temp0, .temp1, .temp2, .temp3, .temp4, .temp5 {
color: rgb(80, 181, 221)
}
.temp6 {
color: rgb(78, 178, 206)
}
.temp7 {
color: rgb(76, 176, 190)
}
.temp8 {
color: rgb(73, 173, 175)
}
.temp9 {
color: rgb(72, 171, 159)
}
.temp10 {
color: rgb(70, 168, 142)
}
.temp11 {
color: rgb(68, 166, 125)
}
.temp12 {
color: rgb(66, 164, 108)
}
.temp13 {
color: rgb(102, 173, 94)
}
.temp14 {
color: rgb(135, 190, 64)
}
.temp15 {
color: rgb(179, 204, 26)
}
.temp16 {
color: rgb(214, 213, 28)
}
.temp17 {
color: rgb(249, 202, 3)
}
.temp18 {
color: rgb(246, 181, 3)
}
.temp19 {
color: rgb(244, 150, 26)
}
.temp20 {
color: rgb(236, 110, 5)
}
.day {
font-family: "Roboto Slab", "Helvetica Neue", Helvetica, Arial, SansSerif;
text-transform: uppercase;
}
.summary::first-letter {
text-transform: capitalize
}
</style>
<div id='weather'>
{#if weatherData}
{#each weatherData as item}
<div class="card mui--z1 mui-col-md-6 mui-col-lg-4">
<div class="mui-col-md-3">
<div class="mui--text-accent mui--text-title day mui--text-center">{item.day}</div>
<div class="mui--text-dark-secondary mui--text-subhead mui--text-center">{item.date}</div>
</div>
<div class="mui-col-md-7">
<div>
<i class="mui--text-headline wi {item.icon }"></i>
<span class="mui--text-display1 {item.tempHighClass}">{item.tempHigh}°</span> /
<span class="mui--text-headline {item.tempLowClass}">{item.tempLow}°</span>
</div>
<div class="mui--text-caption summary">{item.summary}</div>
</div>
<div class="mui-col-md-2">
<div class="mui--text-caption">{item.tempMorn}°</div>
<div class="mui--text-caption">{item.tempDay}°</div>
<div class="mui--text-caption">{item.tempEve}°</div>
<div class="mui--text-caption">{item.tempNight}°</div>
</div>
</div>
{/each}
{/if}
</div>

6
src/components/store.js Normal file
View File

@ -0,0 +1,6 @@
import { writable } from 'svelte/store';
const route = writable({ 'fromStation':'', 'toStation':'' });
export { route };

13
src/main.js Normal file
View File

@ -0,0 +1,13 @@
import App from './App.svelte';
const app = new App({
'target': document.body,
'props': {
'events' : [
{ 'event': new Date(2020, 0, 1), 'label': 'Contract Ends:' }
]
}
});
export default app;