From b5d4fe9ba201c203eb50bd90c4584499b19c8d56 Mon Sep 17 00:00:00 2001 From: Asaf Gartner Date: Thu, 8 Feb 2024 22:21:01 +0200 Subject: [PATCH] Learning jam scaffolding --- src/hmndata/jams.go | 13 +- src/hmnurl/hmnurl_test.go | 11 +- src/hmnurl/urls.go | 14 ++ src/templates/src/include/header.html | 2 +- src/templates/src/jam_2024_lj_feed.html | 74 +++++++++ src/templates/src/jam_2024_lj_index.html | 93 +++++++++++ src/templates/src/jams_index.html | 5 + src/templates/src/landing.html | 69 ++++++++ .../src/layouts/jam_2024_learning_base.html | 152 ++++++++++++++++++ src/templates/types.go | 1 + src/website/base_data.go | 1 + src/website/jam.go | 135 ++++++++++++++++ src/website/landing.go | 6 +- src/website/routes.go | 2 + 14 files changed, 572 insertions(+), 6 deletions(-) create mode 100644 src/templates/src/jam_2024_lj_feed.html create mode 100644 src/templates/src/jam_2024_lj_index.html create mode 100644 src/templates/src/layouts/jam_2024_learning_base.html diff --git a/src/hmndata/jams.go b/src/hmndata/jams.go index 3b206f3f..7799d7a9 100644 --- a/src/hmndata/jams.go +++ b/src/hmndata/jams.go @@ -62,6 +62,17 @@ var WRJ2023 = Jam{ UrlSlug: "2023", } +var LJ2024 = Jam{ + Event: Event{ + StartTime: time.Date(2024, 3, 15, 17, 0, 0, 0, time.UTC), + EndTime: time.Date(2024, 3, 24, 20, 0, 0, 0, time.UTC), + }, + Name: "Learning Jam 2024", + Slug: "LJ2024", + UrlSlug: "learning-2024", +} + +// Conferences var HMS2022 = Event{ StartTime: time.Date(2022, 11, 16, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))), EndTime: time.Date(2022, 11, 18, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))), @@ -77,7 +88,7 @@ var HMBoston2023 = Event{ EndTime: time.Date(2023, 8, 4, 0, 0, 0, 0, utils.Must1(time.LoadLocation("America/Los_Angeles"))), } -var AllJams = []Jam{WRJ2021, WRJ2022, VJ2023, WRJ2023} +var AllJams = []Jam{WRJ2021, WRJ2022, VJ2023, WRJ2023, LJ2024} func CurrentJam() *Jam { now := time.Now() diff --git a/src/hmnurl/hmnurl_test.go b/src/hmnurl/hmnurl_test.go index cbbaa0a6..b4e18379 100644 --- a/src/hmnurl/hmnurl_test.go +++ b/src/hmnurl/hmnurl_test.go @@ -143,7 +143,6 @@ func TestFeed(t *testing.T) { func TestProjectIndex(t *testing.T) { AssertRegexMatch(t, BuildProjectIndex(1, ""), RegexProjectIndex, nil) - AssertRegexMatch(t, BuildProjectIndex(2, ""), RegexProjectIndex, map[string]string{"page": "2"}) AssertRegexMatch(t, BuildProjectIndex(1, "test"), RegexProjectIndex, map[string]string{"category": "test"}) AssertRegexMatch(t, BuildProjectIndex(2, "test"), RegexProjectIndex, map[string]string{"page": "2", "category": "test"}) assert.Panics(t, func() { BuildProjectIndex(0, "") }) @@ -427,6 +426,16 @@ func TestJamFeed2023(t *testing.T) { AssertSubdomain(t, BuildJamFeed2023(), "") } +func TestJamIndex2024_Learning(t *testing.T) { + AssertRegexMatch(t, BuildJamIndex2024_Learning(), RegexJamIndex2024_Learning, nil) + AssertSubdomain(t, BuildJamIndex2024_Learning(), "") +} + +func TestJamFeed2024_Learning(t *testing.T) { + AssertRegexMatch(t, BuildJamFeed2024_Learning(), RegexJamFeed2024_Learning, nil) + AssertSubdomain(t, BuildJamFeed2024_Learning(), "") +} + func TestTimeMachine(t *testing.T) { AssertRegexMatch(t, BuildTimeMachine(), RegexTimeMachine, nil) AssertSubdomain(t, BuildTimeMachine(), "") diff --git a/src/hmnurl/urls.go b/src/hmnurl/urls.go index a057ba5d..ab77e622 100644 --- a/src/hmnurl/urls.go +++ b/src/hmnurl/urls.go @@ -126,6 +126,20 @@ func BuildJamRecap2023_Visibility() string { return Url("/jam/visibility-2023/recap", nil) } +var RegexJamIndex2024_Learning = regexp.MustCompile("^/jam/learning-2024$") + +func BuildJamIndex2024_Learning() string { + defer CatchPanic() + return Url("/jam/learning-2024", nil) +} + +var RegexJamFeed2024_Learning = regexp.MustCompile("^/jam/learning-2024/feed$") + +func BuildJamFeed2024_Learning() string { + defer CatchPanic() + return Url("/jam/learning-2024/feed", nil) +} + func BuildJamIndexAny(slug string) string { defer CatchPanic() return Url(fmt.Sprintf("/jam/%s", slug), nil) diff --git a/src/templates/src/include/header.html b/src/templates/src/include/header.html index d87aca9a..13069fe0 100644 --- a/src/templates/src/include/header.html +++ b/src/templates/src/include/header.html @@ -91,7 +91,7 @@ Fishbowls Podcast Handmade Dev Show - Calendar + {{/*Calendar*/}}
diff --git a/src/templates/src/jam_2024_lj_feed.html b/src/templates/src/jam_2024_lj_feed.html new file mode 100644 index 00000000..314a3bd8 --- /dev/null +++ b/src/templates/src/jam_2024_lj_feed.html @@ -0,0 +1,74 @@ +{{ template "jam_2024_learning_base.html" . }} +{{ define "content-top" }} +
+ +
The Learning Jam
+
+
+
Learn
+
March 15-17, 2024
+
+
+
Teach
+
March 22-24, 2024
+
+
+ +
+{{ end }} + +{{ define "content" }} +
+
+

Recent activity

+
+ {{ if .TimelineItems }} + {{ range .TimelineItems }} +
+
+ {{ if .OwnerAvatarUrl }} + + + + {{ end }} +
+
{{ .OwnerName }}
+
{{ timehtml (relativedate .Date) .Date }}
+
+
+ {{ if .Description }} +
{{ trim .Description }}
+ {{ end }} + {{ range .EmbedMedia }} +
+ {{ if eq .Type mediaimage }} + + {{ else if eq .Type mediavideo }} + {{ if .ThumbnailUrl }} +
+ {{ end }} +
+ {{ end }} + {{ else }} + Be the first! + {{ end }} +
+
+
+{{ end }} + diff --git a/src/templates/src/jam_2024_lj_index.html b/src/templates/src/jam_2024_lj_index.html new file mode 100644 index 00000000..c7a4b13c --- /dev/null +++ b/src/templates/src/jam_2024_lj_index.html @@ -0,0 +1,93 @@ +{{ template "jam_2024_learning_base.html" . }} +{{ define "content-top" }} +
+ +
The Learning Jam
+
+
+
Learn
+
March 15-17, 2024
+
+
+
Teach
+
March 22-24, 2024
+
+
+ {{ if lt .DaysUntilStart 0 }} +
+ {{ if .SubmittedProjectUrl }} + Share your progress + {{ else }} + Create your project + {{ end }} + Recent activity +
+ {{ end }} + +
+{{ end }} + +{{ define "content" }} + +
+
+

How to participate

+
+
+
+ +
+
+
Pick a project and form a team
+
Find a project idea that excites you etc...
+
+
+
+
+ +
+
+
Pick a project and form a team
+
Find a project idea that excites you etc...
+
+
+
+
+ +
+
+
Pick a project and form a team
+
Find a project idea that excites you etc...
+
+
+
+
+
+
+

March 15 - 17, 2024

+
+ Do things +
+
+
+
+

March 22 - 24, 2024

+
+ Do more things +
+
+
+
+

Rules

+
+ Do more things +
+
+
+{{ end }} diff --git a/src/templates/src/jams_index.html b/src/templates/src/jams_index.html index 4ec8f3be..59edd584 100644 --- a/src/templates/src/jams_index.html +++ b/src/templates/src/jams_index.html @@ -16,6 +16,11 @@

Since 2020, we have been running programming jams to encourage community members to explore new ideas and start projects. You can view all the past submissions and results here.

+ +
+ +
+
diff --git a/src/templates/src/landing.html b/src/templates/src/landing.html index 24fe56c3..73c4e25e 100644 --- a/src/templates/src/landing.html +++ b/src/templates/src/landing.html @@ -111,6 +111,74 @@
*/}} +
+ +{{/*
+ + + +
+
+ HANDMADE +
+
+ {{ block "content-top" . }}{{ end }} +
+
+ {{ block "content" . }}{{ end }} +
+ + + + diff --git a/src/templates/types.go b/src/templates/types.go index dd717c29..0b9a9029 100644 --- a/src/templates/types.go +++ b/src/templates/types.go @@ -20,6 +20,7 @@ type BaseData struct { CurrentProjectUrl string LoginPageUrl string ProjectCSSUrl string + DiscordInviteUrl string Project Project User *User diff --git a/src/website/base_data.go b/src/website/base_data.go index 3b7ce4a7..01307ef3 100644 --- a/src/website/base_data.go +++ b/src/website/base_data.go @@ -51,6 +51,7 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc CurrentProjectUrl: c.UrlContext.BuildHomepage(), LoginPageUrl: hmnurl.BuildLoginPage(c.FullUrl()), ProjectCSSUrl: hmnurl.BuildProjectCSS(project.Color1), + DiscordInviteUrl: "https://discord.gg/hmn", Project: templates.ProjectToTemplate(&project, c.UrlContext.BuildHomepage()), User: templateUser, diff --git a/src/website/jam.go b/src/website/jam.go index 35318c39..e0259cb4 100644 --- a/src/website/jam.go +++ b/src/website/jam.go @@ -27,6 +27,7 @@ func JamsIndex(c *RequestContext) ResponseData { WRJ2022Url string VJ2023Url string WRJ2023Url string + LJ2024Url string } res.MustWriteTemplate("jams_index.html", TemplateData{ @@ -37,6 +38,140 @@ func JamsIndex(c *RequestContext) ResponseData { WRJ2022Url: hmnurl.BuildJamIndex2022(), VJ2023Url: hmnurl.BuildJamIndex2023_Visibility(), WRJ2023Url: hmnurl.BuildJamIndex2023(), + LJ2024Url: hmnurl.BuildJamIndex2024_Learning(), + }, c.Perf) + return res +} + +func JamIndex2024_Learning(c *RequestContext) ResponseData { + var res ResponseData + + daysUntilStart := daysUntil(hmndata.LJ2024.StartTime) + daysUntilEnd := daysUntil(hmndata.LJ2024.EndTime) + + baseData := getBaseDataAutocrumb(c, hmndata.LJ2024.Name) + baseData.OpenGraphItems = []templates.OpenGraphItem{ + {Property: "og:site_name", Value: "Handmade Network"}, + {Property: "og:type", Value: "website"}, + {Property: "og:image", Value: hmnurl.BuildPublic("learningjam2024/opengraph.png", true)}, + {Property: "og:description", Value: "Need desc"}, + {Property: "og:url", Value: hmnurl.BuildJamIndex2024_Learning()}, + } + + type JamPageData struct { + templates.BaseData + DaysUntilStart, DaysUntilEnd int + TwitchEmbedUrl string + ProjectSubmissionUrl string + SubmittedProjectUrl string + JamFeedUrl string + } + + twitchEmbedUrl := "" + twitchStatus, err := db.QueryOne[models.TwitchLatestStatus](c, c.Conn, + ` + SELECT $columns + FROM twitch_latest_status + WHERE twitch_login = $1 + `, + "handmadenetwork", + ) + if err == nil { + if twitchStatus.Live { + hmnUrl, err := url.Parse(config.Config.BaseUrl) + if err == nil { + twitchEmbedUrl = fmt.Sprintf("https://player.twitch.tv/?channel=%s&parent=%s", twitchStatus.TwitchLogin, hmnUrl.Hostname()) + } + } + } + + submittedProjectUrl := "" + + if c.CurrentUser != nil { + projects, err := hmndata.FetchProjects(c, c.Conn, c.CurrentUser, hmndata.ProjectsQuery{ + OwnerIDs: []int{c.CurrentUser.ID}, + JamSlugs: []string{hmndata.WRJ2023.Slug}, + Limit: 1, + }) + if err != nil { + return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch jam projects for current user")) + } + if len(projects) > 0 { + urlContext := hmndata.UrlContextForProject(&projects[0].Project) + submittedProjectUrl = urlContext.BuildHomepage() + } + } + + res.MustWriteTemplate("jam_2024_lj_index.html", JamPageData{ + BaseData: baseData, + DaysUntilStart: daysUntilStart, + DaysUntilEnd: daysUntilEnd, + ProjectSubmissionUrl: hmnurl.BuildProjectNewJam(), + SubmittedProjectUrl: submittedProjectUrl, + JamFeedUrl: hmnurl.BuildJamFeed2024_Learning(), + TwitchEmbedUrl: twitchEmbedUrl, + }, c.Perf) + return res +} + +func JamFeed2024_Learning(c *RequestContext) ResponseData { + jamProjects, err := hmndata.FetchProjects(c, c.Conn, c.CurrentUser, hmndata.ProjectsQuery{ + JamSlugs: []string{hmndata.LJ2024.Slug}, + }) + if err != nil { + return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch jam projects for current user")) + } + + projectIds := make([]int, 0, len(jamProjects)) + for _, jp := range jamProjects { + projectIds = append(projectIds, jp.Project.ID) + } + + var timelineItems []templates.TimelineItem + if len(projectIds) > 0 { + snippets, err := hmndata.FetchSnippets(c, c.Conn, c.CurrentUser, hmndata.SnippetQuery{ + ProjectIDs: projectIds, + }) + if err != nil { + return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch snippets for jam showcase")) + } + + timelineItems = make([]templates.TimelineItem, 0, len(snippets)) + for _, s := range snippets { + timelineItem := SnippetToTimelineItem(&s.Snippet, s.Asset, s.DiscordMessage, s.Projects, s.Owner, c.Theme, false) + timelineItem.SmallInfo = true + timelineItems = append(timelineItems, timelineItem) + } + } + + type JamFeedData struct { + templates.BaseData + DaysUntilStart, DaysUntilEnd int + + TimelineItems []templates.TimelineItem + } + + daysUntilStart := daysUntil(hmndata.LJ2024.StartTime) + daysUntilEnd := daysUntil(hmndata.LJ2024.EndTime) + + baseData := getBaseDataAutocrumb(c, hmndata.LJ2024.Name) + baseData.OpenGraphItems = []templates.OpenGraphItem{ + {Property: "og:site_name", Value: "Handmade Network"}, + {Property: "og:type", Value: "website"}, + {Property: "og:image", Value: hmnurl.BuildPublic("learningjam2024/opengraph.png", true)}, + {Property: "og:description", Value: "Need desc"}, + {Property: "og:url", Value: hmnurl.BuildJamFeed2024_Learning()}, + } + + var res ResponseData + res.MustWriteTemplate("jam_2024_lj_feed.html", JamFeedData{ + BaseData: baseData, + DaysUntilStart: daysUntilStart, + DaysUntilEnd: daysUntilEnd, + TimelineItems: timelineItems, + // ProjectSubmissionUrl: hmnurl.BuildProjectNewJam(), + // SubmittedProjectUrl: submittedProjectUrl, + // JamProjects: pageProjects, }, c.Perf) return res } diff --git a/src/website/landing.go b/src/website/landing.go index 86e5854a..528cc951 100644 --- a/src/website/landing.go +++ b/src/website/landing.go @@ -156,9 +156,9 @@ func Index(c *RequestContext) ResponseData { AtomFeedUrl: hmnurl.BuildAtomFeed(), MarkAllReadUrl: hmnurl.HMNProjectContext.BuildForumMarkRead(0), - JamUrl: hmnurl.BuildJamIndex2023(), - JamDaysUntilStart: daysUntil(hmndata.WRJ2023.StartTime), - JamDaysUntilEnd: daysUntil(hmndata.WRJ2023.EndTime), + JamUrl: hmnurl.BuildJamIndex2024_Learning(), + JamDaysUntilStart: daysUntil(hmndata.LJ2024.StartTime), + JamDaysUntilEnd: daysUntil(hmndata.LJ2024.EndTime), HMSDaysUntilStart: daysUntil(hmndata.HMS2023.StartTime), HMSDaysUntilEnd: daysUntil(hmndata.HMS2023.EndTime), diff --git a/src/website/routes.go b/src/website/routes.go index 76bad978..74d7d773 100644 --- a/src/website/routes.go +++ b/src/website/routes.go @@ -71,6 +71,8 @@ func NewWebsiteRoutes(conn *pgxpool.Pool) http.Handler { hmnOnly.GET(hmnurl.RegexJamRecap2023_Visibility, JamRecap2023_Visibility) hmnOnly.GET(hmnurl.RegexJamIndex2023, JamIndex2023) hmnOnly.GET(hmnurl.RegexJamFeed2023, JamFeed2023) + hmnOnly.GET(hmnurl.RegexJamIndex2024_Learning, JamIndex2024_Learning) + hmnOnly.GET(hmnurl.RegexJamFeed2024_Learning, JamFeed2024_Learning) hmnOnly.GET(hmnurl.RegexTimeMachine, TimeMachine) hmnOnly.GET(hmnurl.RegexTimeMachineSubmissions, TimeMachineSubmissions)