Added jam/project association.
This commit is contained in:
parent
359354f2aa
commit
9d1d249ec0
|
@ -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
|
||||||
|
}
|
|
@ -56,7 +56,26 @@ func BuildJamIndex() string {
|
||||||
return Url("/jam", nil)
|
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?
|
// QUESTION(ben): Can we change these routes?
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -20,7 +20,7 @@
|
||||||
{{ if .Editing }}
|
{{ if .Editing }}
|
||||||
<h1>Edit {{ .ProjectSettings.Name }}</h1>
|
<h1>Edit {{ .ProjectSettings.Name }}</h1>
|
||||||
{{ else }}
|
{{ else }}
|
||||||
<h1>Create a new project</h1>
|
<h1>Create a new {{ if .ProjectSettings.JamParticipation }}jam {{ end }}project</h1>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
<form id="project_form" class="tabbed edit-form" method="POST" enctype="multipart/form-data">
|
<form id="project_form" class="tabbed edit-form" method="POST" enctype="multipart/form-data">
|
||||||
{{ csrftoken .Session }}
|
{{ csrftoken .Session }}
|
||||||
|
@ -81,6 +81,20 @@
|
||||||
<div class="c--dim f7" id="tag-discord-info">If you have linked your Discord account, any #project-showcase messages with the tag "&<span id="tag-preview"></span>" will automatically be associated with this project.</div>
|
<div class="c--dim f7" id="tag-discord-info">If you have linked your Discord account, any #project-showcase messages with the tag "&<span id="tag-preview"></span>" will automatically be associated with this project.</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{ if .ProjectSettings.JamParticipation }}
|
||||||
|
<div class="edit-form-row">
|
||||||
|
<div class="pt-input-ns">Jam Participation</div>
|
||||||
|
</div>
|
||||||
|
{{ range .ProjectSettings.JamParticipation }}
|
||||||
|
<div class="edit-form-row">
|
||||||
|
<div>{{ .JamName }}:</div>
|
||||||
|
<div>
|
||||||
|
<input id="jam_{{ .JamSlug }}" type="checkbox" name="jam_participation" value="{{ .JamSlug }}" {{ if .Participating }}checked{{ end }} />
|
||||||
|
<label for="jam_{{ .JamSlug }}">Participating</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
{{ if and .Editing .User.IsStaff }}
|
{{ if and .Editing .User.IsStaff }}
|
||||||
<div class="edit-form-row">
|
<div class="edit-form-row">
|
||||||
<div class="pt-input-ns">Admin settings</div>
|
<div class="pt-input-ns">Admin settings</div>
|
||||||
|
|
|
@ -138,13 +138,14 @@ type Project struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectSettings struct {
|
type ProjectSettings struct {
|
||||||
Name string
|
Name string
|
||||||
Slug string
|
Slug string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Featured bool
|
Featured bool
|
||||||
Personal bool
|
Personal bool
|
||||||
Lifecycle string
|
Lifecycle string
|
||||||
Tag string
|
Tag string
|
||||||
|
JamParticipation []ProjectJamParticipation
|
||||||
|
|
||||||
Blurb string
|
Blurb string
|
||||||
Description string
|
Description string
|
||||||
|
@ -155,6 +156,12 @@ type ProjectSettings struct {
|
||||||
DarkLogo string
|
DarkLogo string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ProjectJamParticipation struct {
|
||||||
|
JamName string
|
||||||
|
JamSlug string
|
||||||
|
Participating bool
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
ID int
|
ID int
|
||||||
Username string
|
Username string
|
||||||
|
|
|
@ -14,12 +14,13 @@ import (
|
||||||
func JamIndex2022(c *RequestContext) ResponseData {
|
func JamIndex2022(c *RequestContext) ResponseData {
|
||||||
var res ResponseData
|
var res ResponseData
|
||||||
|
|
||||||
jamStartTime := time.Date(2022, 8, 15, 0, 0, 0, 0, time.UTC)
|
// If logged in, fetch jam project
|
||||||
jamEndTime := time.Date(2022, 8, 22, 0, 0, 0, 0, time.UTC)
|
// Link to project page if found, otherwise link to project creation page with ?jam=1
|
||||||
daysUntilStart := daysUntil(jamStartTime)
|
|
||||||
daysUntilEnd := daysUntil(jamEndTime)
|
|
||||||
|
|
||||||
baseData := getBaseDataAutocrumb(c, "Wheel Reinvention Jam 2022")
|
daysUntilStart := daysUntil(hmndata.WRJ2022.StartTime)
|
||||||
|
daysUntilEnd := daysUntil(hmndata.WRJ2022.EndTime)
|
||||||
|
|
||||||
|
baseData := getBaseDataAutocrumb(c, hmndata.WRJ2022.Name)
|
||||||
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
||||||
{Property: "og:site_name", Value: "Handmade.Network"},
|
{Property: "og:site_name", Value: "Handmade.Network"},
|
||||||
{Property: "og:type", Value: "website"},
|
{Property: "og:type", Value: "website"},
|
||||||
|
@ -41,11 +42,18 @@ func JamIndex2022(c *RequestContext) ResponseData {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func JamFeed2022(c *RequestContext) ResponseData {
|
||||||
|
// List newly-created jam projects
|
||||||
|
// list snippets from jam projects
|
||||||
|
// list forum posts from jam project threads
|
||||||
|
// timeline everything
|
||||||
|
return FourOhFour(c)
|
||||||
|
}
|
||||||
|
|
||||||
func JamIndex2021(c *RequestContext) ResponseData {
|
func JamIndex2021(c *RequestContext) ResponseData {
|
||||||
var res ResponseData
|
var res ResponseData
|
||||||
|
|
||||||
jamStartTime := time.Date(2021, 9, 27, 0, 0, 0, 0, time.UTC)
|
daysUntilJam := daysUntil(hmndata.WRJ2021.StartTime)
|
||||||
daysUntilJam := daysUntil(jamStartTime)
|
|
||||||
if daysUntilJam < 0 {
|
if daysUntilJam < 0 {
|
||||||
daysUntilJam = 0
|
daysUntilJam = 0
|
||||||
}
|
}
|
||||||
|
@ -79,7 +87,7 @@ func JamIndex2021(c *RequestContext) ResponseData {
|
||||||
showcaseJson := templates.TimelineItemsToJSON(showcaseItems)
|
showcaseJson := templates.TimelineItemsToJSON(showcaseItems)
|
||||||
c.Perf.EndBlock()
|
c.Perf.EndBlock()
|
||||||
|
|
||||||
baseData := getBaseDataAutocrumb(c, "Wheel Reinvention Jam")
|
baseData := getBaseDataAutocrumb(c, hmndata.WRJ2021.Name)
|
||||||
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
baseData.OpenGraphItems = []templates.OpenGraphItem{
|
||||||
{Property: "og:site_name", Value: "Handmade.Network"},
|
{Property: "og:site_name", Value: "Handmade.Network"},
|
||||||
{Property: "og:type", Value: "website"},
|
{Property: "og:type", Value: "website"},
|
||||||
|
|
|
@ -378,6 +378,21 @@ func ProjectNew(c *RequestContext) ResponseData {
|
||||||
var project templates.ProjectSettings
|
var project templates.ProjectSettings
|
||||||
project.Owners = append(project.Owners, templates.UserToTemplate(c.CurrentUser, c.Theme))
|
project.Owners = append(project.Owners, templates.UserToTemplate(c.CurrentUser, c.Theme))
|
||||||
project.Personal = true
|
project.Personal = true
|
||||||
|
|
||||||
|
var currentJam *hmndata.Jam
|
||||||
|
if c.Req.URL.Query().Has("jam") {
|
||||||
|
currentJam = hmndata.CurrentJam()
|
||||||
|
if currentJam != nil {
|
||||||
|
project.JamParticipation = []templates.ProjectJamParticipation{
|
||||||
|
templates.ProjectJamParticipation{
|
||||||
|
JamName: currentJam.Name,
|
||||||
|
JamSlug: currentJam.Slug,
|
||||||
|
Participating: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var res ResponseData
|
var res ResponseData
|
||||||
res.MustWriteTemplate("project_edit.html", ProjectEditData{
|
res.MustWriteTemplate("project_edit.html", ProjectEditData{
|
||||||
BaseData: getBaseDataAutocrumb(c, "New Project"),
|
BaseData: getBaseDataAutocrumb(c, "New Project"),
|
||||||
|
@ -489,6 +504,13 @@ func ProjectEdit(c *RequestContext) ResponseData {
|
||||||
}
|
}
|
||||||
c.Perf.EndBlock()
|
c.Perf.EndBlock()
|
||||||
|
|
||||||
|
c.Perf.StartBlock("SQL", "Fetching project jams")
|
||||||
|
projectJams, err := hmndata.FetchJamsForProject(c.Context(), c.Conn, c.CurrentUser, p.Project.ID)
|
||||||
|
if err != nil {
|
||||||
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch jams for project"))
|
||||||
|
}
|
||||||
|
c.Perf.EndBlock()
|
||||||
|
|
||||||
lightLogoUrl := templates.ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, "light")
|
lightLogoUrl := templates.ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, "light")
|
||||||
darkLogoUrl := templates.ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, "dark")
|
darkLogoUrl := templates.ProjectLogoUrl(&p.Project, p.LogoLightAsset, p.LogoDarkAsset, "dark")
|
||||||
|
|
||||||
|
@ -502,6 +524,15 @@ func ProjectEdit(c *RequestContext) ResponseData {
|
||||||
|
|
||||||
projectSettings.LinksText = LinksToText(projectLinks)
|
projectSettings.LinksText = LinksToText(projectLinks)
|
||||||
|
|
||||||
|
projectSettings.JamParticipation = make([]templates.ProjectJamParticipation, 0, len(projectJams))
|
||||||
|
for _, jam := range projectJams {
|
||||||
|
projectSettings.JamParticipation = append(projectSettings.JamParticipation, templates.ProjectJamParticipation{
|
||||||
|
JamName: jam.JamName,
|
||||||
|
JamSlug: jam.JamSlug,
|
||||||
|
Participating: jam.Participating,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
var res ResponseData
|
var res ResponseData
|
||||||
res.MustWriteTemplate("project_edit.html", ProjectEditData{
|
res.MustWriteTemplate("project_edit.html", ProjectEditData{
|
||||||
BaseData: getBaseDataAutocrumb(c, "Edit Project"),
|
BaseData: getBaseDataAutocrumb(c, "Edit Project"),
|
||||||
|
@ -553,18 +584,19 @@ func ProjectEditSubmit(c *RequestContext) ResponseData {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProjectPayload struct {
|
type ProjectPayload struct {
|
||||||
ProjectID int
|
ProjectID int
|
||||||
Name string
|
Name string
|
||||||
Blurb string
|
Blurb string
|
||||||
Links []ParsedLink
|
Links []ParsedLink
|
||||||
Description string
|
Description string
|
||||||
ParsedDescription string
|
ParsedDescription string
|
||||||
Lifecycle models.ProjectLifecycle
|
Lifecycle models.ProjectLifecycle
|
||||||
Hidden bool
|
Hidden bool
|
||||||
OwnerUsernames []string
|
OwnerUsernames []string
|
||||||
LightLogo FormImage
|
LightLogo FormImage
|
||||||
DarkLogo FormImage
|
DarkLogo FormImage
|
||||||
Tag string
|
Tag string
|
||||||
|
JamParticipationSlugs []string
|
||||||
|
|
||||||
Slug string
|
Slug string
|
||||||
Featured bool
|
Featured bool
|
||||||
|
@ -647,21 +679,24 @@ func ParseProjectEditForm(c *RequestContext) ProjectEditFormResult {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jamParticipationSlugs := c.Req.Form["jam_participation"]
|
||||||
|
|
||||||
res.Payload = ProjectPayload{
|
res.Payload = ProjectPayload{
|
||||||
Name: projectName,
|
Name: projectName,
|
||||||
Blurb: shortDesc,
|
Blurb: shortDesc,
|
||||||
Links: links,
|
Links: links,
|
||||||
Description: description,
|
Description: description,
|
||||||
ParsedDescription: parsedDescription,
|
ParsedDescription: parsedDescription,
|
||||||
Lifecycle: lifecycle,
|
Lifecycle: lifecycle,
|
||||||
Hidden: hidden,
|
Hidden: hidden,
|
||||||
OwnerUsernames: owners,
|
OwnerUsernames: owners,
|
||||||
LightLogo: lightLogo,
|
LightLogo: lightLogo,
|
||||||
DarkLogo: darkLogo,
|
DarkLogo: darkLogo,
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
Slug: slug,
|
JamParticipationSlugs: jamParticipationSlugs,
|
||||||
Personal: !official,
|
Slug: slug,
|
||||||
Featured: featured,
|
Personal: !official,
|
||||||
|
Featured: featured,
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
|
@ -861,6 +896,70 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
|
||||||
twitch.UserOrProjectLinksUpdated(twitchLoginsPreChange, twitchLoginsPostChange)
|
twitch.UserOrProjectLinksUpdated(twitchLoginsPreChange, twitchLoginsPostChange)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE(asaf): Regular users can only edit the jam participation status of the current jam or
|
||||||
|
// jams the project was previously a part of.
|
||||||
|
var possibleJamSlugs []string
|
||||||
|
if user.IsStaff {
|
||||||
|
possibleJamSlugs = make([]string, 0, len(hmndata.AllJams))
|
||||||
|
for _, jam := range hmndata.AllJams {
|
||||||
|
possibleJamSlugs = append(possibleJamSlugs, jam.Slug)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
possibleJamSlugs, err = db.QueryScalar[string](ctx, tx,
|
||||||
|
`
|
||||||
|
SELECT jam_slug
|
||||||
|
FROM jam_project
|
||||||
|
WHERE project_id = $1
|
||||||
|
`,
|
||||||
|
payload.ProjectID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return oops.New(err, "Failed to fetch jam participation for project")
|
||||||
|
}
|
||||||
|
currentJam := hmndata.CurrentJam()
|
||||||
|
if currentJam != nil {
|
||||||
|
possibleJamSlugs = append(possibleJamSlugs, currentJam.Slug)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tx.Exec(ctx,
|
||||||
|
`
|
||||||
|
UPDATE jam_project
|
||||||
|
SET participating = FALSE
|
||||||
|
WHERE project_id = $1
|
||||||
|
`,
|
||||||
|
payload.ProjectID,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return oops.New(err, "Failed to remove jam participation for project")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, jamSlug := range payload.JamParticipationSlugs {
|
||||||
|
found := false
|
||||||
|
for _, possibleSlug := range possibleJamSlugs {
|
||||||
|
if possibleSlug == jamSlug {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
_, err = tx.Exec(ctx,
|
||||||
|
`
|
||||||
|
INSERT INTO jam_project (project_id, jam_slug, participating)
|
||||||
|
VALUES ($1, $2, $3)
|
||||||
|
ON CONFLICT (project_id, jam_slug) DO UPDATE SET
|
||||||
|
participating = EXCLUDED.participating
|
||||||
|
`,
|
||||||
|
payload.ProjectID,
|
||||||
|
jamSlug,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return oops.New(err, "Failed to insert/update jam participation for project")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,6 +168,8 @@ func NewWebsiteRoutes(longRequestContext context.Context, conn *pgxpool.Pool) ht
|
||||||
hmnOnly.GET(hmnurl.RegexWhenIsIt, WhenIsIt)
|
hmnOnly.GET(hmnurl.RegexWhenIsIt, WhenIsIt)
|
||||||
hmnOnly.GET(hmnurl.RegexJamIndex, JamIndex2022)
|
hmnOnly.GET(hmnurl.RegexJamIndex, JamIndex2022)
|
||||||
hmnOnly.GET(hmnurl.RegexJamIndex2021, JamIndex2021)
|
hmnOnly.GET(hmnurl.RegexJamIndex2021, JamIndex2021)
|
||||||
|
hmnOnly.GET(hmnurl.RegexJamIndex2022, JamIndex2022)
|
||||||
|
hmnOnly.GET(hmnurl.RegexJamFeed2022, JamFeed2022)
|
||||||
|
|
||||||
hmnOnly.GET(hmnurl.RegexOldHome, Index)
|
hmnOnly.GET(hmnurl.RegexOldHome, Index)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue