init
201
.gitignore
vendored
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
### GoLand+all template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Go template
|
||||||
|
# If you prefer the allow list template instead of the deny list, see community template:
|
||||||
|
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||||
|
#
|
||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Go workspace file
|
||||||
|
go.work
|
||||||
|
|
||||||
|
### GoLand+iml template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
### GoLand template
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
|
||||||
|
/menuserver
|
40
Makefile
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
PROJECT = traintimes
|
||||||
|
|
||||||
|
VERSION=`git describe --tags`
|
||||||
|
BUILD=`date +%FT%T%z`
|
||||||
|
|
||||||
|
|
||||||
|
ECR_REPO = git.caliban.io/martin
|
||||||
|
|
||||||
|
APP_IMAGE = $(ECR_REPO)/$(PROJECT):$(VERSION)
|
||||||
|
|
||||||
|
NO_CACHE = true
|
||||||
|
|
||||||
|
LDFLAGS=-ldflags "-w -s -X main.Version=${VERSION} -X main.Build=${BUILD}"
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
build:
|
||||||
|
#CC=/usr/local/musl/bin/musl-gcc go build --ldflags '-linkmode external -extldflags "-static"' server.go
|
||||||
|
# GCO_ENABLED=0 GOOS=linux go build ${LDFLAGS} -o ${PROJECT} server.go
|
||||||
|
go build ${LDFLAGS} -o ${PROJECT} server.go
|
||||||
|
|
||||||
|
# docker build ./docker/. -t $(APP_IMAGE) --build-arg VERSION=$(VERSION) --no-cache=$(NO_CACHE) --compress=true
|
||||||
|
docker build --platform linux/amd64 --no-cache -force-rm --tag ${APP_IMAGE} --file ./docker/Dockerfile .
|
||||||
|
|
||||||
|
|
||||||
|
#push docker image to registry
|
||||||
|
.PHONY: push
|
||||||
|
push: build
|
||||||
|
docker push $(APP_IMAGE)
|
||||||
|
|
||||||
|
|
||||||
|
#push docker image to registry
|
||||||
|
.PHONY: run
|
||||||
|
run: build
|
||||||
|
docker run $(APP_IMAGE)
|
||||||
|
|
||||||
|
ver:
|
||||||
|
@echo '$(VERSION)'
|
||||||
|
#echo $ERSION
|
||||||
|
.PHONY: ver
|
9
dist/browserconfig.xml
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<browserconfig>
|
||||||
|
<msapplication>
|
||||||
|
<tile>
|
||||||
|
<square150x150logo src="/img/mstile-150x150.png"/>
|
||||||
|
<TileColor>#2b5797</TileColor>
|
||||||
|
</tile>
|
||||||
|
</msapplication>
|
||||||
|
</browserconfig>
|
12
dist/build/bundle.css
vendored
Normal file
8
dist/build/bundle.js
vendored
Normal file
BIN
dist/build/fonts/GothamSSm-Black.otf
vendored
Executable file
BIN
dist/build/fonts/GothamSSm-Bold.otf
vendored
Executable file
BIN
dist/build/fonts/GothamSSm-Book.otf
vendored
Executable file
BIN
dist/build/fonts/GothamSSm-Light.otf
vendored
Executable file
BIN
dist/build/fonts/GothamSSm-Medium.otf
vendored
Executable file
BIN
dist/build/fonts/Roboto-normal-400.woff
vendored
Normal file
BIN
dist/build/fonts/Roboto_Condensed-normal-400.woff
vendored
Normal file
BIN
dist/build/fonts/Roboto_Mono-normal-400.woff
vendored
Normal file
BIN
dist/build/fonts/Roboto_Slab-normal-400.woff
vendored
Normal file
32
dist/build/fonts/fonts.css
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto Condensed';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto_Condensed-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto_Mono-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto Slab';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto_Slab-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
321
dist/build/fonts/fujicons.css
vendored
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Fujicons';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(fujicons.ttf) format('truetype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
display: inline-block;
|
||||||
|
font: normal normal normal 14px/1 Fujicons;
|
||||||
|
font-size: inherit;
|
||||||
|
text-rendering: auto;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
/* makes the font 33% larger relative to the icon container */
|
||||||
|
.fa-lg {
|
||||||
|
font-size: 1.33333333em;
|
||||||
|
line-height: 0.75em;
|
||||||
|
vertical-align: -15%;
|
||||||
|
}
|
||||||
|
.fa-2x {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.fa-3x {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
.fa-4x {
|
||||||
|
font-size: 4em;
|
||||||
|
}
|
||||||
|
.fa-5x {
|
||||||
|
font-size: 5em;
|
||||||
|
}
|
||||||
|
.fa-fw {
|
||||||
|
width: 1.28571429em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fa-ul {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-left: 2.14285714em;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
.fa-ul > li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.fa-li {
|
||||||
|
position: absolute;
|
||||||
|
left: -2.14285714em;
|
||||||
|
width: 2.14285714em;
|
||||||
|
top: 0.14285714em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fa-li.fa-lg {
|
||||||
|
left: -1.85714286em;
|
||||||
|
}
|
||||||
|
.fa-border {
|
||||||
|
padding: .2em .25em .15em;
|
||||||
|
border: solid 0.08em #eeeeee;
|
||||||
|
border-radius: .1em;
|
||||||
|
}
|
||||||
|
.fa-pull-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.fa-pull-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.fa.fa-pull-left {
|
||||||
|
margin-right: .3em;
|
||||||
|
}
|
||||||
|
.fa.fa-pull-right {
|
||||||
|
margin-left: .3em;
|
||||||
|
}
|
||||||
|
/* Deprecated as of 4.4.0 */
|
||||||
|
.pull-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.pull-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.fa.pull-left {
|
||||||
|
margin-right: .3em;
|
||||||
|
}
|
||||||
|
.fa.pull-right {
|
||||||
|
margin-left: .3em;
|
||||||
|
}
|
||||||
|
.fa-spin {
|
||||||
|
-webkit-animation: fa-spin 2s infinite linear;
|
||||||
|
animation: fa-spin 2s infinite linear;
|
||||||
|
}
|
||||||
|
.fa-pulse {
|
||||||
|
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||||
|
animation: fa-spin 1s infinite steps(8);
|
||||||
|
}
|
||||||
|
@-webkit-keyframes fa-spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes fa-spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fa-rotate-90 {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
-ms-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
.fa-rotate-180 {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
|
||||||
|
-webkit-transform: rotate(180deg);
|
||||||
|
-ms-transform: rotate(180deg);
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
.fa-rotate-270 {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
|
||||||
|
-webkit-transform: rotate(270deg);
|
||||||
|
-ms-transform: rotate(270deg);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
.fa-flip-horizontal {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
|
||||||
|
-webkit-transform: scale(-1, 1);
|
||||||
|
-ms-transform: scale(-1, 1);
|
||||||
|
transform: scale(-1, 1);
|
||||||
|
}
|
||||||
|
.fa-flip-vertical {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
|
||||||
|
-webkit-transform: scale(1, -1);
|
||||||
|
-ms-transform: scale(1, -1);
|
||||||
|
transform: scale(1, -1);
|
||||||
|
}
|
||||||
|
:root .fa-rotate-90,
|
||||||
|
:root .fa-rotate-180,
|
||||||
|
:root .fa-rotate-270,
|
||||||
|
:root .fa-flip-horizontal,
|
||||||
|
:root .fa-flip-vertical {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
.fa-stack {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
line-height: 2em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.fa-stack-1x,
|
||||||
|
.fa-stack-2x {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fa-stack-1x {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
.fa-stack-2x {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.fa-inverse {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.fa-back:before {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-back-chevron:before {
|
||||||
|
content: "\E91F"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-forward:before {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-globe:before {
|
||||||
|
content: "\EA12"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-up:before {
|
||||||
|
content: "\E925"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-down:before {
|
||||||
|
content: "\E922"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-work:before {
|
||||||
|
content: "\E998"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-home:before {
|
||||||
|
content: "\EA1E"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-refresh:before {
|
||||||
|
content: "\EA88"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-menu:before {
|
||||||
|
content: "\EA68"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-star:before {
|
||||||
|
content: "\EAB3"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-star-filled:before {
|
||||||
|
content: "\EAB2"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-thick-arrow:before {
|
||||||
|
content: "\EA08"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-tick:before {
|
||||||
|
content: "\E9A4"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-cross:before {
|
||||||
|
content: "\E951"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-cross-circle:before {
|
||||||
|
content: "\E9D2"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-cross-circle-filled:before {
|
||||||
|
content: "\E9D1"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-alert:before {
|
||||||
|
content: "\E9ED"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-alert-filled:before {
|
||||||
|
content: "\E9EC"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-info:before {
|
||||||
|
content: "\E9EF"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-info-filled:before {
|
||||||
|
content: "\E9EE"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-bookmark:before {
|
||||||
|
content: "\E951"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-bookmark-filled:before {
|
||||||
|
content: "\E950"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-clockface:before {
|
||||||
|
content: "\E9AB"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-clockface-filled:before {
|
||||||
|
content: "\E9AA"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-twitter:before {
|
||||||
|
content: "\EAE5"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-cog:before {
|
||||||
|
content: "\EA9E"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-cog-solid:before {
|
||||||
|
content: "\EA11"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-foursquare:before {
|
||||||
|
content: "\EA0B"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*full list*/
|
||||||
|
|
||||||
|
.fa-binoculars-solid:before {
|
||||||
|
content: "\E900"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-binoculars:before {
|
||||||
|
content: "\E901"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-check-circle-solid:before {
|
||||||
|
content: "\E902"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-check-circle:before {
|
||||||
|
content: "\E903"
|
||||||
|
}
|
||||||
|
|
BIN
dist/build/fonts/fujicons.ttf
vendored
Executable file
BIN
dist/build/fonts/fujicons.woff
vendored
Normal file
BIN
dist/build/fonts/fujicons.woff2
vendored
Normal file
39
dist/build/fonts/gotham.css
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Book.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Light';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Light.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Medium';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Medium.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Bold';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Bold.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Black';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Black.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
1
dist/build/tmp/build-errors.log
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
exit status 1exit status 1
|
BIN
dist/favicon.png
vendored
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
dist/fonts/GothamSSm-Black.otf
vendored
Executable file
BIN
dist/fonts/GothamSSm-Bold.otf
vendored
Executable file
BIN
dist/fonts/GothamSSm-Book.otf
vendored
Executable file
BIN
dist/fonts/GothamSSm-Light.otf
vendored
Executable file
BIN
dist/fonts/GothamSSm-Medium.otf
vendored
Executable file
BIN
dist/fonts/Roboto-normal-400.woff
vendored
Normal file
BIN
dist/fonts/Roboto_Condensed-normal-400.woff
vendored
Normal file
BIN
dist/fonts/Roboto_Mono-normal-400.woff
vendored
Normal file
BIN
dist/fonts/Roboto_Slab-normal-400.woff
vendored
Normal file
32
dist/fonts/fonts.css
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto Condensed';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto_Condensed-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto Mono';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto_Mono-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Roboto Slab';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(Roboto_Slab-normal-400.woff) format('woff');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
209
dist/fonts/fujicons.css
vendored
Normal file
@ -0,0 +1,209 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Fujicons';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(fujicons.ttf) format('truetype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.fa {
|
||||||
|
display: inline-block;
|
||||||
|
font: normal normal normal 14px/1 Fujicons;
|
||||||
|
font-size: inherit;
|
||||||
|
text-rendering: auto;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
/* makes the font 33% larger relative to the icon container */
|
||||||
|
.fa-lg {
|
||||||
|
font-size: 1.33333333em;
|
||||||
|
line-height: 0.75em;
|
||||||
|
vertical-align: -15%;
|
||||||
|
}
|
||||||
|
.fa-2x {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.fa-3x {
|
||||||
|
font-size: 3em;
|
||||||
|
}
|
||||||
|
.fa-4x {
|
||||||
|
font-size: 4em;
|
||||||
|
}
|
||||||
|
.fa-5x {
|
||||||
|
font-size: 5em;
|
||||||
|
}
|
||||||
|
.fa-fw {
|
||||||
|
width: 1.28571429em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fa-ul {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-left: 2.14285714em;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
.fa-ul > li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.fa-li {
|
||||||
|
position: absolute;
|
||||||
|
left: -2.14285714em;
|
||||||
|
width: 2.14285714em;
|
||||||
|
top: 0.14285714em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fa-li.fa-lg {
|
||||||
|
left: -1.85714286em;
|
||||||
|
}
|
||||||
|
.fa-border {
|
||||||
|
padding: .2em .25em .15em;
|
||||||
|
border: solid 0.08em #eeeeee;
|
||||||
|
border-radius: .1em;
|
||||||
|
}
|
||||||
|
.fa-pull-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.fa-pull-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.fa.fa-pull-left {
|
||||||
|
margin-right: .3em;
|
||||||
|
}
|
||||||
|
.fa.fa-pull-right {
|
||||||
|
margin-left: .3em;
|
||||||
|
}
|
||||||
|
/* Deprecated as of 4.4.0 */
|
||||||
|
.pull-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.pull-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.fa.pull-left {
|
||||||
|
margin-right: .3em;
|
||||||
|
}
|
||||||
|
.fa.pull-right {
|
||||||
|
margin-left: .3em;
|
||||||
|
}
|
||||||
|
.fa-spin {
|
||||||
|
-webkit-animation: fa-spin 2s infinite linear;
|
||||||
|
animation: fa-spin 2s infinite linear;
|
||||||
|
}
|
||||||
|
.fa-pulse {
|
||||||
|
-webkit-animation: fa-spin 1s infinite steps(8);
|
||||||
|
animation: fa-spin 1s infinite steps(8);
|
||||||
|
}
|
||||||
|
@-webkit-keyframes fa-spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes fa-spin {
|
||||||
|
0% {
|
||||||
|
-webkit-transform: rotate(0deg);
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
-webkit-transform: rotate(359deg);
|
||||||
|
transform: rotate(359deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fa-rotate-90 {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
|
||||||
|
-webkit-transform: rotate(90deg);
|
||||||
|
-ms-transform: rotate(90deg);
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
.fa-rotate-180 {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
|
||||||
|
-webkit-transform: rotate(180deg);
|
||||||
|
-ms-transform: rotate(180deg);
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
.fa-rotate-270 {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
|
||||||
|
-webkit-transform: rotate(270deg);
|
||||||
|
-ms-transform: rotate(270deg);
|
||||||
|
transform: rotate(270deg);
|
||||||
|
}
|
||||||
|
.fa-flip-horizontal {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
|
||||||
|
-webkit-transform: scale(-1, 1);
|
||||||
|
-ms-transform: scale(-1, 1);
|
||||||
|
transform: scale(-1, 1);
|
||||||
|
}
|
||||||
|
.fa-flip-vertical {
|
||||||
|
-ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
|
||||||
|
-webkit-transform: scale(1, -1);
|
||||||
|
-ms-transform: scale(1, -1);
|
||||||
|
transform: scale(1, -1);
|
||||||
|
}
|
||||||
|
:root .fa-rotate-90,
|
||||||
|
:root .fa-rotate-180,
|
||||||
|
:root .fa-rotate-270,
|
||||||
|
:root .fa-flip-horizontal,
|
||||||
|
:root .fa-flip-vertical {
|
||||||
|
filter: none;
|
||||||
|
}
|
||||||
|
.fa-stack {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 2em;
|
||||||
|
height: 2em;
|
||||||
|
line-height: 2em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.fa-stack-1x,
|
||||||
|
.fa-stack-2x {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.fa-stack-1x {
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
.fa-stack-2x {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
.fa-inverse {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.fa-back:before {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-forward:before {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-globe:before {
|
||||||
|
content: "\EA12"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-up:before {
|
||||||
|
content: "\E925"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-down:before {
|
||||||
|
content: "\E922"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-work:before {
|
||||||
|
content: "\E998"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-home:before {
|
||||||
|
content: "\EA1E"
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-refresh:before {
|
||||||
|
content: "\EA88"
|
||||||
|
}
|
BIN
dist/fonts/fujicons.ttf
vendored
Executable file
39
dist/fonts/gotham.css
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Book.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Light';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Light.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Medium';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Medium.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Bold';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Bold.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Gotham Black';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url(GothamSSm-Black.otf) format('opentype');
|
||||||
|
unicode-range: U+0-10FFFF;
|
||||||
|
}
|
0
dist/global.css
vendored
Normal file
BIN
dist/img/Icon-144.png
vendored
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
dist/img/Icon-192.png
vendored
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
dist/img/Icon-36.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
dist/img/Icon-48.png
vendored
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
dist/img/Icon-512.png
vendored
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
dist/img/Icon-72.png
vendored
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
dist/img/Icon-96.png
vendored
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
dist/img/android-chrome-192x192.png
vendored
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
dist/img/apple-touch-icon.png
vendored
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
dist/img/favicon-16x16.png
vendored
Normal file
After Width: | Height: | Size: 984 B |
BIN
dist/img/favicon-32x32.png
vendored
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
dist/img/favicon.ico
vendored
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
dist/img/mstile-150x150.png
vendored
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
dist/img/photothumb.db
vendored
Normal file
33
dist/img/safari-pinned-tab.svg
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?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="192.000000pt" height="192.000000pt" viewBox="0 0 192.000000 192.000000"
|
||||||
|
preserveAspectRatio="xMidYMid meet">
|
||||||
|
<metadata>
|
||||||
|
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||||
|
</metadata>
|
||||||
|
<g transform="translate(0.000000,192.000000) scale(0.100000,-0.100000)"
|
||||||
|
fill="#000000" stroke="none">
|
||||||
|
<path d="M440 1789 c-80 -4 -104 -10 -149 -35 -63 -34 -117 -94 -145 -162 -19
|
||||||
|
-45 -20 -74 -20 -637 l0 -590 25 -56 c32 -67 91 -128 156 -160 l48 -23 605 -1
|
||||||
|
605 0 53 28 c69 35 118 86 151 156 l26 56 0 585 c-1 534 -2 590 -18 637 -33
|
||||||
|
94 -133 180 -231 199 -47 8 -969 11 -1106 3z m389 -79 c21 0 51 -44 51 -74 l0
|
||||||
|
-34 80 -1 c79 -1 80 -1 80 23 0 40 21 74 51 85 57 20 112 -21 112 -83 0 -17 5
|
||||||
|
-26 16 -26 68 0 143 -50 172 -115 17 -37 19 -74 19 -455 0 -265 -4 -429 -11
|
||||||
|
-454 -6 -23 -28 -55 -55 -81 l-44 -43 85 -89 c91 -94 101 -118 63 -153 -41
|
||||||
|
-38 -61 -28 -194 105 l-125 125 -168 0 -167 0 -128 -125 c-136 -134 -157 -145
|
||||||
|
-196 -103 -35 38 -26 60 65 155 l85 88 -35 30 c-19 16 -44 48 -55 70 -18 38
|
||||||
|
-19 65 -19 468 -1 404 1 431 19 467 32 63 105 110 171 110 11 0 16 8 14 23 -3
|
||||||
|
48 53 104 93 91 8 -2 17 -4 21 -4z"/>
|
||||||
|
<path d="M819 1532 c-48 -15 -65 -75 -31 -106 16 -14 43 -16 172 -17 169 0
|
||||||
|
190 7 190 62 0 25 -21 57 -38 60 -22 4 -282 4 -293 1z"/>
|
||||||
|
<path d="M735 1342 c-93 -5 -94 -6 -94 -192 0 -143 2 -160 19 -175 18 -16 48
|
||||||
|
-18 301 -18 l282 -1 18 23 c17 20 19 42 19 176 0 133 -2 154 -18 168 -15 14
|
||||||
|
-52 17 -242 19 -124 2 -252 2 -285 0z"/>
|
||||||
|
<path d="M685 741 c-35 -22 -50 -67 -35 -107 12 -32 55 -57 93 -56 44 1 88 50
|
||||||
|
81 89 -9 52 -15 63 -43 78 -34 17 -63 16 -96 -4z"/>
|
||||||
|
<path d="M1138 745 c-49 -27 -58 -97 -18 -137 55 -54 139 -31 154 43 7 38 -9
|
||||||
|
71 -44 92 -34 21 -56 21 -92 2z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
30
dist/index.html
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset='utf-8'>
|
||||||
|
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||||
|
|
||||||
|
<title>Traintimes</title>
|
||||||
|
|
||||||
|
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||||
|
|
||||||
|
<link rel="apple-touch-icon" sizes="180x180" href="/img/apple-touch-icon.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon-32x32.png">
|
||||||
|
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon-16x16.png">
|
||||||
|
<link rel="manifest" href="/manifest.json">
|
||||||
|
<link rel="mask-icon" href="/img/safari-pinned-tab.svg" color="#5bbad5">
|
||||||
|
<meta name="apple-mobile-web-app-title" content="Train Times">
|
||||||
|
<meta name="application-name" content="Train Times">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
|
||||||
|
<!--<link rel='stylesheet' href='/global.c
|
||||||
|
ss'>-->
|
||||||
|
<link rel='stylesheet' href='/build/bundle.css'>
|
||||||
|
|
||||||
|
<script defer src='/build/bundle.js'></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
46
dist/manifest.json
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "Train Times",
|
||||||
|
"short_name": "Train Times",
|
||||||
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-36.png",
|
||||||
|
"sizes": "36x36",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-48.png",
|
||||||
|
"sizes": "48x48",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/img/Icon-512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"theme_color": "#ffffff",
|
||||||
|
"background_color": "#ffffff",
|
||||||
|
"start_url": ".",
|
||||||
|
"imgdisplay": "standalone",
|
||||||
|
"display": "standalone"
|
||||||
|
}
|
110
dist/service-worker.js
vendored
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2016 Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
const CACHE_VERSION = 8;
|
||||||
|
const dataCacheName = `traintimesData-v${CACHE_VERSION}`;
|
||||||
|
const cacheName = `traintimePWA-final-${CACHE_VERSION}`;
|
||||||
|
const filesToCache = [
|
||||||
|
'/',
|
||||||
|
'/index.html',
|
||||||
|
'/service-worker.js',
|
||||||
|
'/manifest.json',
|
||||||
|
'/favicon.png',
|
||||||
|
'/browserconfig.xml',
|
||||||
|
'/build/bundle.css',
|
||||||
|
'/build/bundle.js',
|
||||||
|
'/build/fonts/fujicons.css',
|
||||||
|
'/build/fonts/fujicons.woff',
|
||||||
|
'/img/Icon-36.png',
|
||||||
|
'/img/Icon-48.png',
|
||||||
|
'/img/Icon-72.png',
|
||||||
|
'/img/Icon-96.png',
|
||||||
|
'/img/Icon-144.png',
|
||||||
|
'/img/Icon-192.png',
|
||||||
|
'/img/Icon-512.png'
|
||||||
|
];
|
||||||
|
|
||||||
|
self.addEventListener('install', function(e) {
|
||||||
|
console.log('[ServiceWorker] Install');
|
||||||
|
e.waitUntil(
|
||||||
|
caches.open(cacheName).then(function(cache) {
|
||||||
|
console.log('[ServiceWorker] Caching app shell');
|
||||||
|
|
||||||
|
return cache.addAll(filesToCache);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', function(e) {
|
||||||
|
console.log('[ServiceWorker] Activate');
|
||||||
|
e.waitUntil(
|
||||||
|
caches.keys().then(function(keyList) {
|
||||||
|
return Promise.all(keyList.map(function(key) {
|
||||||
|
if (key !== cacheName && key !== dataCacheName) {
|
||||||
|
console.log('[ServiceWorker] Removing old cache', key);
|
||||||
|
|
||||||
|
return caches.delete(key);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixes a corner case in which the app wasn't returning the latest data.
|
||||||
|
* You can reproduce the corner case by commenting out the line below and
|
||||||
|
* then doing the following steps: 1) load app for first time so that the
|
||||||
|
* initial New York City data is shown 2) press the refresh button on the
|
||||||
|
* app 3) go offline 4) reload the app. You expect to see the newer NYC
|
||||||
|
* data, but you actually see the initial data. This happens because the
|
||||||
|
* service worker is not yet activated. The code below essentially lets
|
||||||
|
* you activate the service worker faster.
|
||||||
|
*/
|
||||||
|
return self.clients.claim();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('fetch', function(e) {
|
||||||
|
console.warn('[Service Worker] Fetch', e.request.url);
|
||||||
|
const dataUrl = '/getnexttraintimes?';
|
||||||
|
if (e.request.url.indexOf(dataUrl) > -1) {
|
||||||
|
console.log('!');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the request URL contains dataUrl, the app is asking for fresh
|
||||||
|
* weather data. In this case, the service worker always goes to the
|
||||||
|
* network and then caches the response. This is called the "Cache then
|
||||||
|
* network" strategy:
|
||||||
|
* https://jakearchibald.com/2014/offline-cookbook/#cache-then-network
|
||||||
|
*/
|
||||||
|
e.respondWith(
|
||||||
|
caches.open(dataCacheName).then(function(cache) {
|
||||||
|
return fetch(e.request).then(function(response) {
|
||||||
|
cache.put(e.request.url, response.clone());
|
||||||
|
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The app is asking for app shell files. In this scenario the app uses the
|
||||||
|
* "Cache, falling back to the network" offline strategy:
|
||||||
|
* https://jakearchibald.com/2014/offline-cookbook/#cache-falling-back-to-network
|
||||||
|
*/
|
||||||
|
e.respondWith(
|
||||||
|
caches.match(e.request).then(function(response) {
|
||||||
|
return response || fetch(e.request);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
18
docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: '3.5'
|
||||||
|
|
||||||
|
services:
|
||||||
|
menuserver:
|
||||||
|
container_name: menuserver
|
||||||
|
image: git.caliban.io/martin/menuserver:3.0.0
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- ./db:/app/db
|
||||||
|
environment:
|
||||||
|
- EMAIL_FROM=Aida <aida@caliban.io>
|
||||||
|
- EMAIL_LOGIN=aida@caliban.io
|
||||||
|
- EMAIL_RECIPIENTS=Martin <martin@caliban.io>,Jessica <ing.arvid@gmail.com>
|
||||||
|
- EMAIL_HOSTNAME=mail.caliban.io
|
||||||
|
- EMAIL_PASSWORD=Ultra+Topaz+6XQ
|
||||||
|
- SITE_URL=http://menu.lan
|
26
go.mod
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module traintimes
|
||||||
|
|
||||||
|
go 1.22.0
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gofiber/fiber v1.14.6
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.2
|
||||||
|
github.com/gofiber/template/html/v2 v2.1.1
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
|
github.com/gofiber/template v1.8.3 // indirect
|
||||||
|
github.com/gofiber/utils v1.1.0 // indirect
|
||||||
|
github.com/google/uuid v1.5.0 // indirect
|
||||||
|
github.com/gorilla/schema v1.2.1 // indirect
|
||||||
|
github.com/klauspost/compress v1.17.7 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
|
github.com/valyala/fasthttp v1.52.0 // indirect
|
||||||
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
|
)
|
61
go.sum
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/gofiber/fiber v1.14.6 h1:QRUPvPmr8ijQuGo1MgupHBn8E+wW0IKqiOvIZPtV70o=
|
||||||
|
github.com/gofiber/fiber v1.14.6/go.mod h1:Yw2ekF1YDPreO9V6TMYjynu94xRxZBdaa8X5HhHsjCM=
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.2 h1:b0rYH6b06Df+4NyrbdptQL8ifuxw/Tf2DgfkZkDaxEo=
|
||||||
|
github.com/gofiber/fiber/v2 v2.52.2/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||||
|
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
|
||||||
|
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
||||||
|
github.com/gofiber/template/html/v2 v2.1.1 h1:QEy3O3EBkvwDthy5bXVGUseOyO6ldJoiDxlF4+MJiV8=
|
||||||
|
github.com/gofiber/template/html/v2 v2.1.1/go.mod h1:2G0GHHOUx70C1LDncoBpe4T6maQbNa4x1CVNFW0wju0=
|
||||||
|
github.com/gofiber/utils v0.0.10/go.mod h1:9J5aHFUIjq0XfknT4+hdSMG6/jzfaAgCu4HEbWDeBlo=
|
||||||
|
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||||
|
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||||
|
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||||
|
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||||
|
github.com/gorilla/schema v1.2.1 h1:tjDxcmdb+siIqkTNoV+qRH2mjYdr2hHe5MKXbp61ziM=
|
||||||
|
github.com/gorilla/schema v1.2.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
|
||||||
|
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
|
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||||
|
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
|
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
|
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
|
||||||
|
github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0=
|
||||||
|
github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ=
|
||||||
|
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||||
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
141
server-structs.go
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type AllServices struct {
|
||||||
|
AreServicesAvailable bool `json:"areServicesAvailable"`
|
||||||
|
BusServices interface{} `json:"busServices"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
FerryServices interface{} `json:"ferryServices"`
|
||||||
|
Filtercrs string `json:"filtercrs"`
|
||||||
|
FilterLocationName string `json:"filterLocationName"`
|
||||||
|
FilterType int `json:"filterType"`
|
||||||
|
GeneratedAt time.Time `json:"generatedAt"`
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
NrccMessages []struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
} `json:"nrccMessages"`
|
||||||
|
PlatformAvailable bool `json:"platformAvailable"`
|
||||||
|
TrainServices []struct {
|
||||||
|
AdhocAlerts interface{} `json:"adhocAlerts"`
|
||||||
|
CancelReason string `json:"cancelReason"`
|
||||||
|
CurrentDestinations interface{} `json:"currentDestinations"`
|
||||||
|
CurrentOrigins interface{} `json:"currentOrigins"`
|
||||||
|
DelayReason interface{} `json:"delayReason"`
|
||||||
|
Destination []struct {
|
||||||
|
AssocIsCancelled bool `json:"assocIsCancelled"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
FutureChangeTo interface{} `json:"futureChangeTo"`
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
Via interface{} `json:"via"`
|
||||||
|
} `json:"destination"`
|
||||||
|
DetachFront bool `json:"detachFront"`
|
||||||
|
Eta interface{} `json:"eta"`
|
||||||
|
Etd string `json:"etd"`
|
||||||
|
FilterLocationCancelled bool `json:"filterLocationCancelled"`
|
||||||
|
Formation interface{} `json:"formation"`
|
||||||
|
IsCancelled bool `json:"isCancelled"`
|
||||||
|
IsCircularRoute bool `json:"isCircularRoute"`
|
||||||
|
IsReverseFormation bool `json:"isReverseFormation"`
|
||||||
|
Length int `json:"length"`
|
||||||
|
Operator string `json:"operator"`
|
||||||
|
OperatorCode string `json:"operatorCode"`
|
||||||
|
Origin []struct {
|
||||||
|
AssocIsCancelled bool `json:"assocIsCancelled"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
FutureChangeTo interface{} `json:"futureChangeTo"`
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
Via interface{} `json:"via"`
|
||||||
|
} `json:"origin"`
|
||||||
|
Platform interface{} `json:"platform"`
|
||||||
|
PreviousCallingPoints interface{} `json:"previousCallingPoints"`
|
||||||
|
Rsid interface{} `json:"rsid"`
|
||||||
|
ServiceID string `json:"serviceID"`
|
||||||
|
ServiceIDGUID string `json:"serviceIdGuid"`
|
||||||
|
ServiceIDPercentEncoded string `json:"serviceIdPercentEncoded"`
|
||||||
|
ServiceIDURLSafe string `json:"serviceIdUrlSafe"`
|
||||||
|
ServiceType int `json:"serviceType"`
|
||||||
|
Sta string `json:"sta"`
|
||||||
|
Std string `json:"std"`
|
||||||
|
SubsequentCallingPoints []struct {
|
||||||
|
AssocIsCancelled bool `json:"assocIsCancelled"`
|
||||||
|
CallingPoint []struct {
|
||||||
|
AdhocAlerts interface{} `json:"adhocAlerts"`
|
||||||
|
At interface{} `json:"at"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
DetachFront bool `json:"detachFront"`
|
||||||
|
Et string `json:"et"`
|
||||||
|
Formation interface{} `json:"formation"`
|
||||||
|
IsCancelled bool `json:"isCancelled"`
|
||||||
|
Length int `json:"length"`
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
St string `json:"st"`
|
||||||
|
} `json:"callingPoint"`
|
||||||
|
ServiceChangeRequired bool `json:"serviceChangeRequired"`
|
||||||
|
ServiceType int `json:"serviceType"`
|
||||||
|
} `json:"subsequentCallingPoints"`
|
||||||
|
} `json:"trainServices"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AllDepartures struct {
|
||||||
|
Departures []struct {
|
||||||
|
Service struct {
|
||||||
|
Formation interface{} `json:"formation"`
|
||||||
|
Origin []struct {
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
Via interface{} `json:"via"`
|
||||||
|
FutureChangeTo interface{} `json:"futureChangeTo"`
|
||||||
|
AssocIsCancelled bool `json:"assocIsCancelled"`
|
||||||
|
} `json:"origin"`
|
||||||
|
Destination []struct {
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
Via interface{} `json:"via"`
|
||||||
|
FutureChangeTo interface{} `json:"futureChangeTo"`
|
||||||
|
AssocIsCancelled bool `json:"assocIsCancelled"`
|
||||||
|
} `json:"destination"`
|
||||||
|
CurrentOrigins interface{} `json:"currentOrigins"`
|
||||||
|
CurrentDestinations interface{} `json:"currentDestinations"`
|
||||||
|
Rsid interface{} `json:"rsid"`
|
||||||
|
ServiceIDPercentEncoded string `json:"serviceIdPercentEncoded"`
|
||||||
|
ServiceIDGUID string `json:"serviceIdGuid"`
|
||||||
|
ServiceIDURLSafe string `json:"serviceIdUrlSafe"`
|
||||||
|
Sta string `json:"sta"`
|
||||||
|
Eta string `json:"eta"`
|
||||||
|
Std string `json:"std"`
|
||||||
|
Etd string `json:"etd"`
|
||||||
|
Platform string `json:"platform"`
|
||||||
|
Operator string `json:"operator"`
|
||||||
|
OperatorCode string `json:"operatorCode"`
|
||||||
|
IsCircularRoute bool `json:"isCircularRoute"`
|
||||||
|
IsCancelled bool `json:"isCancelled"`
|
||||||
|
FilterLocationCancelled bool `json:"filterLocationCancelled"`
|
||||||
|
ServiceType int `json:"serviceType"`
|
||||||
|
Length int `json:"length"`
|
||||||
|
DetachFront bool `json:"detachFront"`
|
||||||
|
IsReverseFormation bool `json:"isReverseFormation"`
|
||||||
|
CancelReason interface{} `json:"cancelReason"`
|
||||||
|
DelayReason interface{} `json:"delayReason"`
|
||||||
|
ServiceID string `json:"serviceID"`
|
||||||
|
AdhocAlerts interface{} `json:"adhocAlerts"`
|
||||||
|
} `json:"service"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
} `json:"departures"`
|
||||||
|
GeneratedAt time.Time `json:"generatedAt"`
|
||||||
|
LocationName string `json:"locationName"`
|
||||||
|
Crs string `json:"crs"`
|
||||||
|
FilterLocationName interface{} `json:"filterLocationName"`
|
||||||
|
Filtercrs interface{} `json:"filtercrs"`
|
||||||
|
FilterType int `json:"filterType"`
|
||||||
|
NrccMessages []struct {
|
||||||
|
Value string `json:"value"`
|
||||||
|
} `json:"nrccMessages"`
|
||||||
|
PlatformAvailable bool `json:"platformAvailable"`
|
||||||
|
AreServicesAvailable bool `json:"areServicesAvailable"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NextTrain struct {
|
||||||
|
Sta string `json:"sta"`
|
||||||
|
Eta string `json:"eta"`
|
||||||
|
}
|
245
server.go
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"github.com/gofiber/template/html/v2"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DummyRecord struct {
|
||||||
|
Ts string `json:"ts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
const host = "https://huxley2.azurewebsites.net"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
log.Println("Traintimeserver")
|
||||||
|
|
||||||
|
engine := html.New("./dist", ".html")
|
||||||
|
|
||||||
|
app := fiber.New(fiber.Config{
|
||||||
|
Views: engine,
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/", indexHandler)
|
||||||
|
|
||||||
|
port := os.Getenv("PORT")
|
||||||
|
if port == "" {
|
||||||
|
port = "8100"
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Static("/", "./dist")
|
||||||
|
|
||||||
|
app.Get("/gettrains", func(c *fiber.Ctx) error {
|
||||||
|
return getTrains(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/getnexttraintimes", func(c *fiber.Ctx) error {
|
||||||
|
return GetNextTrainTimes(c)
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/getroute", func(c *fiber.Ctx) error {
|
||||||
|
return NotImplemented(c, "getroute")
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/getnews", func(c *fiber.Ctx) error {
|
||||||
|
return NotImplemented(c, "getnews")
|
||||||
|
})
|
||||||
|
|
||||||
|
app.Get("/getservice", func(c *fiber.Ctx) error {
|
||||||
|
return NotImplemented(c, "getservice")
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Fatalln(app.Listen(fmt.Sprintf(":%v", port)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func indexHandler(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
return c.Render("index", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NotImplemented(c *fiber.Ctx, from string) error {
|
||||||
|
|
||||||
|
params := c.Queries()
|
||||||
|
|
||||||
|
fmt.Printf("NotImplemented from: %s\n", from)
|
||||||
|
fmt.Printf("-- %+v\n", params)
|
||||||
|
|
||||||
|
return c.SendString("{}")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTrains(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
params := c.Queries()
|
||||||
|
|
||||||
|
log.Println("$$:getTrains")
|
||||||
|
log.Printf("-- %+v\n", params)
|
||||||
|
|
||||||
|
From := c.Query("from", "")
|
||||||
|
To := c.Query("to", "")
|
||||||
|
|
||||||
|
ts := time.Now().String()
|
||||||
|
log.Printf("-- %+v\n", ts)
|
||||||
|
|
||||||
|
log.Printf("-- From: %+v\n", From)
|
||||||
|
log.Printf("-- To: %+v\n", To)
|
||||||
|
|
||||||
|
dummy := DummyRecord{Ts: ts}
|
||||||
|
|
||||||
|
jsonStr, _ := json.Marshal(dummy)
|
||||||
|
|
||||||
|
// const url = `/all/${ request.query['from'] }/to/${ request.query['to'] }/10?accessToken=215b99fe-b237-4a01-aadc-cf315d6756d8`;
|
||||||
|
|
||||||
|
if From != "" && To != "" {
|
||||||
|
log.Println("-- Got something to search for")
|
||||||
|
|
||||||
|
// `/all/${ req.query.from }/to/${ req.query.to }/10?accessToken=215b99fe-b237-4a01-aadc-cf315d6756d8`;
|
||||||
|
url := "/all/" + From + "/to/" + To + "/10?accessToken=215b99fe-b237-4a01-aadc-cf315d6756d8"
|
||||||
|
|
||||||
|
log.Printf("-- url: %+v\n", url)
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
MaxIdleConns: 10,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
DisableCompression: true,
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
|
||||||
|
log.Printf("-- full url: %+v\n", host+url)
|
||||||
|
resp, err := client.Get(host + url)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Printf("-- body: %+v\n", string(body))
|
||||||
|
|
||||||
|
return c.SendString(string(body))
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendString(string(jsonStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNextTrainTimes(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
params := c.Queries()
|
||||||
|
|
||||||
|
log.Println("$$:GetNextTrainTimes")
|
||||||
|
log.Printf("-- %+v\n", params)
|
||||||
|
|
||||||
|
From := c.Query("from", "")
|
||||||
|
To := c.Query("to", "")
|
||||||
|
|
||||||
|
ts := time.Now().String()
|
||||||
|
log.Printf("-- %+v\n", ts)
|
||||||
|
|
||||||
|
log.Printf("-- From: %+v\n", From)
|
||||||
|
log.Printf("-- To: %+v\n", To)
|
||||||
|
|
||||||
|
dummy := DummyRecord{Ts: ts}
|
||||||
|
|
||||||
|
jsonStr, _ := json.Marshal(dummy)
|
||||||
|
|
||||||
|
if From != "" && To != "" {
|
||||||
|
log.Println("-- Got something to search for")
|
||||||
|
|
||||||
|
// `/all/${ req.query.from }/to/${ req.query.to }/10?accessToken=215b99fe-b237-4a01-aadc-cf315d6756d8`;
|
||||||
|
url := "/next/" + From + "/to/" + To + "?accessToken=215b99fe-b237-4a01-aadc-cf315d6756d8"
|
||||||
|
|
||||||
|
log.Printf("-- url: %+v\n", url)
|
||||||
|
|
||||||
|
tr := &http.Transport{
|
||||||
|
MaxIdleConns: 10,
|
||||||
|
IdleConnTimeout: 30 * time.Second,
|
||||||
|
DisableCompression: true,
|
||||||
|
}
|
||||||
|
client := &http.Client{Transport: tr}
|
||||||
|
|
||||||
|
log.Printf("-- full url: %+v\n", host+url)
|
||||||
|
resp, err := client.Get(host + url)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// handle error
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
body, err := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var services AllDepartures
|
||||||
|
unerr := json.Unmarshal(body, &services)
|
||||||
|
|
||||||
|
if unerr != nil {
|
||||||
|
|
||||||
|
log.Println("Failed to Unmarshal json")
|
||||||
|
panic(unerr)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
departure := reduceNextTrainTimes(services)
|
||||||
|
|
||||||
|
departJson, derr := json.Marshal(departure)
|
||||||
|
|
||||||
|
if derr != nil {
|
||||||
|
|
||||||
|
log.Println("Failed to marshal json")
|
||||||
|
panic(derr)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Println("-- body: %+v\n", string(body))
|
||||||
|
c.Set(fiber.HeaderContentType, fiber.MIMEApplicationJSON)
|
||||||
|
|
||||||
|
return c.SendString(string(departJson))
|
||||||
|
// return c.Send(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.SendString(string(jsonStr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func reduceNextTrainTimes(departData AllDepartures) NextTrain {
|
||||||
|
|
||||||
|
// log.Printf("-- obj?: %+v\n", departData)
|
||||||
|
|
||||||
|
depart := departData.Departures[0].Service
|
||||||
|
// log.Printf("-- depart: %+v\n", depart)
|
||||||
|
var output NextTrain
|
||||||
|
|
||||||
|
if depart.Origin != nil {
|
||||||
|
if depart.Sta != "" {
|
||||||
|
output.Sta = depart.Sta
|
||||||
|
} else {
|
||||||
|
output.Sta = depart.Std
|
||||||
|
}
|
||||||
|
|
||||||
|
if depart.Eta != "" {
|
||||||
|
output.Eta = depart.Eta
|
||||||
|
} else {
|
||||||
|
output.Eta = depart.Etd
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
output.Eta = "No Service"
|
||||||
|
output.Sta = "No Service"
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.Printf("-- output: %+v\n", depart)
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
1
tmp/build-errors.log
Normal file
@ -0,0 +1 @@
|
|||||||
|
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1
|