V5 updates
40
Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
PROJECT = go-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} main.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
OLD_pb_public/browserconfig.xml
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
OLD_pb_public/build/bundle.css
Normal file
8
OLD_pb_public/build/bundle.js
Normal file
BIN
OLD_pb_public/build/fonts/GothamSSm-Black.otf
Executable file
BIN
OLD_pb_public/build/fonts/GothamSSm-Bold.otf
Executable file
BIN
OLD_pb_public/build/fonts/GothamSSm-Book.otf
Executable file
BIN
OLD_pb_public/build/fonts/GothamSSm-Light.otf
Executable file
BIN
OLD_pb_public/build/fonts/GothamSSm-Medium.otf
Executable file
BIN
OLD_pb_public/build/fonts/Roboto-normal-400.woff
Normal file
BIN
OLD_pb_public/build/fonts/Roboto_Condensed-normal-400.woff
Normal file
BIN
OLD_pb_public/build/fonts/Roboto_Mono-normal-400.woff
Normal file
BIN
OLD_pb_public/build/fonts/Roboto_Slab-normal-400.woff
Normal file
321
OLD_pb_public/build/fonts/fujicons.css
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
OLD_pb_public/build/fonts/fujicons.ttf
Executable file
BIN
OLD_pb_public/build/fonts/fujicons.woff
Normal file
39
OLD_pb_public/build/fonts/gotham.css
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;
|
||||
}
|
BIN
OLD_pb_public/favicon.png
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
OLD_pb_public/fonts/GothamSSm-Black.otf
Executable file
BIN
OLD_pb_public/fonts/GothamSSm-Bold.otf
Executable file
BIN
OLD_pb_public/fonts/GothamSSm-Book.otf
Executable file
BIN
OLD_pb_public/fonts/GothamSSm-Light.otf
Executable file
BIN
OLD_pb_public/fonts/GothamSSm-Medium.otf
Executable file
BIN
OLD_pb_public/fonts/Roboto-normal-400.woff
Normal file
BIN
OLD_pb_public/fonts/Roboto_Condensed-normal-400.woff
Normal file
BIN
OLD_pb_public/fonts/Roboto_Mono-normal-400.woff
Normal file
BIN
OLD_pb_public/fonts/Roboto_Slab-normal-400.woff
Normal file
32
OLD_pb_public/fonts/fonts.css
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
OLD_pb_public/fonts/fujicons.css
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
OLD_pb_public/fonts/fujicons.ttf
Executable file
39
OLD_pb_public/fonts/gotham.css
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
OLD_pb_public/global.css
Normal file
BIN
OLD_pb_public/img/Icon-144.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
OLD_pb_public/img/Icon-192.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
OLD_pb_public/img/Icon-36.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
OLD_pb_public/img/Icon-48.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
OLD_pb_public/img/Icon-512.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
OLD_pb_public/img/Icon-72.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
OLD_pb_public/img/Icon-96.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
OLD_pb_public/img/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
OLD_pb_public/img/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
OLD_pb_public/img/favicon-16x16.png
Normal file
After Width: | Height: | Size: 984 B |
BIN
OLD_pb_public/img/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
OLD_pb_public/img/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
OLD_pb_public/img/mstile-150x150.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
OLD_pb_public/img/photothumb.db
Normal file
33
OLD_pb_public/img/safari-pinned-tab.svg
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
OLD_pb_public/index.html
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
OLD_pb_public/manifest.json
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"
|
||||
}
|
9
OLD_pb_public/public/browserconfig.xml
Executable 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>
|
11
OLD_pb_public/public/build/bundle.css
Normal file
24
OLD_pb_public/public/build/bundle.css.map
Normal file
8
OLD_pb_public/public/build/bundle.js
Normal file
BIN
OLD_pb_public/public/favicon.png
Executable file
After Width: | Height: | Size: 49 KiB |
0
OLD_pb_public/public/global.css
Executable file
BIN
OLD_pb_public/public/img/Icon-144.png
Executable file
After Width: | Height: | Size: 6.7 KiB |
BIN
OLD_pb_public/public/img/Icon-192.png
Executable file
After Width: | Height: | Size: 10 KiB |
BIN
OLD_pb_public/public/img/Icon-36.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
OLD_pb_public/public/img/Icon-48.png
Executable file
After Width: | Height: | Size: 2.2 KiB |
BIN
OLD_pb_public/public/img/Icon-512.png
Executable file
After Width: | Height: | Size: 56 KiB |
BIN
OLD_pb_public/public/img/Icon-72.png
Executable file
After Width: | Height: | Size: 3.3 KiB |
BIN
OLD_pb_public/public/img/Icon-96.png
Executable file
After Width: | Height: | Size: 4.3 KiB |
BIN
OLD_pb_public/public/img/android-chrome-192x192.png
Executable file
After Width: | Height: | Size: 4.4 KiB |
BIN
OLD_pb_public/public/img/apple-touch-icon.png
Executable file
After Width: | Height: | Size: 7.6 KiB |
BIN
OLD_pb_public/public/img/favicon-16x16.png
Executable file
After Width: | Height: | Size: 984 B |
BIN
OLD_pb_public/public/img/favicon-32x32.png
Executable file
After Width: | Height: | Size: 1.7 KiB |
BIN
OLD_pb_public/public/img/favicon.ico
Executable file
After Width: | Height: | Size: 15 KiB |
BIN
OLD_pb_public/public/img/mstile-150x150.png
Executable file
After Width: | Height: | Size: 3.7 KiB |
BIN
OLD_pb_public/public/img/photothumb.db
Executable file
33
OLD_pb_public/public/img/safari-pinned-tab.svg
Executable 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
OLD_pb_public/public/index.html
Executable 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
OLD_pb_public/public/manifest.json
Executable 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
OLD_pb_public/public/service-worker.js
Executable 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.ttf',
|
||||
'/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);
|
||||
})
|
||||
);
|
||||
});
|
110
OLD_pb_public/service-worker.js
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);
|
||||
})
|
||||
);
|
||||
});
|
9
docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
||||
version: '3.5'
|
||||
|
||||
services:
|
||||
trainserver:
|
||||
container_name: trainserver
|
||||
image: git.caliban.io/martin/go-traintimes:5.0.0
|
||||
restart: always
|
||||
ports:
|
||||
- "8100:8100"
|
29
docker/Dockerfile
Normal file
@ -0,0 +1,29 @@
|
||||
FROM debian:12-slim
|
||||
# FROM alpine:latest
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN mkdir -p /app/dist
|
||||
|
||||
COPY ./go-traintimes /app/
|
||||
|
||||
|
||||
COPY ./pb_data /app/pb_data
|
||||
COPY ./pb_public /app/pb_public
|
||||
|
||||
RUN apt-get update && apt-get install -y ca-certificates
|
||||
|
||||
# Need the following to get a go app to run inside a docker container
|
||||
# as per: https://www.fairlyusefulcode.co.uk/post/go-alpine-linux/ -- DEAD!!!
|
||||
# RUN apk upgrade musl
|
||||
# RUN apk add gcompat
|
||||
|
||||
# RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
|
||||
# RUN ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2
|
||||
|
||||
RUN chmod +x /app/go-traintimes
|
||||
|
||||
EXPOSE 8100
|
||||
|
||||
CMD [ "/app/go-traintimes", "serve", "--http=0.0.0.0:8100", "--dev"]
|
||||
|
BIN
go-traintimes
Executable file
2
go.mod
@ -4,6 +4,7 @@ go 1.22.4
|
||||
|
||||
require (
|
||||
github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61
|
||||
github.com/pocketbase/dbx v1.10.1
|
||||
github.com/pocketbase/pocketbase v0.22.14
|
||||
)
|
||||
|
||||
@ -50,7 +51,6 @@ require (
|
||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/pocketbase/dbx v1.10.1 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
|
129
main.go
@ -32,11 +32,25 @@ type GetTrainsRec struct {
|
||||
Hash string `db:"hash" json:"hash"`
|
||||
}
|
||||
|
||||
type GetTrainTimesRec struct {
|
||||
Hash string `db:"hash" json:"hash"`
|
||||
Body string `db:"body" json:"body"`
|
||||
Ts int64 `db:"ts" json:"ts"`
|
||||
}
|
||||
|
||||
const host = "https://huxley2.azurewebsites.net"
|
||||
|
||||
var (
|
||||
Version string
|
||||
Build string
|
||||
tr = &http.Transport{
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
DisableCompression: true,
|
||||
}
|
||||
client = &http.Client{Transport: tr}
|
||||
gmtTimeLoc = time.FixedZone("GMT", 0)
|
||||
timeFormat = "Mon, 2 Jan 2006 15:04:05 GMT"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -58,7 +72,7 @@ func main() {
|
||||
|
||||
e.Router.GET("/getnexttraintimes", func(c echo.Context) error {
|
||||
apis.ActivityLogger(app)
|
||||
return GetNextTrainTimes(c)
|
||||
return GetNextTrainTimes(c, app)
|
||||
})
|
||||
|
||||
scheduler.MustAdd("cleanup", "*/10 * * * *", func() {
|
||||
@ -120,7 +134,7 @@ func getTrains(c echo.Context, app *pocketbase.PocketBase) error {
|
||||
|
||||
if dberr == nil {
|
||||
// handle error
|
||||
log.Printf("-- Cache hit %+v,%+v\n", recentTrain.From, recentTrain.To)
|
||||
log.Printf("-- Cache hit train %+v\n", recentTrain.Hash)
|
||||
return c.String(200, recentTrain.Body)
|
||||
}
|
||||
|
||||
@ -129,12 +143,12 @@ func getTrains(c echo.Context, app *pocketbase.PocketBase) error {
|
||||
|
||||
log.Printf("-- url: %+v\n", url)
|
||||
|
||||
tr := &http.Transport{
|
||||
/*tr := &http.Transport{
|
||||
MaxIdleConns: 10,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
DisableCompression: true,
|
||||
}
|
||||
client := &http.Client{Transport: tr}
|
||||
}*/
|
||||
// client := &http.Client{Transport: tr}
|
||||
|
||||
log.Printf("-- full url: %+v\n", host+url)
|
||||
resp, err := client.Get(host + url)
|
||||
@ -174,7 +188,7 @@ func getTrains(c echo.Context, app *pocketbase.PocketBase) error {
|
||||
return c.JSON(http.StatusAccepted, dummy)
|
||||
}
|
||||
|
||||
func GetNextTrainTimes(c echo.Context) error {
|
||||
func GetNextTrainTimes(c echo.Context, app *pocketbase.PocketBase) error {
|
||||
|
||||
params := c.QueryParams()
|
||||
|
||||
@ -185,6 +199,10 @@ func GetNextTrainTimes(c echo.Context) error {
|
||||
To := c.QueryParamDefault("to", "")
|
||||
|
||||
ts := time.Now().String()
|
||||
tsUnix := time.Now().Unix()
|
||||
now := time.Now()
|
||||
then := now.Add(-2 * time.Minute)
|
||||
|
||||
log.Printf("-- %+v\n", ts)
|
||||
|
||||
log.Printf("-- From: %+v\n", From)
|
||||
@ -192,6 +210,21 @@ func GetNextTrainTimes(c echo.Context) error {
|
||||
|
||||
dummy := DummyRecord{Ts: ts}
|
||||
|
||||
recentTraintimes := GetTrainTimesRec{}
|
||||
|
||||
hash := fmt.Sprintf("%s%s", From, To)
|
||||
|
||||
dberr := app.Dao().DB().NewQuery("SELECT * FROM traintimes WHERE hash = {:hash} and ts >= {:ts}").Bind(dbx.Params{
|
||||
"ts": tsUnix - 120,
|
||||
"hash": hash,
|
||||
}).One(&recentTraintimes)
|
||||
|
||||
if dberr == nil {
|
||||
// handle error
|
||||
log.Printf("-- Cache hit traintimes %+v\n", recentTraintimes.Hash)
|
||||
return c.String(200, recentTraintimes.Body)
|
||||
}
|
||||
|
||||
if From != "" && To != "" {
|
||||
log.Println("-- Got something to search for")
|
||||
|
||||
@ -200,19 +233,18 @@ func GetNextTrainTimes(c echo.Context) error {
|
||||
|
||||
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)
|
||||
|
||||
req, err := http.NewRequest("GET", host+url, nil)
|
||||
|
||||
if err != nil {
|
||||
// handle error
|
||||
}
|
||||
|
||||
req.Header.Add("If-Modified-Since", then.In(gmtTimeLoc).Format(timeFormat))
|
||||
|
||||
resp, err := client.Do(req)
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
|
||||
@ -241,6 +273,20 @@ func GetNextTrainTimes(c echo.Context) error {
|
||||
|
||||
}
|
||||
|
||||
var nTrainTimesRec GetTrainTimesRec
|
||||
|
||||
nTrainTimesRec.Hash = hash
|
||||
nTrainTimesRec.Ts = tsUnix
|
||||
nTrainTimesRec.Body = string(departJson)
|
||||
|
||||
go func() {
|
||||
err := saveTraintimesRec(app, nTrainTimesRec)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
|
||||
}
|
||||
}()
|
||||
|
||||
// log.Println("-- body: %+v\n", string(body))
|
||||
// c.Set(fiber.HeaderContentType, fiber.MIMEApplicationJSON)
|
||||
|
||||
@ -306,7 +352,7 @@ func saveTrainRec(app *pocketbase.PocketBase, trainRecord GetTrainsRec) error {
|
||||
}
|
||||
|
||||
if len(record) == 0 {
|
||||
log.Printf("-- Insert new\n")
|
||||
log.Printf("-- Insert new train\n")
|
||||
|
||||
record := models.NewRecord(collection)
|
||||
|
||||
@ -321,7 +367,7 @@ func saveTrainRec(app *pocketbase.PocketBase, trainRecord GetTrainsRec) error {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Printf("-- Update\n")
|
||||
log.Printf("-- Update train\n")
|
||||
rec := record[0]
|
||||
|
||||
rec.Set("body", trainRecord.Body)
|
||||
@ -371,6 +417,57 @@ func saveTrainRec(app *pocketbase.PocketBase, trainRecord GetTrainsRec) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func saveTraintimesRec(app *pocketbase.PocketBase, traintimesRecord GetTrainTimesRec) error {
|
||||
|
||||
log.Println("$$:saveTraintimesRec")
|
||||
|
||||
// foundTrain := GetTrainsRec{}
|
||||
|
||||
collection, err := app.Dao().FindCollectionByNameOrId("traintimes")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
record, recErr := app.Dao().FindRecordsByExpr("traintimes", dbx.NewExp("hash = {:hash}", dbx.Params{
|
||||
"hash": traintimesRecord.Hash,
|
||||
}))
|
||||
|
||||
if recErr != nil {
|
||||
log.Println(recErr)
|
||||
return recErr
|
||||
}
|
||||
|
||||
if len(record) == 0 {
|
||||
log.Printf("-- Insert new traintimes\n")
|
||||
|
||||
record := models.NewRecord(collection)
|
||||
|
||||
record.Set("body", traintimesRecord.Body)
|
||||
record.Set("ts", traintimesRecord.Ts)
|
||||
record.Set("hash", traintimesRecord.Hash)
|
||||
|
||||
if err := app.Dao().SaveRecord(record); err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.Printf("-- Update traintimes\n")
|
||||
rec := record[0]
|
||||
|
||||
rec.Set("body", traintimesRecord.Body)
|
||||
rec.Set("ts", traintimesRecord.Ts)
|
||||
|
||||
if err := app.Dao().SaveRecord(rec); err != nil {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func CleanupDB(app *pocketbase.PocketBase) {
|
||||
|
||||
ts := time.Now().Unix() - 600
|
||||
|
BIN
pb_data/data.db
BIN
pb_data/logs.db
0
pb_public/browserconfig.xml
Normal file → Executable file
26
pb_public/build/bundle.css.map
Normal file
BIN
pb_public/build/fonts/GothamNarrSSm-Bold.otf
Executable file
BIN
pb_public/build/fonts/GothamNarrSSm-Book.otf
Executable file
BIN
pb_public/build/fonts/GothamNarrSSm-Light.otf
Executable file
BIN
pb_public/build/fonts/GothamNarrSSm-Medium.otf
Executable file
BIN
pb_public/build/fonts/Roboto-normal-400.woff
Normal file → Executable file
BIN
pb_public/build/fonts/Roboto_Condensed-normal-400.woff
Normal file → Executable file
0
pb_public/build/fonts/Roboto_Mono-normal-400.woff
Normal file → Executable file
BIN
pb_public/build/fonts/Roboto_Slab-normal-400.woff
Normal file → Executable file
@ -2,7 +2,7 @@
|
||||
font-family: 'Fujicons';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url(fujicons.ttf) format('truetype');
|
||||
src: url(./fujicons.woff) format('woff');
|
||||
unicode-range: U+0-10FFFF;
|
||||
}
|
||||
|
||||
@ -180,10 +180,6 @@
|
||||
content: "";
|
||||
}
|
||||
|
||||
.fa-back-chevron:before {
|
||||
content: "\E91F"
|
||||
}
|
||||
|
||||
.fa-forward:before {
|
||||
content: "";
|
||||
}
|
||||
@ -212,6 +208,7 @@
|
||||
content: "\EA88"
|
||||
}
|
||||
|
||||
|
||||
.fa-menu:before {
|
||||
content: "\EA68"
|
||||
}
|
||||
@ -319,3 +316,8 @@
|
||||
content: "\E903"
|
||||
}
|
||||
|
||||
.fa-back-chevron:before {
|
||||
content: "\E91F"
|
||||
}
|
||||
|
||||
|
||||
|
7
pb_public/build/fonts/roboto-condensed.css
Normal file
@ -0,0 +1,7 @@
|
||||
@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;
|
||||
}
|
32
pb_public/build/fonts/roboto.css
Executable 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;
|
||||
}
|
||||
|