diff --git a/src/hmndata/jams.go b/src/hmndata/jams.go new file mode 100644 index 00000000..107fb6d1 --- /dev/null +++ b/src/hmndata/jams.go @@ -0,0 +1,116 @@ +package hmndata + +import ( + "context" + "sort" + "time" + + "git.handmade.network/hmn/hmn/src/db" + "git.handmade.network/hmn/hmn/src/models" + "git.handmade.network/hmn/hmn/src/oops" +) + +type Jam struct { + Name string + Slug string + StartTime time.Time + EndTime time.Time +} + +var WRJ2021 = Jam{ + Name: "Wheel Reinvention Jam 2021", + Slug: "WRJ2021", + StartTime: time.Date(2021, 9, 27, 0, 0, 0, 0, time.UTC), + EndTime: time.Date(2021, 10, 4, 0, 0, 0, 0, time.UTC), +} + +var WRJ2022 = Jam{ + Name: "Wheel Reinvention Jam 2022", + Slug: "WRJ2022", + // StartTime: time.Date(2022, 8, 15, 0, 0, 0, 0, time.UTC), + StartTime: time.Date(2021, 8, 15, 0, 0, 0, 0, time.UTC), + EndTime: time.Date(2022, 8, 22, 0, 0, 0, 0, time.UTC), +} + +var AllJams = []Jam{WRJ2021, WRJ2022} + +func CurrentJam() *Jam { + now := time.Now() + for i, jam := range AllJams { + if jam.StartTime.Before(now) && now.Before(jam.EndTime) { + return &AllJams[i] + } + } + return nil +} + +func JamBySlug(slug string) Jam { + for _, jam := range AllJams { + if jam.Slug == slug { + return jam + } + } + return Jam{Slug: slug} +} + +func FetchJamsForProject(ctx context.Context, dbConn db.ConnOrTx, user *models.User, projectId int) ([]*models.JamProject, error) { + jamProjects, err := db.Query[models.JamProject](ctx, dbConn, + ` + SELECT $columns + FROM jam_project + WHERE project_id = $1 + `, + projectId, + ) + if err != nil { + return nil, oops.New(err, "failed to fetch jams for project") + } + + currentJam := CurrentJam() + foundCurrent := false + for i, _ := range jamProjects { + jam := JamBySlug(jamProjects[i].JamSlug) + jamProjects[i].JamName = jam.Name + jamProjects[i].JamStartTime = jam.StartTime + + if currentJam != nil && currentJam.Slug == jamProjects[i].JamSlug { + foundCurrent = true + } + } + if currentJam != nil && !foundCurrent { + jamProjects = append(jamProjects, &models.JamProject{ + ProjectID: projectId, + JamSlug: currentJam.Slug, + Participating: false, + JamName: currentJam.Name, + JamStartTime: currentJam.StartTime, + }) + } + + if user != nil && user.IsStaff { + for _, jam := range AllJams { + found := false + for _, jp := range jamProjects { + if jp.JamSlug == jam.Slug { + found = true + break + } + } + if !found { + jamProjects = append(jamProjects, &models.JamProject{ + ProjectID: projectId, + JamSlug: jam.Slug, + Participating: false, + JamName: jam.Name, + JamStartTime: jam.StartTime, + }) + } + } + } + + sort.Slice(jamProjects, func(i, j int) bool { + return jamProjects[i].JamStartTime.Before(jamProjects[j].JamStartTime) + }) + + return jamProjects, nil +} diff --git a/src/hmnurl/urls.go b/src/hmnurl/urls.go index 74775d23..9212477b 100644 --- a/src/hmnurl/urls.go +++ b/src/hmnurl/urls.go @@ -56,7 +56,26 @@ func BuildJamIndex() string { return Url("/jam", nil) } -var RegexJamIndex2021 = regexp.MustCompile("^/jam/2021") +var RegexJamIndex2021 = regexp.MustCompile("^/jam/2021$") + +func BuildJamIndex2021() string { + defer CatchPanic() + return Url("/jam/2021", nil) +} + +var RegexJamIndex2022 = regexp.MustCompile("^/jam/2022$") + +func BuildJamIndex2022() string { + defer CatchPanic() + return Url("/jam/2022", nil) +} + +var RegexJamFeed2022 = regexp.MustCompile("^/jam/2022/feed$") + +func BuildJamFeed2022() string { + defer CatchPanic() + return Url("/jam/2022/feed", nil) +} // QUESTION(ben): Can we change these routes? diff --git a/src/migration/migrations/2022-06-18T010339Z_AddJamProjects.go b/src/migration/migrations/2022-06-18T010339Z_AddJamProjects.go new file mode 100644 index 00000000..93ca060c --- /dev/null +++ b/src/migration/migrations/2022-06-18T010339Z_AddJamProjects.go @@ -0,0 +1,54 @@ +package migrations + +import ( + "context" + "time" + + "git.handmade.network/hmn/hmn/src/migration/types" + "github.com/jackc/pgx/v4" +) + +func init() { + registerMigration(AddJamProjects{}) +} + +type AddJamProjects struct{} + +func (m AddJamProjects) Version() types.MigrationVersion { + return types.MigrationVersion(time.Date(2022, 6, 18, 1, 3, 39, 0, time.UTC)) +} + +func (m AddJamProjects) Name() string { + return "AddJamProjects" +} + +func (m AddJamProjects) Description() string { + return "Add jam and project association table" +} + +func (m AddJamProjects) Up(ctx context.Context, tx pgx.Tx) error { + _, err := tx.Exec(ctx, + ` + CREATE TABLE jam_project ( + project_id INT REFERENCES project (id) ON DELETE CASCADE, + jam_slug VARCHAR(64) NOT NULL, + participating BOOLEAN NOT NULL DEFAULT FALSE, + UNIQUE (project_id, jam_slug) + ); + CREATE INDEX jam_project_jam_slug ON jam_project (jam_slug); + CREATE INDEX jam_project_project_id ON jam_project (project_id); + `, + ) + return err +} + +func (m AddJamProjects) Down(ctx context.Context, tx pgx.Tx) error { + _, err := tx.Exec(ctx, + ` + DROP INDEX jam_project_jam_slug; + DROP INDEX jam_project_project_id; + DROP TABLE jam_project; + `, + ) + return err +} diff --git a/src/models/jamproject.go b/src/models/jamproject.go new file mode 100644 index 00000000..d89403eb --- /dev/null +++ b/src/models/jamproject.go @@ -0,0 +1,11 @@ +package models + +import "time" + +type JamProject struct { + ProjectID int `db:"project_id"` + JamSlug string `db:"jam_slug"` + Participating bool `db:"participating"` + JamName string + JamStartTime time.Time +} diff --git a/src/templates/src/project_edit.html b/src/templates/src/project_edit.html index 3fb5d1cf..1df121b4 100644 --- a/src/templates/src/project_edit.html +++ b/src/templates/src/project_edit.html @@ -20,7 +20,7 @@ {{ if .Editing }}