Add time machine submissions page
This commit is contained in:
parent
dd6e5e3b66
commit
8be575875d
|
@ -415,6 +415,31 @@ func TestJamRecap2023_Visibility(t *testing.T) {
|
||||||
AssertSubdomain(t, BuildJamRecap2023_Visibility(), "")
|
AssertSubdomain(t, BuildJamRecap2023_Visibility(), "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimeMachine(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildTimeMachine(), RegexTimeMachine, nil)
|
||||||
|
AssertSubdomain(t, BuildTimeMachine(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeMachineSubmissions(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildTimeMachineSubmissions(), RegexTimeMachineSubmissions, nil)
|
||||||
|
AssertSubdomain(t, BuildTimeMachineSubmissions(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeMachineForm(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildTimeMachineForm(), RegexTimeMachineForm, nil)
|
||||||
|
AssertSubdomain(t, BuildTimeMachineForm(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTimeMachineFormDone(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildTimeMachineFormDone(), RegexTimeMachineFormDone, nil)
|
||||||
|
AssertSubdomain(t, BuildTimeMachineFormDone(), "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewsletterSignup(t *testing.T) {
|
||||||
|
AssertRegexMatch(t, BuildNewsletterSignup(), RegexNewsletterSignup, nil)
|
||||||
|
AssertSubdomain(t, BuildNewsletterSignup(), "")
|
||||||
|
}
|
||||||
|
|
||||||
func TestProjectNewJam(t *testing.T) {
|
func TestProjectNewJam(t *testing.T) {
|
||||||
AssertRegexMatch(t, BuildProjectNewJam(), RegexProjectNew, nil)
|
AssertRegexMatch(t, BuildProjectNewJam(), RegexProjectNew, nil)
|
||||||
AssertSubdomain(t, BuildProjectNewJam(), "")
|
AssertSubdomain(t, BuildProjectNewJam(), "")
|
||||||
|
|
|
@ -119,6 +119,13 @@ func BuildTimeMachine() string {
|
||||||
return Url("/timemachine", nil)
|
return Url("/timemachine", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var RegexTimeMachineSubmissions = regexp.MustCompile("^/timemachine/submissions$")
|
||||||
|
|
||||||
|
func BuildTimeMachineSubmissions() string {
|
||||||
|
defer CatchPanic()
|
||||||
|
return Url("/timemachine/submissions", nil)
|
||||||
|
}
|
||||||
|
|
||||||
var RegexTimeMachineForm = regexp.MustCompile("^/timemachine/submit$")
|
var RegexTimeMachineForm = regexp.MustCompile("^/timemachine/submit$")
|
||||||
|
|
||||||
func BuildTimeMachineForm() string {
|
func BuildTimeMachineForm() string {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
<div class="frame">
|
||||||
|
{{ template "frame title" .Title }}
|
||||||
|
<div>
|
||||||
|
<div class="pa3 flex flex-column g3">
|
||||||
|
<div class="flex flex-column flex-row-ns g3">
|
||||||
|
<div class="flex-shrink-0 relative">
|
||||||
|
<img
|
||||||
|
class="pixelated inset"
|
||||||
|
src="{{ static .Thumbnail }}"
|
||||||
|
alt="Video Thumbnail"
|
||||||
|
/>
|
||||||
|
<a href="{{ .Url }}" target="_blank">
|
||||||
|
<div class="absolute absolute--fill bg-black-30 flex justify-center items-center">
|
||||||
|
<img class="pixelated" alt="Play Video" src="{{ dataimg "timemachine/win95-play.png" }}">
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-column g1">
|
||||||
|
{{ range .Details }}
|
||||||
|
<div><strong>{{ .Name }}:</strong> {{ .Content }}</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="post-content">
|
||||||
|
{{ .Description }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -33,7 +33,7 @@
|
||||||
<link href='https://fonts.googleapis.com/css?family=Fira+Mono:300,400,500,700' rel='stylesheet' type='text/css'>
|
<link href='https://fonts.googleapis.com/css?family=Fira+Mono:300,400,500,700' rel='stylesheet' type='text/css'>
|
||||||
<link rel="stylesheet" type="text/css" href="{{ static "style.css" }}">
|
<link rel="stylesheet" type="text/css" href="{{ static "style.css" }}">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
/*
|
/*
|
||||||
This is too light for accessiblity imo. I'll darken them a bit and see how Ben feels
|
This is too light for accessiblity imo. I'll darken them a bit and see how Ben feels
|
||||||
|
@ -176,24 +176,42 @@
|
||||||
.less-spacing p {
|
.less-spacing p {
|
||||||
margin: 0.2rem 0;
|
margin: 0.2rem 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="left white">
|
<div class="left white">
|
||||||
<div class="mt4-ns mw7 margin-center ph3-m ph4-l">
|
<div class="mt4-ns mw7 margin-center ph3-ns">
|
||||||
{{ template "header.html" . }}
|
{{ template "header.html" . }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="jam-sections">
|
<div class="jam-sections">
|
||||||
{{ block "content" . }}{{ end }}
|
<div class="center-layout content mw7 ph3 flex flex-column g3">
|
||||||
|
{{ with .Breadcrumbs }}
|
||||||
|
<div class="mt2 tc tl-ns ph2 ph0-ns">
|
||||||
|
{{ range $i, $e := . -}}
|
||||||
|
{{- if gt $i 0 -}}
|
||||||
|
<span class="ph2">»</span>
|
||||||
|
{{- end -}}
|
||||||
|
<a class="breadcrumb" href="{{ .Url }}">{{ .Name }}</a>
|
||||||
|
{{- end }}
|
||||||
</div>
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
{{ block "content" . }}{{ end }}
|
||||||
|
|
||||||
<div class="mw8 margin-center ph3-m ph4-l">
|
<div class="mw8 margin-center ph3-ns">
|
||||||
{{ template "footer.html" . }}
|
{{ template "footer.html" . }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
{{ define "frame title" }}
|
||||||
|
<div class="title">
|
||||||
|
{{ . }}
|
||||||
|
<img class="frame-close" src="{{ dataimg "timemachine/win95-close.gif" }}">
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
{{ template "timemachine_base.html" . }}
|
{{ template "timemachine_base.html" . }}
|
||||||
|
|
||||||
{{ define "frame title" }}
|
|
||||||
<div class="title">
|
|
||||||
{{ . }}
|
|
||||||
<img class="frame-close" src="{{ dataimg "timemachine/win95-close.gif" }}">
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
||||||
|
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
|
|
||||||
<div class="center-layout content mw7 ph3 flex flex-column g3">
|
<div class="center-layout content mw7 ph3 flex flex-column g3">
|
||||||
|
@ -77,7 +70,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end g3">
|
<div class="flex justify-end g3">
|
||||||
<a class="win95-btn" href="{{ .SubmitUrl }}"><u>S</u>ubmit your own</a>
|
<a class="win95-btn" href="{{ .SubmitUrl }}"><u>S</u>ubmit Your Own</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -92,66 +85,22 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-column flex-grow-1 g3">
|
<div class="flex flex-column flex-grow-1 g3">
|
||||||
<div>
|
<div>
|
||||||
1 video has been submitted! Would you like to see it?
|
{{ if eq .NumSubmissions 1 }}
|
||||||
|
{{ .NumSubmissions }} video has been submitted! Would you like to see it?
|
||||||
|
{{ else }}
|
||||||
|
{{ .NumSubmissions }} videos have been submitted! Would you like to see them?
|
||||||
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-end g3">
|
<div class="flex justify-end g3">
|
||||||
<div class="win95-btn"><u>Y</u>es</div>
|
<a href="{{ .SubmissionsUrl }}"><div class="win95-btn"><u>Y</u>es</div></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="frame mv4">
|
<div class="mv4">
|
||||||
{{ template "frame title" "2009 iPod Touch" }}
|
{{ template "timemachine_submission.html" .FeaturedSubmission }}
|
||||||
<div>
|
|
||||||
<div class="pa3 flex flex-column g3">
|
|
||||||
<div class="flex flex-column flex-row-ns g3">
|
|
||||||
<div class="flex-shrink-0 relative">
|
|
||||||
<img
|
|
||||||
class="pixelated inset"
|
|
||||||
src="{{ static "timemachine/ipodtouch-dither.gif" }}"
|
|
||||||
alt="Video Thumbnail"
|
|
||||||
/>
|
|
||||||
<a href="https://youtu.be/2eBFk1yV6mE" target="_blank">
|
|
||||||
<div class="absolute absolute--fill bg-black-30 flex justify-center items-center">
|
|
||||||
<img class="pixelated" alt="Play Video" src="{{ dataimg "timemachine/win95-play.png" }}">
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-column g1">
|
|
||||||
<div><strong>Device:</strong> iPod Touch 3rd gen, model MC008LL</div>
|
|
||||||
<div><strong>Submitted by:</strong> Ben Visness</div>
|
|
||||||
<div><strong>Release year:</strong> 2009</div>
|
|
||||||
<div><strong>Processor:</strong> 600MHz Samsung S5L8922, single-core</div>
|
|
||||||
<div><strong>Memory:</strong> 256MB LPDDR2 @ 200 MHz</div>
|
|
||||||
<div><strong>Operating system:</strong> iOS 5</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="post-content">
|
|
||||||
<p>
|
|
||||||
This is the iPod Touch I got when I was 13. It was my first major
|
|
||||||
tech purchase and an early device in the iOS lineup. When I
|
|
||||||
purchased this I think it was running iOS 3; at this point it has
|
|
||||||
iOS 5. I was pleased to see that the battery still holds a charge
|
|
||||||
quite well, and it consistently runs at about 30 to 60 frames per
|
|
||||||
second.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
In the video you can see several built-in apps. Media playback
|
|
||||||
still works great, and scrubbing around in songs is instantaneous.
|
|
||||||
App switching works well. The calculator launches instantly (as
|
|
||||||
you would hope). I was shocked to see that the old Google Maps app
|
|
||||||
still works - apparently they have kept their old tile-based map
|
|
||||||
servers online. It even gave me public transit directions.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Overall, I would say this device feels only a hair slower than my
|
|
||||||
current iPhone.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
{{ template "timemachine_base.html" . }}
|
||||||
|
|
||||||
|
{{ define "content" }}
|
||||||
|
<div class="center-layout content mw7 ph3 flex flex-column g3">
|
||||||
|
<div>
|
||||||
|
<div class="mv4 mv5-ns flex justify-center">
|
||||||
|
<div class="frame mw6">
|
||||||
|
{{ template "frame title" "About This Page" }}
|
||||||
|
<div class="pa3 flex g3">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<img class="pixelated" src="{{ dataimg "timemachine/win95-info.png" }}">
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-column flex-grow-1 g3">
|
||||||
|
<div>
|
||||||
|
The community has submitted the following
|
||||||
|
{{ with len .Submissions }}
|
||||||
|
{{ if eq . 1 }}video{{ else }}{{ . }} videos{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
to the Time Machine project. If you have access to any older devices, you can participate too!
|
||||||
|
</div>
|
||||||
|
<div class="flex justify-end g3">
|
||||||
|
<a href="{{ .MainUrl }}"><div class="win95-btn">Learn <u>M</u>ore</div></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-column g3">
|
||||||
|
{{ range .Submissions }}
|
||||||
|
{{ template "timemachine_submission.html" . }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
|
@ -71,6 +71,7 @@ func NewWebsiteRoutes(conn *pgxpool.Pool) http.Handler {
|
||||||
hmnOnly.GET(hmnurl.RegexJamRecap2023_Visibility, JamRecap2023_Visibility)
|
hmnOnly.GET(hmnurl.RegexJamRecap2023_Visibility, JamRecap2023_Visibility)
|
||||||
|
|
||||||
hmnOnly.GET(hmnurl.RegexTimeMachine, TimeMachine)
|
hmnOnly.GET(hmnurl.RegexTimeMachine, TimeMachine)
|
||||||
|
hmnOnly.GET(hmnurl.RegexTimeMachineSubmissions, TimeMachineSubmissions)
|
||||||
hmnOnly.GET(hmnurl.RegexTimeMachineForm, needsAuth(TimeMachineForm))
|
hmnOnly.GET(hmnurl.RegexTimeMachineForm, needsAuth(TimeMachineForm))
|
||||||
hmnOnly.GET(hmnurl.RegexTimeMachineFormDone, needsAuth(TimeMachineFormDone))
|
hmnOnly.GET(hmnurl.RegexTimeMachineFormDone, needsAuth(TimeMachineFormDone))
|
||||||
hmnOnly.POST(hmnurl.RegexTimeMachineForm, needsAuth(csrfMiddleware(TimeMachineFormSubmit)))
|
hmnOnly.POST(hmnurl.RegexTimeMachineForm, needsAuth(csrfMiddleware(TimeMachineFormSubmit)))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package website
|
package website
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -11,7 +12,46 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TimeMachine(c *RequestContext) ResponseData {
|
func TimeMachine(c *RequestContext) ResponseData {
|
||||||
baseData := getBaseDataAutocrumb(c, "Time Machine")
|
baseData := getBaseData(c, "Time Machine", nil)
|
||||||
|
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
||||||
|
{Property: "og:title", Value: "Time Machine"},
|
||||||
|
{Property: "og:site_name", Value: "Handmade Network"},
|
||||||
|
{Property: "og:type", Value: "website"},
|
||||||
|
{Property: "og:image", Value: hmnurl.BuildPublic("timemachine/opengraph.png", true)},
|
||||||
|
{Property: "og:description", Value: "This summer, dig out your old devices and see what they were actually like to use."},
|
||||||
|
{Property: "og:url", Value: hmnurl.BuildTimeMachine()},
|
||||||
|
{Name: "twitter:card", Value: "summary_large_image"},
|
||||||
|
{Name: "twitter:image", Value: hmnurl.BuildPublic("timemachine/twittercard.png", true)},
|
||||||
|
}
|
||||||
|
|
||||||
|
featured := tmSubmissions[0]
|
||||||
|
featured.Title = "Latest Submission"
|
||||||
|
|
||||||
|
type TemplateData struct {
|
||||||
|
templates.BaseData
|
||||||
|
SubmitUrl string
|
||||||
|
SubmissionsUrl string
|
||||||
|
NumSubmissions int
|
||||||
|
FeaturedSubmission TimeMachineSubmission
|
||||||
|
}
|
||||||
|
tmpl := TemplateData{
|
||||||
|
BaseData: baseData,
|
||||||
|
SubmitUrl: hmnurl.BuildTimeMachineForm(),
|
||||||
|
SubmissionsUrl: hmnurl.BuildTimeMachineSubmissions(),
|
||||||
|
NumSubmissions: len(tmSubmissions),
|
||||||
|
FeaturedSubmission: featured,
|
||||||
|
}
|
||||||
|
|
||||||
|
var res ResponseData
|
||||||
|
res.MustWriteTemplate("timemachine.html", tmpl, c.Perf)
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func TimeMachineSubmissions(c *RequestContext) ResponseData {
|
||||||
|
baseData := getBaseData(c, "Time Machine - Submissions", []templates.Breadcrumb{
|
||||||
|
{"Time Machine", hmnurl.BuildTimeMachine()},
|
||||||
|
{"Submissions", hmnurl.BuildTimeMachineSubmissions()},
|
||||||
|
})
|
||||||
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
||||||
{Property: "og:title", Value: "Time Machine"},
|
{Property: "og:title", Value: "Time Machine"},
|
||||||
{Property: "og:site_name", Value: "Handmade Network"},
|
{Property: "og:site_name", Value: "Handmade Network"},
|
||||||
|
@ -25,15 +65,19 @@ func TimeMachine(c *RequestContext) ResponseData {
|
||||||
|
|
||||||
type TemplateData struct {
|
type TemplateData struct {
|
||||||
templates.BaseData
|
templates.BaseData
|
||||||
|
MainUrl string
|
||||||
SubmitUrl string
|
SubmitUrl string
|
||||||
|
Submissions []TimeMachineSubmission
|
||||||
}
|
}
|
||||||
tmpl := TemplateData{
|
tmpl := TemplateData{
|
||||||
BaseData: baseData,
|
BaseData: baseData,
|
||||||
|
MainUrl: hmnurl.BuildTimeMachine(),
|
||||||
SubmitUrl: hmnurl.BuildTimeMachineForm(),
|
SubmitUrl: hmnurl.BuildTimeMachineForm(),
|
||||||
|
Submissions: tmSubmissions,
|
||||||
}
|
}
|
||||||
|
|
||||||
var res ResponseData
|
var res ResponseData
|
||||||
res.MustWriteTemplate("timemachine.html", tmpl, c.Perf)
|
res.MustWriteTemplate("timemachine_submissions.html", tmpl, c.Perf)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,3 +138,53 @@ func TimeMachineFormDone(c *RequestContext) ResponseData {
|
||||||
)
|
)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TimeMachineSubmission struct {
|
||||||
|
Title string
|
||||||
|
Url string
|
||||||
|
Thumbnail string
|
||||||
|
Details []TimeMachineSubmissionDetail
|
||||||
|
Description template.HTML
|
||||||
|
}
|
||||||
|
|
||||||
|
type TimeMachineSubmissionDetail struct {
|
||||||
|
Name string
|
||||||
|
Content template.HTML
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmSubmissions = []TimeMachineSubmission{
|
||||||
|
{
|
||||||
|
Title: "2009 iPod Touch",
|
||||||
|
Url: "https://youtu.be/2eBFk1yV6mE",
|
||||||
|
Thumbnail: "timemachine/ipodtouch-dither.gif",
|
||||||
|
Details: []TimeMachineSubmissionDetail{
|
||||||
|
{"Device", "iPod Touch 3rd gen, model MC008LL"},
|
||||||
|
{"Submitted by", "Ben Visness"},
|
||||||
|
{"Release year", "2009"},
|
||||||
|
{"Processor", "600MHz Samsung S5L8922, single-core"},
|
||||||
|
{"Memory", "256MB LPDDR2 @ 200 MHz"},
|
||||||
|
{"Operating system", "iOS 5"},
|
||||||
|
},
|
||||||
|
Description: `
|
||||||
|
<p>
|
||||||
|
This is the iPod Touch I got when I was 13. It was my first major
|
||||||
|
tech purchase and an early device in the iOS lineup. When I
|
||||||
|
purchased this I think it was running iOS 3; at this point it has
|
||||||
|
iOS 5. I was pleased to see that the battery still holds a charge
|
||||||
|
quite well, and it consistently runs at about 30 to 60 frames per
|
||||||
|
second.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In the video you can see several built-in apps. Media playback
|
||||||
|
still works great, and scrubbing around in songs is instantaneous.
|
||||||
|
App switching works well. The calculator launches instantly (as
|
||||||
|
you would hope). I was shocked to see that the old Google Maps app
|
||||||
|
still works - apparently they have kept their old tile-based map
|
||||||
|
servers online. It even gave me public transit directions.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Overall, I would say this device feels only a hair slower than my
|
||||||
|
current iPhone.
|
||||||
|
</p>`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue